Image-EXIF-2.01/0000755000076500000000000000000011753244231012167 5ustar aaronwheelImage-EXIF-2.01/asahi.c0000644000076500000000000001262511753243142013426 0ustar aaronwheel/* * Copyright (c) 2004 Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: asahi.c,v 1.5 2004/12/23 20:38:52 ejohnst Exp $ */ /* * Exif tag definitions for Asahi Optical Co. (Pentax) maker notes. * Note that the format is similar to Casio's, though has byte order * weirdness like Fuji. * */ #include #include #include #include "makers.h" /* Quality. */ static struct descrip asahi_qual[] = { { 0, "Economy" }, { 1, "Fine" }, { 2, "Super Fine" }, { -1, "Unknown" }, }; /* Resolution. */ static struct descrip asahi_res[] = { { 0, "640x480" }, { 2, "1024x768" }, { 4, "1600x1200" }, { 22, "2304x1728" }, { -1, "Unknown" }, }; /* Focus mode. */ static struct descrip asahi_focus[] = { { 0, "Normal" }, { 1, "Macro" }, { 2, "Macro" }, { 3, "Infinity" }, { -1, "Unknown" }, }; /* White balance. */ static struct descrip asahi_whiteb[] = { { 0, "Auto" }, { 1, "Daylight" }, { 2, "Shade" }, { 3, "Fluorescent" }, { 4, "Tungsten" }, { 5, "Manual" }, { -1, "Unknown" }, }; /* Saturation, contrast, & sharpness. */ static struct descrip asahi_range[] = { { 0, "Soft" }, { 1, "Normal" }, { 2, "Hard" }, { 3, "Medium Soft" }, { 4, "Medium Hard" }, { -1, "Unknown" }, }; /* Maker note IFD tags. */ static struct exiftag asahi_tags[] = { { 0x0008, TIFF_SHORT, 1, ED_IMG, "AsahiQuality", "Quality Level", asahi_qual }, { 0x0009, TIFF_SHORT, 1, ED_VRB, "AsahiRes", "Recorded Pixels", asahi_res }, { 0x000d, TIFF_SHORT, 1, ED_IMG, "AsahiFocus", "Focusing Mode", asahi_focus }, { 0x0019, TIFF_SHORT, 1, ED_IMG, "AsahiWhiteB", "White Balance", asahi_whiteb }, { 0x001f, TIFF_SHORT, 1, ED_IMG, "AsahiSaturate", "Saturation", asahi_range }, { 0x0020, TIFF_SHORT, 1, ED_IMG, "AsahiContrast", "Contrast", asahi_range }, { 0x0021, TIFF_SHORT, 1, ED_IMG, "AsahiSharp", "Sharpness", asahi_range }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "AsahiUnknown", "Asahi Unknown", NULL }, }; /* * Process Asahi maker note tags. */ void asahi_prop(struct exifprop *prop, struct exiftags *t) { /* Override a couple of standard tags. */ switch (prop->tag) { case 0x0019: prop->override = EXIF_T_WHITEBAL; break; case 0x001f: prop->override = EXIF_T_SATURATION; break; case 0x0020: prop->override = EXIF_T_CONTRAST; break; case 0x0021: prop->override = EXIF_T_SHARPNESS; break; } } /* * Try to read an Asahi maker note IFD. */ struct ifd * asahi_ifd(u_int32_t offset, struct tiffmeta *md) { /* * It appears that there are a couple of maker note schemes for * for Asahi cameras, most with a 6 byte offset. ("AOC" stands * for "Asahi Optical Co.") */ if (!memcmp("AOC\0", md->btiff + offset, 4)) { /* * If the prefix includes two spaces, fix at big-endian. * E.g., Optio 230, 330GS, 33L. */ if (!memcmp(" ", md->btiff + offset + 4, 2)) { md->order = BIG; return (readifds(offset + 6, asahi_tags, md)); } /* * With two zero bytes, try file byte order (?). * E.g., Optio 330RS, 33WR, 430RS, 450, 550, 555, S, S4. */ if (!memcmp("\0\0", md->btiff + offset + 4, 2)) return (readifds(offset + 6, asahi_tags, md)); /* * Two M's seems to be a different tag set we don't grok. * E.g., *ist D. */ if (!memcmp("MM", md->btiff + offset + 4, 2)) { exifwarn("Asahi maker note version not supported"); return (NULL); } exifwarn("Asahi maker note version not supported"); return (NULL); } /* * The EI-200 seems to have a non-IFD note; we'll use the heuristic * of a minimum 10 tags before we look at it as an IFD. */ if (exif2byte(md->btiff + offset, md->order) < 10) { exifwarn("Asahi maker note version not supported"); return (NULL); } /* E.g., Optio 330, 430. */ md->order = BIG; return (readifds(offset, asahi_tags, md)); } Image-EXIF-2.01/canon.c0000644000076500000000000011226511753243142013440 0ustar aaronwheel/* * Copyright (c) 2001-2007, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: canon.c,v 1.54 2007/12/16 03:06:13 ejohnst Exp $ */ /* * Exif tag definitions for Canon maker notes. * Developed from http://www.burren.cx/david/canon.html. * EOS 1D and 1Ds contributions from Stan Jirman . * EOS 10D contributions from Jason Montojo . * EOS 20D contributions from Per Kristian Hove . * EOS 5D contributions from Albert Max Lai . * */ #include #include #include #include #include "makers.h" /* * Calculate and format an exposure value ("-n.nn EV"). */ static float calcev(char *c, int l, int16_t v) { #if 0 /* Adjustment seems silly. If someone complains, I'll reconsider. */ int16_t n; /* * XXX 1/3 and 2/3 values seem to be a bit off. This makes a * slight adjustment; may want to revisit. */ n = (abs(v) - 32) * (v & 0x8000 ? -1 : 1); if (n == 20 || n == -12) v++; else if (n == -20 || n == 12) v--; #endif if (c) snprintf(c, l, "%.2f EV", (float)v / 32); return ((float)v / 32); } /* Macro mode. */ static struct descrip canon_macro[] = { { 1, "Macro" }, { 2, "Normal" }, { -1, "Unknown" }, }; /* Focus type. */ static struct descrip canon_focustype[] = { { 0, "Manual" }, { 1, "Auto" }, { 2, "Auto" }, { 3, "Close-Up (Macro Mode)" }, { 7, "Infinity Mode" }, { 8, "Locked (Pan Mode)" }, { -1, "Unknown" }, }; /* Quality. */ static struct descrip canon_quality[] = { { 2, "Normal" }, { 3, "Fine" }, { 5, "Superfine" }, { -1, "Unknown" }, }; /* Flash mode. */ static struct descrip canon_flash[] = { { 0, "Off" }, { 1, "Auto" }, { 2, "On" }, { 3, "Red-Eye Reduction" }, { 4, "Slow-Synchro" }, { 5, "Red-Eye Reduction (Auto)" }, { 6, "Red-Eye Reduction (On)" }, { 16, "External Flash" }, { -1, "Unknown" }, }; /* Drive mode. */ static struct descrip canon_drive[] = { { 0, "Single" }, /* "Timed" when field 2 is > 0. */ { 1, "Continuous" }, { -1, "Unknown" }, }; /* Focus mode. */ static struct descrip canon_focus1[] = { { 0, "One-Shot" }, { 1, "AI Servo" }, { 2, "AI Focus" }, { 3, "Manual" }, { 4, "Single" }, { 5, "Continuous" }, { 6, "Manual" }, { -1, "Unknown" }, }; /* Image size. */ static struct descrip canon_imagesz[] = { { 0, "Large" }, { 1, "Medium" }, { 2, "Small" }, { -1, "Unknown" }, }; /* Shooting mode. */ static struct descrip canon_shoot[] = { { 0, "Full Auto" }, { 1, "Manual" }, { 2, "Landscape" }, { 3, "Fast Shutter" }, { 4, "Slow Shutter" }, { 5, "Night" }, { 6, "Black & White" }, { 7, "Sepia" }, { 8, "Portrait" }, { 9, "Sports" }, { 10, "Macro/Close-Up" }, { 11, "Pan Focus" }, { 19, "Indoor" }, { 22, "Underwater" }, { 24, "Kids & Pets" }, { 25, "Night Snapshot" }, { -1, "Unknown" }, }; /* Digital zoom. */ static struct descrip canon_dzoom[] = { { 0, "None" }, { 1, "x2" }, { 2, "x4" }, { -1, "Unknown" }, }; /* Contrast, saturation, & sharpness. */ static struct descrip canon_range[] = { { 0, "Normal" }, { 1, "High" }, { 0xffff, "Low" }, { -1, "Unknown" }, }; /* ISO speed rating. */ static struct descrip canon_iso[] = { { 15, "Auto" }, { 16, "50" }, { 17, "100" }, { 18, "200" }, { 19, "400" }, { -1, "Unknown" }, }; /* Metering mode. */ static struct descrip canon_meter[] = { { 0, "Default" }, { 1, "Spot" }, { 3, "Evaluative" }, { 4, "Partial" }, { 5, "Center-Weighted" }, { -1, "Unknown" }, }; /* Exposure mode. */ static struct descrip canon_expmode[] = { { 0, "Easy Shooting" }, { 1, "Program" }, { 2, "Tv-Priority" }, { 3, "Av-Priority" }, { 4, "Manual" }, { 5, "A-DEP" }, { 6, "DEP" }, { -1, "Unknown" }, }; /* White balance. */ static struct descrip canon_whitebal[] = { { 0, "Auto" }, { 1, "Daylight" }, { 2, "Cloudy" }, { 3, "Tungsten" }, { 4, "Fluorescent" }, { 5, "Flash" }, { 6, "Custom" }, { 7, "Black & White" }, { 8, "Shade" }, { 9, "Manual Temperature" }, { 14, "Daylight Fluorescent" }, { 15, "Custom 1" }, { 16, "Custom 2" }, { 17, "Underwater" }, { -1, "Unknown" }, }; /* Maker note IFD tags. */ static struct exiftag canon_tags[] = { { 0x0001, TIFF_SHORT, 0, ED_UNK, "Canon1Tag", "Canon Tag1 Offset", NULL }, { 0x0004, TIFF_SHORT, 0, ED_UNK, "Canon4Tag", "Canon Tag4 Offset", NULL }, { 0x0006, TIFF_ASCII, 32, ED_VRB, "ImageType", "Image Type", NULL }, { 0x0007, TIFF_ASCII, 24, ED_CAM, "FirmwareVer", "Firmware Version", NULL }, { 0x0008, TIFF_LONG, 1, ED_IMG, "ImgNum", "Image Number", NULL }, { 0x0009, TIFF_ASCII, 32, ED_CAM, "OwnerName", "Owner Name", NULL }, { 0x000c, TIFF_LONG, 1, ED_CAM, "Serial", "Serial Number", NULL }, { 0x000f, TIFF_SHORT, 0, ED_UNK, "CustomFunc", "Custom Function", NULL }, { 0x0090, TIFF_SHORT, 0, ED_UNK, "CustomFunc", "Custom Function", NULL }, { 0x0093, TIFF_SHORT, 0, ED_UNK, "Canon93Tag", "Canon Tag93 Offset", NULL }, { 0x0095, TIFF_ASCII, 64, ED_PAS, "LensName", "Lens Name", NULL }, { 0x00a0, TIFF_SHORT, 0, ED_UNK, "CanonA0Tag", "Canon TagA0 Offset", NULL }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "CanonUnknown", "Canon Unknown", NULL }, }; /* Fields under tag 0x0001 (camera settings). */ static struct exiftag canon_tags01[] = { { 0, TIFF_SHORT, 0, ED_VRB, "Canon1Len", "Canon Tag1 Length", NULL }, { 1, TIFF_SHORT, 0, ED_IMG, "CanonMacroMode", "Macro Mode", canon_macro }, { 2, TIFF_SHORT, 0, ED_VRB, "CanonTimerLen", "Self-Timer Length", NULL }, { 3, TIFF_SHORT, 0, ED_IMG, "CanonQuality", "Compression Setting", canon_quality }, { 4, TIFF_SHORT, 0, ED_IMG, "CanonFlashMode", "Flash Mode", canon_flash }, { 5, TIFF_SHORT, 0, ED_IMG, "CanonDriveMode", "Drive Mode", canon_drive }, { 7, TIFF_SHORT, 0, ED_IMG, "CanonFocusMode", "Focus Mode", canon_focus1 }, { 10, TIFF_SHORT, 0, ED_IMG, "CanonImageSize", "Image Size", canon_imagesz }, { 11, TIFF_SHORT, 0, ED_IMG, "CanonShootMode", "Shooting Mode", canon_shoot }, { 12, TIFF_SHORT, 0, ED_VRB, "CanonDigiZoom", "Digital Zoom", NULL }, { 13, TIFF_SHORT, 0, ED_IMG, "CanonContrast", "Contrast", canon_range }, { 14, TIFF_SHORT, 0, ED_IMG, "CanonSaturate", "Saturation", canon_range }, { 15, TIFF_SHORT, 0, ED_IMG, "CanonSharpness", "Sharpness", canon_range }, { 16, TIFF_SHORT, 0, ED_IMG, "CanonISO", "ISO Speed Rating", canon_iso }, { 17, TIFF_SHORT, 0, ED_IMG, "CanonMeterMode", "Metering Mode", canon_meter }, { 18, TIFF_SHORT, 0, ED_IMG, "CanonFocusType", "Focus Type", canon_focustype }, { 19, TIFF_SHORT, 0, ED_UNK, "CanonAFPoint", "Autofocus Point", NULL }, { 20, TIFF_SHORT, 0, ED_IMG, "CanonExpMode", "Exposure Mode", canon_expmode }, { 23, TIFF_SHORT, 0, ED_UNK, "CanonMaxFocal", "Max Focal Length", NULL }, { 24, TIFF_SHORT, 0, ED_UNK, "CanonMinFocal", "Min Focal Length", NULL }, { 25, TIFF_SHORT, 0, ED_UNK, "CanonFocalUnits", "Focal Units/mm", NULL }, { 28, TIFF_SHORT, 0, ED_UNK, "CanonFlashAct", "Flash Activity", NULL }, { 29, TIFF_SHORT, 0, ED_UNK, "CanonFlashDet", "Flash Details", NULL }, { 36, TIFF_SHORT, 0, ED_VRB, "CanonDZoomRes", "Zoomed Resolution", NULL }, { 37, TIFF_SHORT, 0, ED_VRB, "CanonBZoomRes", "Base Zoom Resolution", NULL }, { 0xffff, TIFF_SHORT, 0, ED_UNK, "Canon01Unknown", "Canon Tag1 Unknown", NULL }, }; /* Fields under tag 0x0004 (shot info). */ static struct exiftag canon_tags04[] = { { 0, TIFF_SHORT, 0, ED_VRB, "Canon4Len", "Canon Tag4 Length", NULL }, { 2, TIFF_SHORT, 0, ED_IMG, "CanonSensorSpeed", "Sensor ISO Speed", NULL }, { 6, TIFF_SHORT, 0, ED_IMG, "CanonExpComp", "Exposure Compensation", NULL }, { 7, TIFF_SHORT, 0, ED_IMG, "CanonWhiteB", "White Balance", canon_whitebal }, { 9, TIFF_SHORT, 0, ED_IMG, "CanonSequence", "Sequence Number", NULL }, { 14, TIFF_SHORT, 0, ED_UNK, "CanonAFPoint2", "Autofocus Point", NULL }, { 15, TIFF_SHORT, 0, ED_IMG, "CanonFlashBias", "Flash Bias", NULL }, { 19, TIFF_SHORT, 0, ED_IMG, "CanonSubjDst", "Subject Distance", NULL }, { 0xffff, TIFF_SHORT, 0, ED_UNK, "Canon04Unknown", "Canon Tag4 Unknown", NULL }, }; /* Fields under tag 0x00a0 (EOS 1D, 1Ds). */ static struct exiftag canon_tagsA0[] = { { 0, TIFF_SHORT, 0, ED_VRB, "CanonA0Len", "Canon TagA0 Length", NULL }, { 9, TIFF_SHORT, 0, ED_IMG, "CanonColorTemp", "Color Temperature", NULL }, { 10, TIFF_SHORT, 0, ED_IMG, "CanonColorMatrix", "Color Matrix", NULL }, { 0xffff, TIFF_SHORT, 0, ED_UNK, "CanonA0Unknown", "Canon TagA0 Unknown", NULL }, }; /* Fields under tag 0x0093 (counter on EOS 1D, 1Ds). */ static struct exiftag canon_tags93[] = { { 0, TIFF_SHORT, 0, ED_VRB, "Canon93Len", "Canon Tag93 Length", NULL }, { 1, TIFF_SHORT, 0, ED_VRB, "CanonActuateMult", "Actuation Multiplier", NULL }, { 2, TIFF_SHORT, 0, ED_VRB, "CanonActuateCount", "Actuation Counter", NULL }, { 0xffff, TIFF_SHORT, 0, ED_UNK, "Canon93Unknown", "Canon Tag93 Unknown", NULL }, }; /* Placeholder for unknown fields. */ static struct exiftag canon_tagsunk[] = { { 0xffff, TIFF_SHORT, 0, ED_UNK, "CanonUnknown", "Canon Unknown", NULL }, }; /* Value descriptions for custom functions. */ static struct descrip ccstm_offon[] = { { 0, "Off" }, { 1, "On" }, { -1, "Unknown" }, }; static struct descrip ccstm_shutter[] = { { 0, "AF/AE Lock" }, { 1, "AE Lock/AF" }, { 2, "AF/AF Lock" }, { 3, "AE+Release/AE+AF" }, { -1, "Unknown" }, }; static struct descrip ccstm_disen[] = { { 0, "Disabled" }, { 1, "Enabled" }, { -1, "Unknown" }, }; static struct descrip ccstm_explvl[] = { { 0, "1/2 Stop" }, { 1, "1/3 Stop" }, { -1, "Unknown" }, }; static struct descrip ccstm_autooff[] = { { 0, "Auto" }, { 1, "Off" }, { -1, "Unknown" }, }; static struct descrip ccstm_shutspd[] = { { 0, "Auto" }, { 1, "1/200 (Fixed)" }, { -1, "Unknown" }, }; static struct descrip ccstm_aebseq[] = { { 0, "0,-,+/Enabled" }, { 1, "0,-,+/Disabled" }, { 2, "-,0,+/Enabled" }, { 3, "-,0,+/Disabled" }, { -1, "Unknown" }, }; static struct descrip ccstm_shutsync[] = { { 0, "1st-Curtain Sync" }, { 1, "2nd-Curtain Sync" }, { -1, "Unknown" }, }; static struct descrip ccstm_lensaf[] = { { 0, "AF Stop" }, { 1, "Operate AF" }, { 2, "Lock AE & Start Timer" }, { -1, "Unknown" }, }; static struct descrip ccstm_endis[] = { { 0, "Enabled" }, { 1, "Disabled" }, { -1, "Unknown" }, }; static struct descrip ccstm_menubut[] = { { 0, "Top" }, { 1, "Previous (Volatile)" }, { 2, "Previous" }, { -1, "Unknown" }, }; static struct descrip ccstm_setbut[] = { { 0, "Not Assigned" }, { 1, "Change Quality" }, { 2, "Change ISO Speed" }, { 3, "Select Parameters" }, { -1, "Unknown" }, }; static struct descrip ccstm_yesno[] = { { 0, "Yes" }, { 1, "No" }, { -1, "Unknown" }, }; static struct descrip ccstm_noyes[] = { { 0, "No" }, { 1, "Yes" }, { -1, "Unknown" }, }; static struct descrip ccstm_onoff[] = { { 0, "On" }, { 1, "Off" }, { -1, "Unknown" }, }; static struct descrip ccstm_afsel[] = { { 0, "H=AF+Main/V=AF+Command" }, { 1, "H=Comp+Main/V=Comp+Command" }, { 2, "H=Command Only/V=Assist+Main" }, { 3, "H=FEL+Main/V=FEL+Command" }, { -1, "Unknown" }, }; static struct descrip ccstm_afill[] = { { 0, "On" }, { 1, "Off" }, { 2, "On Without Dimming" }, { 3, "Brighter" }, { -1, "Unknown" }, }; static struct descrip ccstm_lcdpanels[] = { { 0, "Remain. Shots/File No." }, { 1, "ISO/Remain. Shots" }, { 2, "ISO/File No." }, { 3, "Shots In Folder/Remain. Shots" }, { -1, "Unknown" }, }; static struct descrip ccstm_usmmf[] = { { 0, "Turns On After One-Shot AF" }, { 1, "Turns Off After One-Shot AF" }, { 2, "Always Turned Off" }, { -1, "Unknown" }, }; static struct descrip ccstm_explvlinc[] = { { 0, "1/3-Stop Set, 1/3-Stop Comp" }, { 1, "1-Stop Set, 1/3-Stop Comp" }, { 2, "1/2-Stop Set, 1/2-Stop Comp" }, { -1, "Unknown" }, }; static struct descrip ccstm_tvavform[] = { { 0, "Tv=Main/Av=Control" }, { 1, "Tv=Control/Av=Main" }, { 2, "Tv=Main/Av=Main w/o Lens" }, { 3, "Tv=Control/Av=Main w/o Lens" }, { -1, "Unknown" }, }; static struct descrip ccstm_shutterael[] = { { 0, "AF/AE Lock Stop" }, { 1, "AE Lock/AF" }, { 2, "AF/AF Lock, No AE Lock" }, { 3, "AE/AF, No AE Lock" }, { -1, "Unknown" }, }; static struct descrip ccstm_afspot[] = { { 0, "45/Center AF Point" }, { 1, "11/Active AF Point" }, { 2, "11/Center AF Point" }, { 3, "9/Active AF Point" }, { -1, "Unknown" }, }; static struct descrip ccstm_afact[] = { { 0, "Single AF Point" }, { 1, "Expanded (TTL. of 7 AF Points)" }, { 2, "Automatic Expanded (Max. 13)" }, { -1, "Unknown" }, }; static struct descrip ccstm_regaf[] = { { 0, "Assist + AF" }, { 1, "Assist" }, { 2, "Only While Pressing Assist" }, { -1, "Unknown" }, }; static struct descrip ccstm_lensaf1[] = { { 0, "AF Stop" }, { 1, "AF Start" }, { 2, "AE Lock While Metering" }, { 3, "AF Point: M->Auto/Auto->Ctr" }, { 4, "AF Mode: ONESHOT<->SERVO" }, { 5, "IS Start" }, { -1, "Unknown" }, }; static struct descrip ccstm_aisens[] = { { 0, "Standard" }, { 1, "Slow" }, { 2, "Moderately Slow" }, { 3, "Moderately Fast" }, { 4, "Fast" }, { -1, "Unknown" }, }; static struct descrip ccstm_fscr[] = { { 0, "Ec-N, R" }, { 1, "Ec-A,B,C,CII,CIII,D,H,I,L" }, { -1, "Unknown" }, }; static struct descrip ccstm_10dsetbut[] = { { 0, "Not Assigned" }, { 1, "Change Quality" }, { 2, "Change Parameters" }, { 3, "Menu Display" }, { 4, "Image Replay" }, { -1, "Unknown" }, }; static struct descrip ccstm_10dshutter[] = { { 0, "AF/AE Lock" }, { 1, "AE Lock/AF" }, { 2, "AF/AF Lock, No AE Lock" }, { 3, "AE/AF, No AE Lock" }, { -1, "Unknown" }, }; static struct descrip ccstm_assistflash[] = { { 0, "Emits/Fires" }, { 1, "Does Not Emit/Fires" }, { 2, "Only Ext. Flash Emits/Fires" }, { 3, "Emits/Does Not Fire" }, { -1, "Unknown" }, }; static struct descrip ccstm_afptreg[] = { { 0, "Center" }, { 1, "Bottom" }, { 2, "Right" }, { 3, "Extreme Right" }, { 4, "Automatic" }, { 5, "Extreme Left" }, { 6, "Left" }, { 7, "Top" }, { -1, "Unknown" }, }; static struct descrip ccstm_rawjpeg[] = { { 0, "RAW+Small/Normal" }, { 1, "RAW+Small/Fine" }, { 2, "RAW+Medium/Normal" }, { 3, "RAW+Medium/Fine" }, { 4, "RAW+Large/Normal" }, { 5, "RAW+Large/Fine" }, { -1, "Unknown" }, }; static struct descrip ccstm_10dmenubut[] = { { 0, "Previous (Volatile)" }, { 1, "Previous" }, { 2, "Top" }, { -1, "Unknown" }, }; static struct descrip ccstm_assistbut[] = { { 0, "Normal" }, { 1, "Select Home Position" }, { 2, "Select HP (while pressing)" }, { 3, "Av+/- (AF point by QCD)" }, { 4, "FE lock" }, { -1, "Unknown" }, }; static struct descrip ccstm_20dexplvl[] = { { 0, "1/3 Stop" }, { 1, "1/2 Stop" }, { -1, "Unknown" }, }; static struct descrip ccstm_20dflashsync[] = { { 0, "Auto" }, { 1, "1/250 (Fixed)" }, { -1, "Unknown" }, }; static struct descrip ccstm_20dflash[] = { { 0, "Fires" }, { 1, "Does Not Fire" }, { -1, "Unknown" }, }; static struct descrip ccstm_20dafpsel[] = { { 0, "Normal" }, { 1, "Multi-Controller Direct" }, { 2, "Quick Control Dial Direct" }, { -1, "Unknown" }, }; static struct descrip ccstm_20dettl[] = { { 0, "Evaluative" }, { 1, "Average" }, { -1, "Unknown" }, }; static struct descrip ccstm_5dflashsync[] = { { 0, "Auto" }, { 1, "1/200 (Fixed)" }, { -1, "Unknown" }, }; static struct descrip ccstm_5dfscr[] = { { 0, "Ee-A" }, { 1, "Ee-D" }, { 2, "Ee-S" }, { -1, "Unknown" }, }; /* D30/D60 custom functions. */ static struct exiftag canon_d30custom[] = { { 1, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Long exposure noise reduction", ccstm_offon }, { 2, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Shutter/AE lock buttons", ccstm_shutter }, { 3, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Mirror lockup", ccstm_disen }, { 4, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Tv/Av and exposure level", ccstm_explvl }, { 5, TIFF_SHORT, 0, ED_VRB, "D30Custom", "AF-assist light", ccstm_autooff }, { 6, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Av mode shutter speed", ccstm_shutspd }, { 7, TIFF_SHORT, 0, ED_VRB, "D30Custom", "AEB sequence/auto cancellation", ccstm_aebseq }, { 8, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Shutter curtain sync", ccstm_shutsync }, { 9, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Lens AF stop button", ccstm_lensaf }, { 10, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Fill flash auto reduction", ccstm_endis }, { 11, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Menu button return position", ccstm_menubut }, { 12, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Shooting Set button function", ccstm_setbut }, { 13, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Sensor cleaning", ccstm_disen }, { 14, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Superimposed display", ccstm_onoff }, { 15, TIFF_SHORT, 0, ED_VRB, "D30Custom", "Shutter release w/o CF card", ccstm_yesno }, { 0xffff, TIFF_SHORT, 0, ED_UNK, "D30CustomUnknown", "Canon D30/D60 Custom Unknown", NULL }, }; /* EOS-1D/1Ds custom functions. */ static struct exiftag canon_1dcustom[] = { { 0, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Focusing screen", ccstm_fscr }, { 1, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Finder display during exposure", ccstm_offon }, { 2, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Shutter release w/o CF card", ccstm_yesno }, { 3, TIFF_SHORT, 0, ED_VRB, "1DCustom", "ISO speed expansion", ccstm_noyes }, { 4, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Shutter button/AEL button", ccstm_shutterael }, { 5, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Manual Tv/Av for M", ccstm_tvavform }, { 6, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Exposure level increments", ccstm_explvlinc }, { 7, TIFF_SHORT, 0, ED_VRB, "1DCustom", "USM lens electronic MF", ccstm_usmmf }, { 8, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Top/back LCD panels", ccstm_lcdpanels }, { 9, TIFF_SHORT, 0, ED_VRB, "1DCustom", "AEB sequence/auto cancellation", ccstm_aebseq }, { 10, TIFF_SHORT, 0, ED_VRB, "1DCustom", "AF point illumination", ccstm_afill }, { 11, TIFF_SHORT, 0, ED_VRB, "1DCustom", "AF point selection", ccstm_afsel }, { 12, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Mirror lockup", ccstm_disen }, { 13, TIFF_SHORT, 0, ED_VRB, "1DCustom", "# AF points/spot metering", ccstm_afspot }, { 14, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Fill flash auto reduction", ccstm_endis }, { 15, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Shutter curtain sync", ccstm_shutsync }, { 16, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Safety shift in Av or Tv", ccstm_disen }, { 17, TIFF_SHORT, 0, ED_VRB, "1DCustom", "AF point activation area", ccstm_afact }, { 18, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Switch to registered AF point", ccstm_regaf }, { 19, TIFF_SHORT, 0, ED_VRB, "1DCustom", "Lens AF stop button", ccstm_lensaf1 }, { 20, TIFF_SHORT, 0, ED_VRB, "1DCustom", "AI servo tracking sensitivity", ccstm_aisens }, { 0xffff, TIFF_SHORT, 0, ED_UNK, "1DCustomUnknown", "Canon 1D/1Ds Custom Unknown", NULL }, }; /* 5D custom functions. */ static struct exiftag canon_5dcustom[] = { { 0, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Focusing Screen", ccstm_5dfscr }, { 1, TIFF_SHORT, 0, ED_VRB, "5DCustom", "SET button function when shooting", ccstm_10dsetbut }, { 2, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Long exposure noise reduction", ccstm_offon }, { 3, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Flash sync speed in Av mode", ccstm_5dflashsync }, { 4, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Shutter button/AE lock button", ccstm_10dshutter }, { 5, TIFF_SHORT, 0, ED_VRB, "5DCustom", "AF-assist beam", ccstm_assistflash }, { 6, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Exposure level increments", ccstm_20dexplvl }, { 7, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Flash firing", ccstm_20dflash }, { 8, TIFF_SHORT, 0, ED_VRB, "5DCustom", "ISO expansion", ccstm_offon }, { 9, TIFF_SHORT, 0, ED_VRB, "5DCustom", "AEB sequence/auto cancellation", ccstm_aebseq }, { 10, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Superimposed display", ccstm_onoff }, { 11, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Menu button display position", ccstm_10dmenubut }, { 12, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Mirror lockup", ccstm_disen }, { 13, TIFF_SHORT, 0, ED_VRB, "5DCustom", "AF point selection method", ccstm_20dafpsel }, { 14, TIFF_SHORT, 0, ED_VRB, "5DCustom", "E-TTL II", ccstm_20dettl }, { 15, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Shutter curtain sync", ccstm_shutsync }, { 16, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Safety shift in Av or Tv", ccstm_disen }, { 17, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Lens AF stop button", ccstm_lensaf1 }, { 18, TIFF_SHORT, 0, ED_VRB, "5DCustom", "Add original decision data", ccstm_offon }, { 0xffff, TIFF_SHORT, 0, ED_UNK, "5DCustomUnknown", "Canon 5D Custom Unknown", NULL }, }; /* 10D custom functions. */ static struct exiftag canon_10dcustom[] = { { 1, TIFF_SHORT, 0, ED_VRB, "10DCustom", "SET button function when shooting", ccstm_10dsetbut }, { 2, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Shutter release w/o CF card", ccstm_yesno }, { 3, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Flash sync speed in Av mode", ccstm_shutspd }, { 4, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Shutter button/AE lock button", ccstm_10dshutter }, { 5, TIFF_SHORT, 0, ED_VRB, "10DCustom", "AF-assist beam/Flash firing", ccstm_assistflash }, { 6, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Exposure level increments", ccstm_explvl }, { 7, TIFF_SHORT, 0, ED_VRB, "10DCustom", "AF point registration", ccstm_afptreg }, { 8, TIFF_SHORT, 0, ED_VRB, "10DCustom", "RAW+JPEG recording", ccstm_rawjpeg }, { 9, TIFF_SHORT, 0, ED_VRB, "10DCustom", "AEB sequence/auto cancellation", ccstm_aebseq }, { 10, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Superimposed display", ccstm_onoff }, { 11, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Menu button display position", ccstm_10dmenubut }, { 12, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Mirror lockup", ccstm_disen }, { 13, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Assist button function", ccstm_assistbut }, { 14, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Fill flash auto reduction", ccstm_endis }, { 15, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Shutter curtain sync", ccstm_shutsync }, { 16, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Safety shift in Av or Tv", ccstm_disen }, { 17, TIFF_SHORT, 0, ED_VRB, "10DCustom", "Lens AF stop button", ccstm_lensaf }, { 0xffff, TIFF_SHORT, 0, ED_UNK, "10DCustomUnknown", "Canon 10D Custom Unknown", NULL }, }; /* 20D custom functions. */ static struct exiftag canon_20dcustom[] = { { 0, TIFF_SHORT, 0, ED_VRB, "20DCustom", "SET button function when shooting", ccstm_10dsetbut }, { 1, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Long exposure noise reduction", ccstm_offon }, { 2, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Flash sync speed in Av mode", ccstm_20dflashsync }, { 3, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Shutter button/AE lock button", ccstm_10dshutter }, { 4, TIFF_SHORT, 0, ED_VRB, "20DCustom", "AF-assist beam", ccstm_assistflash }, { 5, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Exposure level increments", ccstm_20dexplvl }, { 6, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Flash firing", ccstm_20dflash }, { 7, TIFF_SHORT, 0, ED_VRB, "20DCustom", "ISO expansion", ccstm_offon }, { 8, TIFF_SHORT, 0, ED_VRB, "20DCustom", "AEB sequence/auto cancellation", ccstm_aebseq }, { 9, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Superimposed display", ccstm_onoff }, { 10, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Menu button display position", ccstm_10dmenubut }, { 11, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Mirror lockup", ccstm_disen }, { 12, TIFF_SHORT, 0, ED_VRB, "20DCustom", "AF point selection method", ccstm_20dafpsel }, { 13, TIFF_SHORT, 0, ED_VRB, "20DCustom", "E-TTL II", ccstm_20dettl }, { 14, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Shutter curtain sync", ccstm_shutsync }, { 15, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Safety shift in Av or Tv", ccstm_disen }, { 16, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Lens AF stop button", ccstm_lensaf1 }, { 17, TIFF_SHORT, 0, ED_VRB, "20DCustom", "Add original decision data", ccstm_offon }, { 0xffff, TIFF_SHORT, 0, ED_UNK, "20DCustomUnknown", "Canon 20D Custom Unknown", NULL }, }; /* * Process maker note tag 0x0001 values. */ static int canon_prop01(struct exifprop *aprop, struct exifprop *prop, unsigned char *off, struct exiftags *t) { u_int16_t v = (u_int16_t)aprop->value; switch (aprop->tag) { case 2: aprop->lvl = v ? ED_IMG : ED_VRB; exifstralloc(&aprop->str, 32); snprintf(aprop->str, 31, "%d sec", v / 10); break; case 5: /* Change "Single" to "Timed" if #2 > 0. */ if (!v && exif2byte(off + 2 * 2, t->mkrmd.order)) strcpy(aprop->str, "Timed"); break; case 12: aprop->lvl = v ? ED_IMG : ED_VRB; /* * Looks like we can calculate zoom level when value * is 3 (ref S110). Calculation is (2 * #37 / #36). */ if (v == 3 && prop->count >= 37) { exifstralloc(&aprop->str, 32); snprintf(aprop->str, 31, "x%.1f", 2 * (float)exif2byte(off + 37 * 2, t->mkrmd.order) / (float)exif2byte(off + 36 * 2, t->mkrmd.order)); } else aprop->str = finddescr(canon_dzoom, v); break; case 16: /* ISO overrides standard one if known. */ if (!strcmp(aprop->str, "Unknown")) { aprop->lvl = ED_VRB; break; } aprop->override = EXIF_T_ISOSPEED; break; case 17: /* Maker meter mode overrides standard one if known. */ if (!strcmp(aprop->str, "Unknown")) { aprop->lvl = ED_VRB; break; } aprop->override = EXIF_T_METERMODE; break; case 20: /* With "Easy Shooting", shooting mode is all that matters. */ aprop->lvl = v ? ED_IMG : ED_VRB; break; default: return (FALSE); } return (TRUE); } /* * Process maker note tag 0x0004 values. */ static int canon_prop04(struct exifprop *aprop, struct exifprop *prop, unsigned char *off, struct exiftags *t) { struct exifprop *tmpprop; u_int16_t v = (u_int16_t)aprop->value; int d; switch (aprop->tag) { case 6: /* Calculate sensor speed (ISO units). */ exifstralloc(&aprop->str, 32); snprintf(aprop->str, 31, "%d", (int)(exp(calcev(NULL, 0, v) * log(2)) * 100.0 / 32.0 + 0.5)); break; case 7: aprop->override = EXIF_T_WHITEBAL; break; case 9: aprop->lvl = v ? ED_IMG : ED_VRB; break; case 15: exifstralloc(&aprop->str, 16); if (calcev(aprop->str, 15, v) == 0.0) aprop->lvl = ED_VRB; break; /* * Sigh. Some cameras have a standard Exif subject distance tag, * some do not. Some express this in mm, some in cm. (I cannot * for the life of me figure out how to tell what the units are.) * It looks like maybe some of the newer models stick to cm; we'll * assume cm and consider mm by exception. In any case, we'll only * display the value in the absence of the standard Exif value. * Needless to say, this is pretty ugly. */ case 19: exifstralloc(&aprop->str, 32); if (!v) { aprop->lvl = ED_VRB; strcpy(aprop->str, "Unknown"); break; } if (t->model && (!strcmp(t->model, "Canon PowerShot A10") || !strcmp(t->model, "Canon PowerShot S110") || !strcmp(t->model, "Canon PowerShot S30") || !strcmp(t->model, "Canon PowerShot S40") || !strcmp(t->model, "Canon EOS 10D"))) d = 1000; else d = 100; if (v == 0xffff) strcpy(aprop->str, "Infinity"); else snprintf(aprop->str, 31, "%.3f m", (float)v / (float)d); if ((tmpprop = findprop(t->props, tags, EXIF_T_DISTANCE))) { if (strcmp(tmpprop->str, "Unknown")) aprop->lvl = ED_VRB; else aprop->override = EXIF_T_DISTANCE; } break; default: return (FALSE); } return (TRUE); } /* * Process maker note tag 0x00a0 values. */ static int canon_propA0(struct exifprop *aprop, struct exifprop *prop, unsigned char *off, struct exiftags *t) { switch (aprop->tag) { case 9: exifstralloc(&aprop->str, 32); snprintf(aprop->str, 31, "%d K", aprop->value); break; default: return (FALSE); } return (TRUE); } /* * Common function for a tag's child values. Pass in the list of tags * and a function to process them. */ static int canon_subval(struct exifprop *prop, struct exiftags *t, struct exiftag *subtags, int (*valfun)()) { int i, j; u_int16_t v; struct exifprop *aprop; unsigned char *off = t->mkrmd.btiff + prop->value; /* Check size of tag (first value) if we're not debugging. */ if (valfun && exif2byte(off, t->mkrmd.order) != 2 * prop->count) { exifwarn("Canon maker tag appears corrupt"); return (FALSE); } if (debug) printf("Processing %s (0x%04X) directory, %d entries\n", prop->name, prop->tag, prop->count); for (i = 0; i < (int)prop->count; i++) { v = exif2byte(off + i * 2, t->mkrmd.order); aprop = childprop(prop); aprop->value = (u_int32_t)v; aprop->tag = i; aprop->tagset = subtags; /* Lookup property name and description. */ for (j = 0; subtags[j].tag < EXIF_T_UNKNOWN && subtags[j].tag != i; j++); aprop->name = subtags[j].name; aprop->descr = subtags[j].descr; aprop->lvl = subtags[j].lvl; if (subtags[j].table) aprop->str = finddescr(subtags[j].table, v); dumpprop(aprop, NULL); /* Process individual values. Returns false if unknown. */ if (valfun && !valfun(aprop, prop, off, t)) { if (aprop->lvl != ED_UNK) continue; exifstralloc(&aprop->str, 32); snprintf(aprop->str, 31, "num %02d, val 0x%04X", i, v); } } if (debug) printf("\n"); return (TRUE); } /* * Process custom function tag values. */ static void canon_custom(struct exifprop *prop, unsigned char *off, enum byteorder o, struct exiftag *table) { int i, j = -1; const char *cn; char *cv = NULL; u_int16_t v; struct exifprop *aprop; /* * Check size of tag (first value). * XXX There seems to be a problem with the D60 where it reports the * wrong size, hence the 2nd clause in the if(). Could be related * to the second value being zero? */ if (exif2byte(off, o) != 2 * prop->count && exif2byte(off, o) != 2 * (prop->count - 1)) { exifwarn("Canon custom tag appears corrupt"); return; } if (debug) printf("Processing %s directory, %d entries\n", prop->name, prop->count); for (i = 1; i < (int)prop->count; i++) { v = exif2byte(off + i * 2, o); aprop = childprop(prop); aprop->value = v & 0xff; aprop->tag = v >> 8 & 0xff; aprop->tagset = table; /* * Lookup function name and value. First byte is function * number; second is function value. */ for (j = 0; table[j].tag != EXIF_T_UNKNOWN && table[j].tag != (v >> 8 & 0xff); j++); aprop->name = table[j].name; aprop->descr = prop->descr; aprop->lvl = table[j].lvl; if (table[j].table) cv = finddescr(table[j].table, (u_int16_t)(v & 0xff)); cn = table[j].descr; dumpprop(aprop, NULL); exifstralloc(&aprop->str, 4 + strlen(cn) + (cv ? strlen(cv) : 10)); if (cv && j != -1) { snprintf(aprop->str, 4 + strlen(cn) + strlen(cv), "%s - %s", cn, cv); free(cv); cv = NULL; } else { snprintf(aprop->str, 4 + strlen(cn) + 10, "%s %d - %d", cn, v >> 8 & 0xff, v & 0xff); aprop->str[3 + strlen(cn) + 10] = '\0'; aprop->lvl = ED_UNK; } } if (debug) printf("\n"); } /* * Process Canon maker note tags. */ void canon_prop(struct exifprop *prop, struct exiftags *t) { unsigned char *offset; u_int16_t flmin = 0, flmax = 0, flunit = 0; u_int32_t v, w; struct exifprop *tmpprop; switch (prop->tag) { /* Various image data. */ case 0x0001: if (!canon_subval(prop, t, canon_tags01, canon_prop01)) break; /* * Create a new value for the lens' focal length range. If * it's not a zoom lens, we'll make it verbose (it should * match the existing focal length Exif tag). */ if (prop->count >= 25) { offset = t->mkrmd.btiff + prop->value; flmax = exif2byte(offset + 23 * 2, t->mkrmd.order); flmin = exif2byte(offset + 24 * 2, t->mkrmd.order); flunit = exif2byte(offset + 25 * 2, t->mkrmd.order); } if (flunit && (flmin || flmax)) { tmpprop = childprop(prop); tmpprop->name = "CanonLensSz"; tmpprop->descr = "Lens Size"; exifstralloc(&tmpprop->str, 32); if (flmin == flmax) { snprintf(tmpprop->str, 31, "%.2f mm", (float)flmax / (float)flunit); tmpprop->lvl = ED_VRB; } else { snprintf(tmpprop->str, 31, "%.2f - %.2f mm", (float)flmin / (float)flunit, (float)flmax / (float)flunit); tmpprop->lvl = ED_PAS; } } break; case 0x0004: canon_subval(prop, t, canon_tags04, canon_prop04); break; case 0x00a0: if (!canon_subval(prop, t, canon_tagsA0, canon_propA0)) break; /* Color temp is bad if white balance isn't manual. */ if ((tmpprop = findprop(t->props, canon_tags04, 7))) if (tmpprop->value != 9) { if ((tmpprop = findprop(prop, canon_tagsA0, 9))) tmpprop->lvl = ED_BAD; } break; /* Number of actuations. */ case 0x0093: /* * Alas, meanings of these fields seem to differ according * to camera model. For the 1D, 1Ds, and 1D2, they are total * number of actuations. For the 20D, they're the image * number. For now, we'll make the former behavior default * and the latter an exception. */ if (!t->model) { exifwarn("Canon model unset; please report to author"); break; } if (!canon_subval(prop, t, canon_tags93, NULL)) break; v = 0; if (strstr(t->model, "20D")) { /* Image number is in two shorts... */ if ((tmpprop = findprop(t->props, canon_tags93, 1))) { v = tmpprop->value >> 6; w = (tmpprop->value & 0x3f) << 8; if ((tmpprop = findprop(prop, canon_tags93, 2))) w += tmpprop->value; else { v = 0; w = 0; } } if (v) { tmpprop = childprop(prop); tmpprop->name = "ImgNum"; tmpprop->descr = "Image Number"; tmpprop->lvl = ED_IMG; exifstralloc(&tmpprop->str, 32); snprintf(tmpprop->str, 31, "%03d-%04d", v, w); } break; } /* Number of acuations is in two shorts... */ if ((tmpprop = findprop(t->props, canon_tags93, 1))) { v = tmpprop->value * 65536; if ((tmpprop = findprop(prop, canon_tags93, 2))) v += tmpprop->value; else v = 0; } if (v) { tmpprop = childprop(prop); tmpprop->name = "CanonActuations"; tmpprop->descr = "Camera Actuations"; tmpprop->lvl = ED_IMG; tmpprop->value = v; } break; /* Image number. */ case 0x0008: if (!prop->value) prop->lvl = ED_VRB; exifstralloc(&prop->str, 32); snprintf(prop->str, 31, "%03d-%04d", prop->value / 10000, prop->value % 10000); break; /* Serial number. */ case 0x000c: exifstralloc(&prop->str, 11); snprintf(prop->str, 11, "%010d", prop->value); break; /* Custom functions. */ case 0x000f: /* * Canon annoyingly reuses this tag value for different sets * of custom functions (e.g., D30/60, 10D). Therefore, we * won't try to interpret them unless we know for sure that * the camera model is supported. */ if (!t->model) { exifwarn("Canon model unset; please report to author"); break; } if (strstr(t->model, "10D")) canon_custom(prop, t->mkrmd.btiff + prop->value, t->mkrmd.order, canon_10dcustom); else if (strstr(t->model, "D30") || strstr(t->model, "D60")) canon_custom(prop, t->mkrmd.btiff + prop->value, t->mkrmd.order, canon_d30custom); else if (strstr(t->model, "20D")) canon_custom(prop, t->mkrmd.btiff + prop->value, t->mkrmd.order, canon_20dcustom); else if (strstr(t->model, "5D")) canon_custom(prop, t->mkrmd.btiff + prop->value, t->mkrmd.order, canon_5dcustom); else exifwarn2("Custom function unsupported; please " "report to author", t->model); break; case 0x0090: canon_custom(prop, t->mkrmd.btiff + prop->value, t->mkrmd.order, canon_1dcustom); break; /* Dump debug for tags of type short w/count > 1. */ default: if (prop->type == TIFF_SHORT && prop->count > 1 && debug) canon_subval(prop, t, canon_tagsunk, NULL); break; } } /* * Try to read Canon maker note IFDs. */ struct ifd * canon_ifd(u_int32_t offset, struct tiffmeta *md) { return (readifds(offset, canon_tags, md)); } Image-EXIF-2.01/casio.c0000644000076500000000000001264011753243142013434 0ustar aaronwheel/* * Copyright (c) 2002, 2003, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: casio.c,v 1.11 2003/08/06 02:26:42 ejohnst Exp $ */ /* * Exif tag definitions for Casio maker notes. * */ #include #include #include #include "makers.h" /* Recording mode. */ static struct descrip casio_record[] = { { 1, "Single Shutter" }, { 7, "Panorama" }, { 10, "Night Scene" }, { 15, "Portrait" }, { 16, "Landscape" }, { -1, "Unknown" }, }; /* Quality. */ static struct descrip casio_qual[] = { { 1, "Economy" }, { 2, "Normal" }, { 3, "Fine" }, { -1, "Unknown" }, }; /* Focus mode. */ static struct descrip casio_focus[] = { { 2, "Macro" }, { 3, "Auto" }, { 4, "Manual" }, { 5, "Infinity" }, { -1, "Unknown" }, }; /* Flash mode. */ static struct descrip casio_flash[] = { { 1, "Auto" }, { 2, "On" }, { 4, "Off" }, { 5, "Red Eye Reduction" }, { -1, "Unknown" }, }; /* Flash intensity. */ static struct descrip casio_intense[] = { { 11, "Weak" }, { 13, "Normal" }, { 15, "Strong" }, { -1, "Unknown" }, }; /* White balance. */ static struct descrip casio_whiteb[] = { { 1, "Auto" }, { 2, "Tungsten" }, { 3, "Daylight" }, { 4, "Fluorescent" }, { 5, "Shade" }, { 129, "Manual" }, { -1, "Unknown" }, }; /* Sharpness. */ static struct descrip casio_sharp[] = { { 0, "Normal" }, { 1, "Soft" }, { 2, "Hard" }, { -1, "Unknown" }, }; /* Contrast & saturation. */ static struct descrip casio_range[] = { { 0, "Normal" }, { 1, "Low" }, { 2, "High" }, { -1, "Unknown" }, }; /* Sensitivity. */ static struct descrip casio_sensitive[] = { { 64, "Normal" }, { 80, "Normal" }, { 100, "High" }, { 125, "+1.0" }, { 244, "+3.0" }, { 250, "+2.0" }, { -1, "Unknown" }, }; /* Maker note IFD tags. */ static struct exiftag casio_tags0[] = { { 0x0001, TIFF_SHORT, 1, ED_IMG, "CasioRecord", "Recording Mode", casio_record }, { 0x0002, TIFF_SHORT, 1, ED_IMG, "CasioQuality", "Quality Setting", casio_qual }, { 0x0003, TIFF_SHORT, 1, ED_IMG, "CasioFocus", "Focusing Mode", casio_focus }, { 0x0004, TIFF_SHORT, 1, ED_IMG, "CasioFlash", "Flash Mode", casio_flash }, { 0x0005, TIFF_SHORT, 1, ED_IMG, "CasioIntensity", "Flash Intensity", casio_intense }, { 0x0006, TIFF_LONG, 1, ED_VRB, "CasioDistance", "Object Distance", NULL }, { 0x0007, TIFF_SHORT, 1, ED_IMG, "CasioWhiteB", "White Balance", casio_whiteb }, { 0x000a, TIFF_LONG, 1, ED_UNK, "CasioDZoom", "Digital Zoom", NULL }, { 0x000b, TIFF_SHORT, 1, ED_IMG, "CasioSharp", "Sharpness", casio_sharp }, { 0x000c, TIFF_SHORT, 1, ED_IMG, "CasioContrast", "Contrast", casio_range }, { 0x000d, TIFF_SHORT, 1, ED_IMG, "CasioSaturate", "Saturation", casio_range }, { 0x0014, TIFF_SHORT, 1, ED_IMG, "CasioSensitive", "Sensitivity", casio_sensitive }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "CasioUnknown", "Casio Unknown", NULL }, }; static struct exiftag casio_tags1[] = { { 0x2001, TIFF_ASCII, 1, ED_UNK, "CasioASCII1", "Casio ASCII Val 1", NULL }, { 0x2002, TIFF_ASCII, 1, ED_UNK, "CasioASCII2", "Casio ASCII Val 2", NULL }, { 0x3006, TIFF_ASCII, 1, ED_UNK, "CasioASCII3", "Casio ASCII Val 3", NULL }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "CasioUnknown", "Casio Unknown", NULL }, }; /* * Try to read a Casio maker note IFD. */ struct ifd * casio_ifd(u_int32_t offset, struct tiffmeta *md) { struct ifd *myifd; /* * It appears that there are two different types of maker notes * for Casio cameras: one, for older cameras, uses a standard IFD * format; the other starts at offset + 6 ("QVC\0\0\0"). */ if (!memcmp("QVC\0\0\0", md->btiff + offset, 6)) { readifd(offset + strlen("QVC") + 3, &myifd, casio_tags1, md); exifwarn("Casio maker note version not supported"); } else readifd(offset, &myifd, casio_tags0, md); return (myifd); } Image-EXIF-2.01/Changes0000644000076500000000000001021611753243311013460 0ustar aaronwheelRevision history for Perl extension Image::EXIF. 2.01 Fri May 11 18:04:11 BST 2012 - Fix building under Perl 5.8.8 (including Red Hat 5.6) 2.00 Sun May 6 16:22:04 BST 2012 - New maintainer Aaron Crane - New versioning scheme: don't encode exiftags version number in Perl module version - Upgrade embedded exiftags library to 1.01 - Require Perl 5.8 - Fix build on case-insensitive filesystems, as typically found under Mac OS, Windows, Cygwin, etc (RT#4353, RT#4973, RT#76281) - Fix broken dists (RT#4353, RT#32641) - Fix: allow multiple Image::EXIF objects to exist simultaneously - Fix: no more fixed-size buffers (and potential buffer overflows) - Use exceptions to report errors, not a mixture of exit() and return-value checking (RT#26094) 1.00.4 Thu Jul 14 15:03:03 MSD 2011 Fixed bugs:45085, 26094 Dmitry Kosenkov 1.00.3 Mod Apr 25 16:56 PST 2005 Mr Eric Johnston released new version of his library which is 1.00. So did we! 99.4 Thu Aug 12 21:42 PST 2004 (-) Fix Martijn van de Streek found a bug and sent a patch. Below his note: >In the current version of Image::EXIF there's a bug: when reading a >non-EXIF JPEG file after reading an EXIF JPEG file, the module generates >a Segmentation Fault. > >The attached patch fixes this bug by re-setting the "et" to NULL after >exiffree()ing it. (-) Fix One more issue. If file which is kinda jpeg is a wrong one, then package gets stuck. Fixed 99.1 Fri May 21 14:40 PST 2004 Mr Eric Johnston released new version of his library which is 0.99.1 So did we! From now I'm gonna rename exif.c to _exif.c to allow compile and use this package for Win & Mac perl cookers. And just small note from Blair Zajac: >Hello, >I'm looking to use the Image::EXIF module and noticed that the >'unknown' hash key is actually spelled 'unknow'. Since all >occurrences of the word are misspelled in the package, is this >deliberate? >I'm attaching a patch to fix this and a couple of other spelling >mistakes. >Best, >Blair Thanks Blair for your note. Fixed. 98.6 Wed Jan 14 13:53:48 PST 2004 HONY (OldNewYear Crazy Russian Custom) * small change in EXIF.xs 78c78 < break; --- > ; - From Rolf Dignatz: using the original Image-EXIF-0.98.5: file: nikon0001.JPG rd debug: read_data: mark = 0xe1 (JPEG_M_APP1) rd debug: exifscan: header='Exif' rd debug: read_data: mark = 0xe1 (JPEG_M_APP1) rd debug: exifscan: header='http://ns.adobe.com/xap/1.0/' (null): couldn't find Exif data As you see in my first debug output there are two JPEG_M_APP1-marked sections in the nikon jpeg-file and only the first one is the 'real' EXIF section. So I decided to break after the first legal EXIF section. Another way might be to read all possibly EXIF sections and process them all? Similar is the original exiftags-0.98::exiftags.c::doit() (code in line ~ 182) which processes each JPEG_M_APP1-section which leads in a true expression * small fix in create_web_gallery.pl 98.5 Mon Jan 5 11:28:48 PST 2004 HNY * exifgps.c file was missing in package + also I added script create_web_galley.pl where you can see how I deal with the package 98.3 Mon Nov 10 11:28:48 PST 2003 * bugfix. EXIF got core dump if jpeg didn't have exif section. based on comment from Sebastien Gross (tnku) 0.02 Tue Aug 5 10:33:19 PST 2003 - original version; created by h2xs 1.21 with options -n Image::EXIF Image-EXIF-2.01/examples/0000755000076500000000000000000011753244231014005 5ustar aaronwheelImage-EXIF-2.01/examples/create_web_gallery.pl0000755000076500000000000002411311753243142020165 0ustar aaronwheel#!/usr/local/bin/perl -w # # author : sergey s prozhogin (ccpro@rrelaxo.org.ru) # script creates web gallery. # for information start perl create_web_gallery.pl --help # # v 1.3 May-20-2004 # use strict; use CGI qw(:standard :html3 -no_xhtml); use Getopt::Long; use GD; use Image::GD::Thumbnail; use Image::EXIF; use Data::Dumper; sub main( $ ); sub init( $ ); sub copy_images( $$ ); sub create_pages( $$ ); sub create_index( $$ ); sub create_thumbnails( $$ ); my %opt; print "create_web_galley.pl --help (v1.3): for help\n"; unless(GetOptions(\%opt, 'no_php', 'table_size=i', 'del_src', 'in_dir=s', 'out_dir=s', 'mask=s', 'thumb_size=i', 'exif', 'd=s') || exists($opt{help})){ print qq^ --no_php - remove php section and create html --table_size size - set number pictures in a table --del_src - remove graphics files after handling --in_dir - directory with graphics files --out_dir - directory for result --mask mask - mask for graphic files --thumb_size size - the size oh thumbnails --exif - build EXIF section --d "description" - Description for gallery\n^; exit(); } my $cfg = { in_dir => '.', out_dir => '.', mask => '\.jpg', thumb_size => 180, table_size => 5, style => 'Font-Size: 8pt; Font-Family: verdana,Arial; Font-Weight: bold;', php_db_connect => '"dbname=db_name user=user_name"', }; $cfg->{d} = undef; $cfg->{$_} = $opt{$_} foreach(keys %opt); init( $cfg ); main( $cfg ); sub main( $ ) { my $cfg = shift; opendir DIR, $cfg->{in_dir} or die "error open $cfg->{in_dir} directory\n"; my @jpeg = sort grep { /$cfg->{mask}$/i && -f "$cfg->{in_dir}/$_" } readdir(DIR); # print "$_\n" readdir(DIR); closedir DIR; print "found:\n@jpeg\n"; create_index( $cfg, \@jpeg ); create_pages( $cfg, \@jpeg ); copy_images( $cfg, \@jpeg ); create_thumbnails( $cfg, \@jpeg ); } sub init( $ ) { my $cfg = shift; # print "removed $cfg->{out_dir}\n"; # system( "rm -R $cfg->{out_dir}"); print "created $cfg->{out_dir}\n"; mkdir("$cfg->{out_dir}/", 0755); mkdir("$cfg->{out_dir}/thumbnails", 0755); mkdir("$cfg->{out_dir}/pages", 0755); mkdir("$cfg->{out_dir}/images", 0755); } sub copy_images( $$ ) { my $cfg = shift; my $list = shift; my $command = exists($cfg->{del_src}) ? 'mv' : 'cp'; foreach(@$list){ system("$command $cfg->{in_dir}/$_ $cfg->{out_dir}/images/"); print "image $_ copied\n"; } } sub create_pages( $$ ) { my $cfg = shift; my $list = shift; my @html; my $q = new CGI; my $style = $cfg->{style}; my $ext = exists($cfg->{no_php}) ? 'html' : 'php'; my $exif = new Image::EXIF; for( my $i=0; $i < @$list; $i ++ ){ @html = (); open FH, ">$cfg->{out_dir}/pages/$list->[$i].$ext" or die "can not create $cfg->{out_dir}/pages/$list->[$i].$ext\n"; my @lines = split("\n", start_html( -title=>($cfg->{d}||'')." $list->[$i]", -author=>'ccpro', -head => meta({ 'http-equiv' => 'Content-Type', 'content' => 'text/html', 'charset' => 'windows-1251', }), -bgcolor=>'#ffffff', -script=>qq^ showing = false; function toggleInfo() { if (showing == false) { if (document.all || document.getElementById) document.getElementById('imageinfo').style.visibility="visible"; // IE & Gecko else document.layers['imageinfo'].visibility="show"; // Netscape 4 showing = true; } else { if (document.all || document.getElementById) document.getElementById('imageinfo').style.visibility="hidden"; // IE & Gecko else document.layers['imageinfo'].visibility="hide"; // Netscape 4 showing = false; } } ^ )."\n" ); if (exists($cfg->{exif})){ print "EXIF table for $list->[$i]\n"; $exif->file_name($list->[$i]); my $data = $exif->get_all_info(); push @lines, "\n"; } print FH join("\n", @lines)."\n"; my $image_name = $list->[$i]; $image_name =~ s/(.*)\..*/$1/; exists($cfg->{no_php}) || print FH qq^ {php_db_connect})){ \$year = split('/', getenv('SCRIPT_NAME')); \$num = ereg_replace(".JPG.PHP", "", "$image_name"); \$result = pg_query ( \$dbh, "SELECT comment FROM photo_comments WHERE num='\$num' and year=\$year[2]"); if( \$result ){ \$res = pg_fetch_array(\$result); pg_free_result (\$result); echo "\$res[0]"; } pg_close(\$dbh); } ?> ^; push @html, td({-align=>'center', -valign=>'center', -colspan=>3},' ')."\n"; my $str = td({-align=>'center', -valign=>'center'}, font({-face=>'tacoma', -size=>'-1', -color=>'#000000'}, a({-href=>'../index.html', -style=>$style}, 'index') ) ); if (exists($cfg->{exif})){ $str .= td({-align=>'center', -valign=>'center'}, ' '. font({-face=>'tacoma', -size=>'-1', -color=>'#000000'}, a({-href=>'javascript:toggleInfo()', -style=>$style}, 'exif') ) ); } if( $i > 0 ){ $str = td({-align=>'center', -valign=>'center'}, font({-face=>'tacoma', -size=>'-1', -color=>'#000000'}, a({-href=>"./$list->[$i-1].$ext", -style=>$style},'prev'). '  ' ) ).$str; } if( ($i+1) < @$list ){ $str .= td({-align=>'center', -valign=>'center'}, font({-face=>'tacoma', -size=>'-1', -color=>'#000000'}, '  '. a({-href=>"./$list->[$i+1].$ext", -style=>$style}, 'next') ) ) } push @html, $str; # push @html, # td({-align=>'center', -valign=>'center', -colspan=>3}, # img({-src=>"../images/$list->[$i]"}) # )."\n"; print FH div({-align=>'center'}, $str. # table({-border=>0, -bgcolor=>'#ffffff'}, # Tr(\@html)).br."\n". table({-border=>0, -cellpadding=>8, -cellspacing=>8}, Tr([td({-align=>'center', -bgcolor=>'#EEEEEE'}, ($i+1) < @$list ? a({-href=>"./$list->[$i+1].$ext"}, img({-src=>"../images/$list->[$i]"}) ) : a({-href=>'../'}, img({-src=>"../images/$list->[$i]"}) ) )])) )."\n"; print FH end_html()."\n"; close FH; print "page $cfg->{out_dir}/pages/$list->[$i].$ext is created\n"; } } sub create_index( $$ ) { my $cfg = shift; my $list = shift; my @html; my $q = new CGI; my $style = $cfg->{style}; my $ext = exists($cfg->{no_php}) ? 'html' : 'php'; open INDEX, ">$cfg->{out_dir}/index.html" or die "can not open $cfg->{out_dir}/index.html\n"; print INDEX start_html( -title=>$cfg->{d}||'Title', -author=>'ccpro', -head => meta({ 'http-equiv' => 'Content-Type', 'content' => 'text/html', 'charset' => 'windows-1251', }) )."\n"; push @html, td({-align=>'left',-colspan=>$cfg->{table_size},-bgcolor=>'#ffffff'}, br.$cfg->{d}||'Description'.br.br)."\n", td({-align=>'center',-colspan=>$cfg->{table_size},-bgcolor=>'#ffffff'}, a({-href=>'/?photos=1', -style=>$style}, 'up') )."\n"; my $size = $cfg->{table_size}; for( my $i=0; $i< @$list; $i += $size ){ my $str = "\t"; for( my $j=0; $j < $size; $j++ ){ $str .= defined($list->[$i+$j])? td({-align=>'center', -valign=>'middle', -bgcolor=>'#eeeeee'}, CGI::center( a({-href=>"./pages/$list->[$i+$j].$ext"}, img({ -alt=>"./images/$list->[$i+$j]", -src=>"./thumbnails/$list->[$i+$j]", -border=>0 }), ) ) ): CGI::center(td(' ')); } push @html, $str."\n"; } print INDEX CGI::center(table({ -border=>0,-width=>$cfg->{thumb_size}*$size+8*$size, -cellpadding=>8, -cellspacing=>8}, Tr(\@html)))."\n"; print INDEX end_html()."\n"; close INDEX; print "index.html is created\n"; } sub create_thumbnails( $$ ) { my $cfg = shift; my $list = shift; foreach my $fname (@$list){ open IN, "$cfg->{in_dir}/images/$fname" or die "Could not open $fname."; my $srcImage = GD::Image->newFromJpeg(*IN); close IN; # Create the thumbnail from it, where the biggest side is 50 px my ($thumb, $x, $y) = Image::GD::Thumbnail::create($srcImage,$cfg->{thumb_size}); # Save your thumbnail open OUT, ">$cfg->{out_dir}/thumbnails/$fname" or die "Could not save $fname\n"; binmode OUT; print OUT $thumb->jpeg; close OUT; print "thumbnail $cfg->{out_dir}/thumbnail/$fname is created\n"; } } Image-EXIF-2.01/examples/rename.pl0000755000076500000000000000132211753243142015612 0ustar aaronwheel#!/usr/bin/perl -w # author : sergey s prozhogin (ccpro@rrelaxo.org.ru) # script renames file by EXIF date # for information start perl rename.pl # # v 1.3 May-20-2004 # use strict; use Image::EXIF; use Date::Parse; use Data::Dumper; my @list = `ls -1 *JPG *jpg *jpeg *JPEG`; my $exif = new Image::EXIF; for my $fname (@list) { chomp $fname; $exif->file_name($fname); my $data = $exif->get_all_info(); if ($data) { my $timestamp = $data->{image}->{'Image Created'} || $data->{other}->{'Image Generated'}; my $time = str2time($timestamp); $timestamp = sprintf "%x", $time; my $count = 0; while (-f "img_$timestamp$count.jpg") { $count ++; } rename $fname, "img_$timestamp$count.jpg"; } } Image-EXIF-2.01/examples/t.pl0000644000076500000000000000033711753243142014610 0ustar aaronwheel#!/usr/bin/perl -w use strict; use Image::EXIF; use Data::Dumper; my $exif = new Image::EXIF($ARGV[0] || "i424f2d1c0.jpg"); my $all_info = $exif->get_all_info(); print $exif->error ? $exif->errstr : Dumper($all_info); Image-EXIF-2.01/exif.c0000644000076500000000000005506011753243142013274 0ustar aaronwheel/* * Copyright (c) 2001-2007, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: exif.c,v 1.77 2007/12/16 00:25:08 ejohnst Exp $ */ /* * Exchangeable image file format (Exif) parser. * * Developed using the TIFF 6.0 specification: * (http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf) * and the EXIF 2.21 standard: (http://tsc.jeita.or.jp/avs/data/cp3451_1.pdf). * * Portions of this code were developed while referencing the public domain * 'Jhead' program (version 1.2) by Matthias Wandel . * */ #include #include #include #include #include #include #include #include "exif.h" #include "exifint.h" #include "makers.h" #define OLYMPUS_BUGS /* Work around Olympus stupidity. */ #define WINXP_BUGS /* Work around Windows XP stupidity. */ #define SIGMA_BUGS /* Work around Sigma stupidity. */ #define UNCREDITED_BUGS /* Work around uncredited stupidity. */ /* Function prototypes. */ static void parsetag(struct exifprop *prop, struct ifd *dir, struct exiftags *t, int domkr); /* * Create an Exif property from the raw IFD field data. */ static void readtag(struct field *afield, int ifdseq, struct ifd *dir, struct exiftags *t, int domkr) { int i, j; struct exifprop *prop, *tmpprop; u_int16_t tag; prop = newprop(); if (dir->par) tag = dir->par->tag; else tag = EXIF_T_UNKNOWN; /* Field info. */ prop->tag = exif2byte(afield->tag, dir->md.order); prop->type = exif2byte(afield->type, dir->md.order); prop->count = exif4byte(afield->count, dir->md.order); /* XXX Makes dealing with two shorts somewhat messy. */ if ((prop->type == TIFF_SHORT || prop->type == TIFF_SSHORT) && prop->count <= 1) prop->value = exif2byte(afield->value, dir->md.order); else prop->value = exif4byte(afield->value, dir->md.order); /* IFD identifying info. */ prop->ifdseq = ifdseq; prop->par = dir->par; prop->tagset = dir->tagset; /* Lookup the field name. */ for (i = 0; prop->tagset[i].tag < EXIF_T_UNKNOWN && prop->tagset[i].tag != prop->tag; i++); prop->name = prop->tagset[i].name; prop->descr = prop->tagset[i].descr; prop->lvl = prop->tagset[i].lvl; /* * Lookup and check the field type. * * We have to be pretty severe with entries that have an invalid * field type -- too many assumptions in the rest of the code. */ for (j = 0; ftypes[j].type && ftypes[j].type != prop->type; j++); if (!ftypes[j].type) { exifwarn2("unknown TIFF field type; discarding", prop->name); free(prop); return; } /* Skip sanity checking on maker note tags; we'll get to them later. */ if (tag != EXIF_T_MAKERNOTE) { /* * XXX Ignore UserComment -- a hack to get around an apparent * WinXP Picture Viewer bug (err, liberty). When you rotate * a picture in the viewer, it modifies the IFD1 (thumbnail) * tags to UserComment without changing the type appropriately. * (At least we're able to ID invalid comments...) */ if (prop->tagset[i].type && prop->tagset[i].type != prop->type) { #ifdef WINXP_BUGS if (prop->tag != EXIF_T_USERCOMMENT) #endif exifwarn2("field type mismatch", prop->name); prop->lvl = ED_BAD; } /* * Check the field count. * XXX For whatever the reason, Sigma doesn't follow the * spec on count for FileSource. */ if (prop->tagset[i].count && prop->tagset[i].count != #ifdef SIGMA_BUGS prop->count && prop->tag != EXIF_T_FILESRC) { #else prop->count) { #endif exifwarn2("field count mismatch", prop->name); /* Let's be forgiving with ASCII fields. */ if (prop->type != TIFF_ASCII) prop->lvl = ED_BAD; } } /* Debuggage. */ dumpprop(prop, afield); /* * Do as much as we can with the tag at this point and add it * to our list. */ parsetag(prop, dir, t, domkr); if ((tmpprop = t->props)) { while (tmpprop->next) tmpprop = tmpprop->next; tmpprop->next = prop; } else t->props = prop; } /* * Process the Exif tags for each field of an IFD. * * Note that this function is only called once per IFD. Therefore, in order * to associate an IFD sequence number with the property, we keep track of * the count here. Root IFDs (0 and 1) are processed first (along with any * other "root" IFDs we find), then any nested IFDs in the order they're * encountered. */ static void readtags(struct ifd *dir, int seq, struct exiftags *t, int domkr) { int i; if (debug) { /* XXX Byte order info can be off for maker notes. */ if (dir->par && dir->par->tag != EXIF_T_UNKNOWN) { printf("Processing %s directory, %d entries, " "%s-endian\n", dir->par->name, dir->num, dir->md.order == BIG ? "big" : "little"); } else printf("Processing directory %d, %d entries, " "%s-endian\n", seq, dir->num, dir->md.order == BIG ? "big" : "little"); } for (i = 0; i < dir->num; i++) readtag(&(dir->fields[i]), seq, dir, t, domkr); if (debug) printf("\n"); } /* * Post-process property values. By now we've got all of the standard * Exif tags read in (but not maker tags), so it's safe to work out * dependencies between tags. * * XXX At this point, we've lost IFD-level TIFF metadata. Therefore, * assumptions about byte order and beginning of the TIFF might be false. */ static void postprop(struct exifprop *prop, struct exiftags *t) { struct exifprop *tmpprop; u_int16_t v; u_int32_t val; float fval; enum byteorder o = t->md.order; struct exifprop *h = t->props; /* Skip bad properties. */ if (prop->lvl == ED_BAD) return; /* * Process tags from special IFDs. */ if (prop->par && prop->par->tagset == tags) { switch (prop->par->tag) { case EXIF_T_MAKERNOTE: if (makers[t->mkrval].propfun) { makers[t->mkrval].propfun(prop, t); return; } break; case EXIF_T_GPSIFD: gpsprop(prop, t); return; } } /* Process normal tags. */ if (prop->tagset != tags) return; switch (prop->tag) { case EXIF_T_XRES: case EXIF_T_YRES: case EXIF_T_FPXRES: case EXIF_T_FPYRES: if (prop->tag == EXIF_T_XRES || prop->tag == EXIF_T_YRES) { if (!(tmpprop = findprop(h, tags, EXIF_T_RESUNITS))) break; } else { if (!(tmpprop = findprop(h, tags, EXIF_T_FPRESUNITS))) break; } val = exif4byte(t->md.btiff + prop->value, o) / exif4byte(t->md.btiff + prop->value + 4, o); snprintf(prop->str, 31, "%d dp%s", val, tmpprop->str); prop->str[31] = '\0'; break; /* * Shutter speed doesn't seem all that useful. It's usually the * same as exposure time and when it's not, it's wrong. * Exposure time overrides it. */ case EXIF_T_SHUTTER: fval = (float)exif4sbyte(t->md.btiff + prop->value, o) / (float)exif4sbyte(t->md.btiff + prop->value + 4, o); if (isnan(fval)) fval = 0; /* 1 / (2^speed) */ snprintf(prop->str, 31, "1/%d", (int)floor(pow(2, (double)fval) + 0.5)); prop->str[31] = '\0'; /* FALLTHROUGH */ case EXIF_T_EXPOSURE: if (strlen(prop->str) > 27) break; strcat(prop->str, " sec"); if (prop->tag == EXIF_T_EXPOSURE) prop->override = EXIF_T_SHUTTER; break; case EXIF_T_FNUMBER: fval = (float)exif4byte(t->md.btiff + prop->value, o) / (float)exif4byte(t->md.btiff + prop->value + 4, o); if (isnan(fval)) fval = 0; snprintf(prop->str, 31, "f/%.1f", fval); prop->str[31] = '\0'; break; case EXIF_T_LAPERTURE: case EXIF_T_MAXAPERTURE: fval = (float)exif4byte(t->md.btiff + prop->value, o) / (float)exif4byte(t->md.btiff + prop->value + 4, o); if (isnan(fval)) fval = 0; /* sqrt(2)^aperture */ snprintf(prop->str, 31, "f/%.1f", pow(1.4142, (double)fval)); prop->str[31] = '\0'; break; case EXIF_T_BRIGHTVAL: if (exif4byte(t->md.btiff + prop->value, o) == 0xffffffff) { strcpy(prop->str, "Unknown"); break; } /* FALLTHROUGH */ case EXIF_T_EXPBIASVAL: if (strlen(prop->str) > 28) break; strcat(prop->str, " EV"); break; case EXIF_T_DISTANCE: if (exif4byte(t->md.btiff + prop->value, o) == 0xffffffff) { strcpy(prop->str, "Infinity"); break; } if (exif4byte(t->md.btiff + prop->value + 4, o) == 0) { strcpy(prop->str, "Unknown"); break; } fval = (float)exif4byte(t->md.btiff + prop->value, o) / (float)exif4byte(t->md.btiff + prop->value + 4, o); if (isnan(fval)) fval = 0; snprintf(prop->str, 31, "%.2f m", fval); prop->str[31] = '\0'; break; /* Flash consists of a number of bits, which expanded with v2.2. */ #define LFLSH 96 case EXIF_T_FLASH: if (t->exifmaj <= 2 && t->exifmin < 20) v = (u_int16_t)(prop->value & 0x7); else v = (u_int16_t)(prop->value & 0x7F); exifstralloc(&prop->str, LFLSH); /* Don't do anything else if there isn't a flash. */ if (catdescr(prop->str, flash_func, (u_int16_t)(v & 0x20), LFLSH)) break; catdescr(prop->str, flash_fire, (u_int16_t)(v & 0x01), LFLSH); catdescr(prop->str, flash_mode, (u_int16_t)(v & 0x18), LFLSH); catdescr(prop->str, flash_redeye, (u_int16_t)(v & 0x40), LFLSH); catdescr(prop->str, flash_return, (u_int16_t)(v & 0x06), LFLSH); break; case EXIF_T_FOCALLEN: fval = (float)exif4byte(t->md.btiff + prop->value, o) / (float)exif4byte(t->md.btiff + prop->value + 4, o); if (isnan(fval)) fval = 0; snprintf(prop->str, 31, "%.2f mm", fval); prop->str[31] = '\0'; break; /* Digital zoom: set to verbose if numerator is 0 or fraction = 1. */ case EXIF_T_DIGIZOOM: if (!exif4byte(t->md.btiff + prop->value, o)) strcpy(prop->str, "Unused"); else if (exif4byte(t->md.btiff + prop->value, o) != exif4byte(t->md.btiff + prop->value + 4, o)) break; prop->lvl = ED_VRB; break; case EXIF_T_FOCALLEN35: exifstralloc(&prop->str, 16); snprintf(prop->str, 15, "%d mm", prop->value); break; /* * XXX This really should be in parsetag() to guarantee that it's * done before we process the maker notes. However, I haven't seen * model not come first, so it should be safe (and more convenient). */ case EXIF_T_MODEL: t->model = prop->str; break; } } /* * This gives us an opportunity to change the dump level based on * property values after all properties are established. */ static void tweaklvl(struct exifprop *prop, struct exiftags *t) { char *c; struct exifprop *tmpprop; /* Change any ASCII properties to verbose if they're empty. */ if (prop->type == TIFF_ASCII && (prop->lvl & (ED_CAM | ED_IMG | ED_PAS))) { c = prop->str; while (c && *c && (isspace((int)*c) || (unsigned char)*c < ' ')) c++; if (!c || !*c) prop->lvl = ED_VRB; } /* * Don't let unprintable characters slip through -- we'll just replace * them with '_'. (Can see this with some corrupt maker notes.) * Remove trailing whitespace while we're at it. */ if (prop->str && prop->type == TIFF_ASCII) { c = prop->str; while (*c) { /* Catch those pesky chars > 127. */ if ((unsigned char)*c < ' ') *c = '_'; c++; } c = prop->str + strlen(prop->str); while (c > prop->str && isspace((int)*(c - 1))) --c; *c = '\0'; } /* * IFD1 refers to the thumbnail image; we don't really care. * It seems that some images might not have an IFD1 (does FinePix * Viewer strip it?), so make sure that the property doesn't have * a parent association. */ if (prop->ifdseq == 1 && !prop->par && prop->lvl != ED_UNK) prop->lvl = ED_VRB; /* Maker tags can override normal Exif tags. */ if (prop->override && (tmpprop = findprop(t->props, tags, prop->override))) if (tmpprop->lvl & (ED_CAM | ED_IMG | ED_PAS)) tmpprop->lvl = ED_OVR; } /* * Fetch the data for an Exif tag. */ static void parsetag(struct exifprop *prop, struct ifd *dir, struct exiftags *t, int domkr) { unsigned int i, len; u_int16_t v = (u_int16_t)prop->value; u_int32_t un, ud, denom; int32_t sn, sd; char buf[32], *c, *d; struct tiffmeta *md; unsigned char *btiff = dir->md.btiff; enum byteorder o = dir->md.order; /* If the tag's already marked as bad, no sense in continuing. */ if (prop->lvl == ED_BAD) return; /* Set description if we have a lookup table. */ for (i = 0; prop->tagset[i].tag < EXIF_T_UNKNOWN && prop->tagset[i].tag != prop->tag; i++); if (prop->tagset[i].table) { prop->str = finddescr(prop->tagset[i].table, v); return; } /* XXX Probably shouldn't process this switch for non-standard tags. */ switch (prop->tag) { /* Process an Exif IFD. */ case EXIF_T_EXIFIFD: case EXIF_T_GPSIFD: case EXIF_T_INTEROP: md = &dir->md; while (dir->next) dir = dir->next; /* * XXX Olympus cameras don't seem to include a proper offset * at the end of the ExifOffset IFD, so just read one IFD. * Hopefully this won't cause us to miss anything... */ #ifdef OLYMPUS_BUGS if (prop->tag == EXIF_T_EXIFIFD) readifd(prop->value, &dir->next, tags, md); else #endif if (prop->tag == EXIF_T_GPSIFD) { dir->next = readifds(prop->value, gpstags, md); } else { dir->next = readifds(prop->value, tags, md); } if (!dir->next) { /* * XXX Ignore the case where interoperability offset * is invalid. This appears to be the case with some * Olympus cameras, and we don't want to abort things * things on an IFD we don't really care about anyway. */ #ifdef OLYMPUS_BUGS if (prop->tag == EXIF_T_INTEROP) break; #endif exifwarn2("invalid Exif format: IFD length mismatch", prop->name); break; } /* XXX Doesn't catch multiple IFDs. */ dir->next->par = prop; return; /* Record the Exif version. */ case EXIF_T_VERSION: byte4exif(prop->value, (unsigned char *)buf, o); buf[4] = '\0'; t->exifmin = (short)atoi(buf + 2); buf[2] = '\0'; t->exifmaj = (short)atoi(buf); exifstralloc(&prop->str, 8); snprintf(prop->str, 7, "%d.%02d", t->exifmaj, t->exifmin); break; /* Process a maker note. */ case EXIF_T_MAKERNOTE: if (!domkr) return; /* Maker function can change metadata if necessary. */ t->mkrmd = dir->md; md = &t->mkrmd; while (dir->next) dir = dir->next; /* * Try to process maker note IFDs using the function * specified for the maker. * * XXX Note that for this to work right, we have to see * the manufacturer tag first to figure out makerifd(). */ if (makers[t->mkrval].ifdfun) { if (!offsanity(prop, 1, dir)) dir->next = makers[t->mkrval].ifdfun(prop->value, md); } else exifwarn("maker note not supported"); if (!dir->next) break; /* XXX Doesn't catch multiple IFDs. */ dir->next->par = prop; return; /* Lookup functions for maker note. */ case EXIF_T_EQUIPMAKE: /* Sanity check the offset. */ if (offsanity(prop, 1, dir)) return; strncpy(buf, (const char *)(btiff + prop->value), sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; for (c = buf; *c; c++) *c = tolower(*c); for (i = 0; makers[i].val != EXIF_MKR_UNKNOWN; i++) if (!strncmp(buf, makers[i].name, strlen(makers[i].name))) break; t->mkrval = (short)i; /* Keep processing (ASCII value). */ break; /* * Handle user comment. According to the spec, the first 8 bytes * of the comment indicate what charset follows. For now, we * just support ASCII. * * XXX A handful of the GPS tags are also stored in this format. */ case 0x001b: /* GPSProcessingMethod */ case 0x001c: /* GPSAreaInformation */ /* * XXX Note that this is kind of dangerous -- any other * tag set won't reach the end of the switch... */ if (prop->tagset != gpstags) break; /* FALLTHROUGH */ case EXIF_T_USERCOMMENT: /* Check for a comment type and sane offset. */ if (prop->count < 8) { exifwarn("invalid user comment length"); prop->lvl = ED_BAD; return; } if (offsanity(prop, 1, dir)) return; /* Ignore the 'comments' WinXP creates when rotating. */ #ifdef WINXP_BUGS for (i = 0; tags[i].tag < EXIF_T_UNKNOWN && tags[i].tag != EXIF_T_USERCOMMENT; i++); if (tags[i].type && tags[i].type != prop->type) break; #endif /* Lookup the comment type. */ for (i = 0; ucomment[i].descr; i++) if (!memcmp(ucomment[i].descr, btiff + prop->value, 8)) break; /* Handle an ASCII comment; strip any trailing whitespace. */ if (ucomment[i].val == TIFF_ASCII) { c = (char *)(btiff + prop->value + 8); d = strlen(c) < prop->count - 8 ? c + strlen(c) : c + prop->count - 8; while (d > c && isspace((int)*(d - 1))) --d; exifstralloc(&prop->str, d - c + 1); strncpy(prop->str, c, d - c); prop->lvl = prop->str[0] ? ED_IMG : ED_VRB; return; } break; case EXIF_T_FILESRC: /* * This 'undefined' field is one byte; runs afoul of XP * not zeroing out stuff. */ #ifdef WINXP_BUGS prop->str = finddescr(filesrcs, (u_int16_t)(v & 0xFFU)); #else prop->str = finddescr(filesrcs, v); #endif return; } /* * ASCII types. */ if (prop->type == TIFF_ASCII) { /* Should fit in the value field. */ if (prop->count < 5) { exifstralloc(&prop->str, 5); byte4exif(prop->value, (unsigned char *)prop->str, o); return; } /* Sanity check the offset. */ if (!offsanity(prop, 1, dir)) { exifstralloc(&prop->str, prop->count + 1); strncpy(prop->str, (const char *)(btiff + prop->value), prop->count); } return; } /* * Rational types. (Note that we'll redo some in our later pass.) * We'll reduce and simplify the fraction. * * XXX Misses multiple rationals. */ if ((prop->type == TIFF_RTNL || prop->type == TIFF_SRTNL) && !offsanity(prop, 8, dir)) { exifstralloc(&prop->str, 32); if (prop->type == TIFF_RTNL) { un = exif4byte(btiff + prop->value, o); ud = exif4byte(btiff + prop->value + 4, o); denom = gcd(un, ud); fixfract(prop->str, un, ud, denom); } else { sn = exif4sbyte(btiff + prop->value, o); sd = exif4sbyte(btiff + prop->value + 4, o); denom = gcd(abs(sn), abs(sd)); fixfract(prop->str, sn, sd, (int32_t)denom); } return; } /* * Multiple short values. * XXX For now, we're going to ignore tags with count > 8. Maker * note tags frequently consist of many shorts; we don't really * want to be spitting these out. (Plus, TransferFunction is huge.) * * XXX Note that this doesn't apply to two shorts, which are * stuffed into the value. */ if ((prop->type == TIFF_SHORT || prop->type == TIFF_SSHORT) && prop->count > 2 && !offsanity(prop, 2, dir)) { if (prop->count > 8) return; len = 8 * prop->count + 1; exifstralloc(&prop->str, len); for (i = 0; i < prop->count; i++) { if (prop->type == TIFF_SHORT) snprintf(prop->str + strlen(prop->str), len - strlen(prop->str) - 1, "%d, ", exif2byte(btiff + prop->value + (i * 2), o)); else snprintf(prop->str + strlen(prop->str), len - strlen(prop->str) - 1, "%d, ", exif2sbyte(btiff + prop->value + (i * 2), o)); } prop->str[strlen(prop->str) - 2] = '\0'; return; } return; } /* * Delete dynamic Exif property and IFD memory. */ void exiffree(struct exiftags *t) { struct exifprop *tmpprop; struct ifdoff *tmpoff; if (!t) return; while ((tmpprop = t->props)) { if (t->props->str) free(t->props->str); t->props = t->props->next; free(tmpprop); } while ((tmpoff = (struct ifdoff *)(t->md.ifdoffs))) { t->md.ifdoffs = (void *)tmpoff->next; free(tmpoff); } free(t); } /* * Scan the Exif section. */ struct exiftags * exifscan(unsigned char *b, int len, int domkr) { int seq; u_int32_t ifdoff; struct exiftags *t; struct ifd *curifd, *tmpifd; /* Create and initialize our file info structure. */ t = (struct exiftags *)malloc(sizeof(struct exiftags)); if (!t) { exifwarn2("can't allocate file info", (const char *)strerror(errno)); return (NULL); } memset(t, 0, sizeof(struct exiftags)); seq = 0; t->md.etiff = b + len; /* End of TIFF. */ /* * Make sure we've got the proper Exif header. If not, we're * looking at somebody else's APP1 (e.g., Photoshop). */ if (memcmp(b, "Exif\0\0", 6)) { exiffree(t); return (NULL); } b += 6; /* Determine endianness of the TIFF data. */ if (!memcmp(b, "MM", 2)) t->md.order = BIG; else if (!memcmp(b, "II", 2)) t->md.order = LITTLE; else { exifwarn("invalid TIFF header"); exiffree(t); return (NULL); } t->md.btiff = b; /* Beginning of TIFF. */ b += 2; /* Verify the TIFF header. */ if (exif2byte(b, t->md.order) != 42) { exifwarn("invalid TIFF header"); exiffree(t); return (NULL); } b += 2; /* Get the 0th IFD, where all of the good stuff should start. */ ifdoff = exif4byte(b, t->md.order); curifd = readifds(ifdoff, tags, &t->md); if (!curifd) { exifwarn("invalid Exif format (couldn't read IFD0)"); exiffree(t); return (NULL); } /* Now, let's parse the fields... */ while ((tmpifd = curifd)) { readtags(curifd, seq++, t, domkr); curifd = curifd->next; free(tmpifd); /* No need to keep it around... */ } return (t); } /* * Read the Exif section and prepare the data for output. */ struct exiftags * exifparse(unsigned char *b, int len) { struct exiftags *t; struct exifprop *curprop; /* Find the section and scan it. */ if (!(t = exifscan(b, len, TRUE))) return (NULL); /* Make field values pretty. */ curprop = t->props; while (curprop) { postprop(curprop, t); tweaklvl(curprop, t); curprop = curprop->next; } return (t); } Image-EXIF-2.01/exif.h0000644000076500000000000001734111753243142013301 0ustar aaronwheel/* * Copyright (c) 2001-2007, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: exif.h,v 1.38 2007/12/16 03:44:32 ejohnst Exp $ */ /* * Exchangeable image file format (Exif) parser. * * Developed using the TIFF 6.0 specification * (http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf) * and the EXIF 2.21 standard: (http://tsc.jeita.or.jp/avs/data/cp3451_1.pdf). * */ #ifndef _EXIF_H #define _EXIF_H #include /* * XXX Only checking for Solaris, HP, & Windows now. Other platforms will * probably need something similar if they don't have u_int16_t or u_int32_t. */ #if (defined(sun) && (defined(__svr4__) || defined(__SVR4))) typedef unsigned short u_int16_t; typedef unsigned int u_int32_t; #endif #if (defined(__hpux)) typedef uint16_t u_int16_t; typedef uint32_t u_int32_t; #endif #ifdef WIN32 typedef unsigned __int16 u_int16_t; typedef unsigned __int32 u_int32_t; typedef __int16 int16_t; typedef __int32 int32_t; #define snprintf _snprintf #define isnan _isnan #endif #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif /* TIFF types. */ #define TIFF_UNKN 0 #define TIFF_BYTE 1 #define TIFF_ASCII 2 #define TIFF_SHORT 3 #define TIFF_LONG 4 #define TIFF_RTNL 5 #define TIFF_SBYTE 6 #define TIFF_UNDEF 7 #define TIFF_SSHORT 8 #define TIFF_SLONG 9 #define TIFF_SRTNL 10 #define TIFF_FLOAT 11 #define TIFF_DBL 12 /* Dump level. */ #define ED_UNK 0x01 /* Unknown or unimplemented info. */ #define ED_CAM 0x02 /* Camera-specific info. */ #define ED_IMG 0x04 /* Image-specific info. */ #define ED_VRB 0x08 /* Verbose info. */ #define ED_PAS 0x10 /* Point-and-shoot info. */ #define ED_OVR 0x20 /* Overridden info. */ #define ED_BAD 0x40 /* 'Bad' or incorrect info (given other values). */ /* Interesting tags. */ #define EXIF_T_UNKNOWN 0xffff /* XXX Non-standard. */ #define EXIF_T_COMPRESS 0x0103 #define EXIF_T_PHOTOINTERP 0x0106 #define EXIF_T_EQUIPMAKE 0x010f #define EXIF_T_MODEL 0x0110 #define EXIF_T_ORIENT 0x0112 #define EXIF_T_XRES 0x011a #define EXIF_T_YRES 0x011b #define EXIF_T_PLANARCONFIG 0x011c #define EXIF_T_RESUNITS 0x0128 #define EXIF_T_XFERFUNC 0x012d #define EXIF_T_DATETIME 0x0132 #define EXIF_T_CHROMRATIO 0x0212 #define EXIF_T_CHROMPOS 0x0213 #define EXIF_T_EXPOSURE 0x829a #define EXIF_T_FNUMBER 0x829d #define EXIF_T_EXPPROG 0x8822 #define EXIF_T_GPSIFD 0x8825 #define EXIF_T_ISOSPEED 0x8827 #define EXIF_T_VERSION 0x9000 #define EXIF_T_DATETIMEORIG 0x9003 #define EXIF_T_DATETIMEDIGI 0x9004 #define EXIF_T_COMPCONFIG 0x9101 #define EXIF_T_SHUTTER 0x9201 #define EXIF_T_LAPERTURE 0x9202 #define EXIF_T_BRIGHTVAL 0x9203 #define EXIF_T_EXPBIASVAL 0x9204 #define EXIF_T_MAXAPERTURE 0x9205 #define EXIF_T_DISTANCE 0x9206 #define EXIF_T_METERMODE 0x9207 #define EXIF_T_LIGHTSRC 0x9208 #define EXIF_T_FLASH 0x9209 #define EXIF_T_FOCALLEN 0x920a #define EXIF_T_USERCOMMENT 0x9286 #define EXIF_T_COLORSPC 0xa001 #define EXIF_T_FPXRES 0xa20e #define EXIF_T_FPYRES 0xa20f #define EXIF_T_FPRESUNITS 0xa210 #define EXIF_T_IMGSENSOR 0xa217 #define EXIF_T_FILESRC 0xa300 #define EXIF_T_SCENETYPE 0xa301 #define EXIF_T_EXPMODE 0xa402 #define EXIF_T_WHITEBAL 0xa403 #define EXIF_T_DIGIZOOM 0xa404 #define EXIF_T_FOCALLEN35 0xa405 #define EXIF_T_SCENECAPTYPE 0xa406 #define EXIF_T_CONTRAST 0xa408 #define EXIF_T_SATURATION 0xa409 #define EXIF_T_SHARPNESS 0xa40a /* Byte order. */ enum byteorder { LITTLE, BIG }; /* Generic field description lookup table. */ struct descrip { int32_t val; const char *descr; }; /* Tag lookup table. */ struct exiftag { u_int16_t tag; /* Tag ID. */ u_int16_t type; /* Expected type. */ u_int16_t count; /* Expected count. */ unsigned short lvl; /* Output level. */ const char *name; const char *descr; struct descrip *table; /* Value lookup table. */ }; /* Final Exif property info. (Note: descr can be NULL.) */ struct exifprop { u_int16_t tag; /* The Exif tag. */ u_int16_t type; u_int32_t count; u_int32_t value; const char *name; const char *descr; char *str; /* String representation of value (dynamic). */ unsigned short lvl; /* Verbosity level. */ int ifdseq; /* Sequence number of parent IFD. */ u_int16_t override; /* Override display of another tag. */ struct exiftag *tagset; /* Tags used to create property. */ struct exifprop *par; /* Parent property association. */ struct exifprop *next; }; /* * TIFF/IFD metadata. * * Implementation note: ordinarily, this information wouldn't be stored * at the directory (IFD) level -- it's characteristic of the TIFF itself. * However, the format of some maker notes force this level of detail. * For example, Fuji notes can be in a different byte order than the rest of * the TIFF. Also, some Nikon notes actually contain a full TIFF header * and specify their own byte order and offset base. * * Therefore, while this information is generally true for the TIFF, it * may not apply to maker note properties. */ struct tiffmeta { enum byteorder order; /* Endianness of IFD. */ unsigned char *btiff; /* Beginning of TIFF (offset base). */ unsigned char *etiff; /* End of TIFF. */ void *ifdoffs; /* List of IFD offsets (internal only). */ }; /* Image info and exifprop pointer returned by exifscan(). */ struct exiftags { struct exifprop *props; /* The good stuff. */ struct tiffmeta md; /* Beginning, end, and endianness of TIFF. */ const char *model; /* Camera model, to aid maker tag processing. */ short mkrval; /* Maker index (see makers.h). */ struct tiffmeta mkrmd; /* Maker TIFF info. */ /* Version info. */ short exifmaj; /* Exif version, major. */ short exifmin; /* Exif version, minor. */ }; /* Eternal interfaces. */ extern int debug; extern const char *progname; extern struct exiftag tags[]; extern struct exifprop *findprop(struct exifprop *prop, struct exiftag *tagset, u_int16_t tag); extern void exifdie(const char *msg); extern void exifwarn(const char *msg); extern void exifwarn2(const char *msg1, const char *msg2); extern void exiffree(struct exiftags *t); extern struct exiftags *exifscan(unsigned char *buf, int len, int domkr); extern struct exiftags *exifparse(unsigned char *buf, int len); #endif Image-EXIF-2.01/exifgps.c0000644000076500000000000002421511753243142014004 0ustar aaronwheel/* * Copyright (c) 2003-2005, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: exifgps.c,v 1.14 2007/12/15 20:57:10 ejohnst Exp $ */ /* * Exif GPS information tags. * * Note: things aren't quite complete. Waiting on additional examples * that include the tags marked unknown. */ #include #include #include #include #include "exif.h" #include "exifint.h" #define DEGREE "°" /* Speed. */ static struct descrip gps_speed[] = { { 'K', "km/h" }, { 'M', "mph" }, { 'N', "knots" }, { -1, "" }, }; /* Status. */ static struct descrip gps_status[] = { { 'A', "Measurement In Progress" }, { 'V', "Measurement Interoperability" }, { -1, "Unknown" }, }; /* Distance. */ static struct descrip gps_dist[] = { { 'K', "km" }, { 'M', "mi" }, { 'N', "knots" }, { -1, "" }, }; /* Differential correction. */ static struct descrip gps_diff[] = { { 0, "No Correction" }, { 1, "Correction Applied" }, { -1, "Unknown" }, }; /* Bearing reference. */ static struct descrip gps_bear[] = { { 'M', "Magnetic North" }, { 'T', "True North" }, { -1, "Unknown" }, }; /* GPS info version 2.2.0.0 tags. */ struct exiftag gpstags[] = { { 0x0000, TIFF_BYTE, 4, ED_VRB, "GPSVersionID", "GPS Info Version", NULL }, { 0x0001, TIFF_ASCII, 2, ED_VRB, "GPSLatitudeRef", "Latitude Reference", NULL }, { 0x0002, TIFF_RTNL, 3, ED_IMG, "GPSLatitude", "Latitude", NULL }, { 0x0003, TIFF_ASCII, 2, ED_VRB, "GPSLongitudeRef", "Longitude Reference", NULL }, { 0x0004, TIFF_RTNL, 3, ED_IMG, "GPSLongitude", "Longitude", NULL }, { 0x0005, TIFF_BYTE, 1, ED_VRB, "GPSAltitudeRef", "Altitude Reference", NULL }, { 0x0006, TIFF_RTNL, 1, ED_IMG, /* meters */ "GPSAltitude", "Altitude", NULL }, { 0x0007, TIFF_RTNL, 3, ED_IMG, "GPSTimeStamp", "Time (UTC)", NULL }, { 0x0008, TIFF_ASCII, 0, ED_IMG, "GPSSatellites", "GPS Satellites", NULL }, { 0x0009, TIFF_ASCII, 2, ED_IMG, "GPSStatus", "GPS Status", gps_status }, { 0x000a, TIFF_ASCII, 2, ED_IMG, "GPSMeasureMode", "GPS Measurement Mode", NULL }, { 0x000b, TIFF_RTNL, 1, ED_UNK, "GPSDOP", "GPS Degree of Precision", NULL }, { 0x000c, TIFF_ASCII, 2, ED_VRB, "GPSSpeedRef", "GPS Speed Reference", gps_speed }, { 0x000d, TIFF_RTNL, 1, ED_UNK, "GPSSpeed", "Movement Speed", NULL }, { 0x000e, TIFF_ASCII, 2, ED_VRB, "GPSTrackRef", "GPS Direction Reference", gps_bear }, { 0x000f, TIFF_RTNL, 1, ED_UNK, /* degrees */ "GPSTrack", "Movement Direction", NULL }, { 0x0010, TIFF_ASCII, 2, ED_VRB, "GPSImgDirectionRef", "GPS Image Direction Ref", gps_bear }, { 0x0011, TIFF_RTNL, 1, ED_UNK, /* degrees */ "GPSImgDirection", "Image Direction", NULL }, { 0x0012, TIFF_ASCII, 0, ED_IMG, "GPSMapDatum", "Geodetic Survey Data", NULL }, { 0x0013, TIFF_ASCII, 2, ED_VRB, "GPSDestLatitudeRef", "GPS Dest Latitude Ref", NULL }, { 0x0014, TIFF_RTNL, 3, ED_IMG, "GPSDestLatitude", "Destination Latitude", NULL }, { 0x0015, TIFF_ASCII, 2, ED_VRB, "GPSDestLongitudeRef", "GPS Dest Longitude Ref", NULL }, { 0x0016, TIFF_RTNL, 3, ED_IMG, "GPSDestLongitude", "Destination Longitude", NULL }, { 0x0017, TIFF_ASCII, 2, ED_VRB, "GPSDestBearingRef", "GPS Dest Bearing Ref", gps_bear }, { 0x0018, TIFF_RTNL, 1, ED_UNK, /* degrees */ "GPSDestBearing", "Destination Direction", NULL }, { 0x0019, TIFF_ASCII, 2, ED_VRB, "GPSDestDistanceRef", "GPS Dest Distance Ref", gps_dist }, { 0x001a, TIFF_RTNL, 1, ED_UNK, "GPSDestDistance", "Destination Distance", NULL }, { 0x001b, TIFF_UNDEF, 0, ED_IMG, "GPSProcessingMethod", "GPS Processing Method", NULL }, { 0x001c, TIFF_UNDEF, 0, ED_IMG, "GPSAreaInformation", "GPS Area", NULL }, { 0x001d, TIFF_ASCII, 11, ED_IMG, "GPSDateStamp", "Date (UTC)", NULL }, { 0x001e, TIFF_SHORT, 1, ED_IMG, "GPSDifferental", "GPS Differential Correction", gps_diff }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "Unknown", NULL, NULL }, }; /* * Process GPS tags. */ void gpsprop(struct exifprop *prop, struct exiftags *t) { u_int32_t i, n, d; double deg, min, sec, alt; char fmt[32], buf[16]; struct exifprop *tmpprop; enum byteorder o = t->md.order; switch (prop->tag) { /* Version. */ case 0x0000: exifstralloc(&prop->str, 8); /* Convert the value back into a string. */ byte4exif(prop->value, (unsigned char *)buf, o); for (i = 0; i < 4; i++) { prop->str[i * 2] = '0' + buf[i]; prop->str[i * 2 + 1] = '.'; } prop->str[7] = '\0'; break; /* * Reference values. The value is 2-count nul-terminated ASCII, * not an offset to the ASCII string. * XXX Shouldn't really be necessary now that short ASCII strings work. */ case 0x0001: case 0x0003: case 0x0009: case 0x000a: case 0x000c: case 0x000e: case 0x0010: case 0x0013: case 0x0015: case 0x0017: case 0x0019: /* Clean-up from any earlier processing. */ free(prop->str); prop->str = NULL; byte4exif(prop->value, (unsigned char *)buf, o); for (i = 0; gpstags[i].tag < EXIF_T_UNKNOWN && gpstags[i].tag != prop->tag; i++); if (gpstags[i].table) prop->str = finddescr(gpstags[i].table, (unsigned char)buf[0]); else { exifstralloc(&prop->str, 2); prop->str[0] = buf[0]; } break; /* * Coordinate values. * * This is really kind of a mess. The display behavior here is * based on image samples from a Nikon D1X and a Fuji FinePix S1 Pro. * The specification allows for fractional minutes (and no seconds). * Not sure if there are any other combinations... */ case 0x0002: case 0x0004: case 0x0014: case 0x0016: if (prop->count != 3) { exifwarn("unexpected GPS coordinate values"); prop->lvl = ED_BAD; break; } free(prop->str); prop->str = NULL; exifstralloc(&prop->str, 32); /* Figure out the reference prefix. */ switch (prop->tag) { case 0x0002: tmpprop = findprop(t->props, gpstags, 0x0001); break; case 0x0004: tmpprop = findprop(t->props, gpstags, 0x0003); break; case 0x0014: tmpprop = findprop(t->props, gpstags, 0x0013); break; case 0x0016: tmpprop = findprop(t->props, gpstags, 0x0015); break; default: tmpprop = NULL; } /* Degrees. */ i = 0; n = exif4byte(t->md.btiff + prop->value + i * 8, o); d = exif4byte(t->md.btiff + prop->value + 4 + i * 8, o); strcpy(fmt, "%s %.f%s "); if (!n || !d) /* Punt. */ deg = 0.0; else { deg = (double)n / (double)d; if (d != 1) sprintf(fmt, "%%s %%.%df%%s ", (int)log10((double)d)); } /* Minutes. */ i++; n = exif4byte(t->md.btiff + prop->value + i * 8, o); d = exif4byte(t->md.btiff + prop->value + 4 + i * 8, o); if (!n || !d) { /* Punt. */ min = 0.0; strcat(fmt, "%.f'"); } else { min = (double)n / (double)d; if (d != 1) { sprintf(buf, "%%.%df'", (int)log10((double)d)); strcat(fmt, buf); } else strcat(fmt, "%.f'"); } /* * Seconds. We'll assume if minutes are fractional, we * should just ignore seconds. */ i++; n = exif4byte(t->md.btiff + prop->value + i * 8, o); d = exif4byte(t->md.btiff + prop->value + 4 + i * 8, o); if (!n || !d) { /* Assume no seconds. */ snprintf(prop->str, 31, fmt, tmpprop && tmpprop->str ? tmpprop->str : "", deg, DEGREE, min); break; } else { sec = (double)n / (double)d; if (d != 1) { sprintf(buf, " %%.%df", (int)log10((double)d)); strcat(fmt, buf); } else strcat(fmt, " %.f"); } snprintf(prop->str, 31, fmt, tmpprop && tmpprop->str ? tmpprop->str : "", deg, DEGREE, min, sec); break; /* Altitude. */ case 0x0006: n = exif4byte(t->md.btiff + prop->value, o); d = exif4byte(t->md.btiff + prop->value + 4, o); /* Look up reference. Non-zero means negative altitude. */ tmpprop = findprop(t->props, gpstags, 0x0005); if (tmpprop && tmpprop->value) n *= -1; if (!n || !d) alt = 0.0; else alt = (double)n / (double)d; /* Should already have a 32-byte buffer from parsetag(). */ snprintf(prop->str, 31, "%.2f m", alt); prop->str[31] = '\0'; break; /* Time. */ case 0x0007: /* Should already have a 32-byte buffer from parsetag(). */ prop->str[0] = '\0'; for (i = 0; i < prop->count; i++) { n = exif4byte(t->md.btiff + prop->value + i * 8, o); d = exif4byte(t->md.btiff + prop->value + 4 + i * 8, o); if (!d) break; if (!i) sprintf(fmt, "%%02.%df", (int)log10((double)d)); else sprintf(fmt, ":%%02.%df", (int)log10((double)d)); snprintf(buf, 8, fmt, (double)n / (double)d); strcat(prop->str, buf); } break; } } Image-EXIF-2.01/exifint.h0000644000076500000000000001221611753243142014010 0ustar aaronwheel/* * Copyright (c) 2001-2007, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: exifint.h,v 1.32 2007/12/16 00:48:22 ejohnst Exp $ */ /* * Exchangeable image file format (Exif) parser. * * Developed using the TIFF 6.0 specification * (http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf) * and the EXIF 2.21 standard: (http://tsc.jeita.or.jp/avs/data/cp3451_1.pdf). * * Definitions internal to the Exif parsing library. * */ #ifndef _EXIFINT_H #define _EXIFINT_H #include "exif.h" /* Exif IFD tags. */ #define EXIF_T_EXIFIFD 0x8769 #define EXIF_T_GPSIFD 0x8825 #define EXIF_T_MAKERNOTE 0x927c #define EXIF_T_INTEROP 0xa005 /* IFD field types. */ struct fieldtype { u_int16_t type; const char *name; size_t size; }; /* A raw Image File Directory (IFD) entry (12 bytes). */ struct field { unsigned char tag[2]; unsigned char type[2]; unsigned char count[4]; unsigned char value[4]; }; /* IFD entry. */ struct ifd { u_int16_t num; /* Number of fields. */ struct field *fields; /* Array of fields. */ struct exifprop *par; /* Parent property association. */ struct exiftag *tagset; /* Tag definitions. */ struct tiffmeta md; /* Metadata. */ struct ifd *next; }; /* List of IFD offsets, to detect loops. */ struct ifdoff { unsigned char *offset; /* Offset to IFD. */ struct ifdoff *next; /* Next IFD in list. */ }; /* Macro for making sense of a fraction. */ #define fixfract(str, n, d, t) { \ if ((t)) { (n) /= (t); (d) /= (t); } \ if (!(n)) sprintf((str), "0"); \ else if (!(d)) sprintf((str), "Infinite"); \ else if (abs((n)) == abs((d))) sprintf((str), "%d", (n) / (d)); \ else if (abs((d)) == 1) snprintf((str), 31, "%d", (n) / (d)); \ else if (abs((n)) > abs((d))) snprintf((str), 31, "%.1f", \ (double)(n) / (double)(d)); \ else if (abs((d)) > 2 && abs((n)) > 1 && \ (fabs((double)(n) / (double)(d))) >= 0.1) \ snprintf((str), 31, "%.1f", (double)(n) / (double)(d)); \ else snprintf((str), 31, "%d/%d", (n), (d)); \ } /* The tables from tagdefs.c. */ extern struct fieldtype ftypes[]; extern struct descrip ucomment[]; extern struct descrip flash_fire[]; extern struct descrip flash_return[]; extern struct descrip flash_mode[]; extern struct descrip flash_func[]; extern struct descrip flash_redeye[]; extern struct descrip filesrcs[]; /* Utility functions from exifutil.c. */ extern int offsanity(struct exifprop *prop, u_int16_t size, struct ifd *dir); extern u_int16_t exif2byte(unsigned char *b, enum byteorder o); extern int16_t exif2sbyte(unsigned char *b, enum byteorder o); extern u_int32_t exif4byte(unsigned char *b, enum byteorder o); extern void byte4exif(u_int32_t n, unsigned char *b, enum byteorder o); extern int32_t exif4sbyte(unsigned char *b, enum byteorder o); extern char *finddescr(struct descrip *table, u_int16_t val); extern int catdescr(char *c, struct descrip *table, u_int16_t val, int len); extern struct exifprop *newprop(void); extern struct exifprop *childprop(struct exifprop *parent); extern void exifstralloc(char **str, int len); extern void hexprint(unsigned char *b, int len); extern void dumpprop(struct exifprop *prop, struct field *afield); extern struct ifd *readifds(u_int32_t offset, struct exiftag *tagset, struct tiffmeta *md); extern u_int32_t readifd(u_int32_t offset, struct ifd **dir, struct exiftag *tagset, struct tiffmeta *md); extern u_int32_t gcd(u_int32_t a, u_int32_t b); /* Interface to exifgps.c. */ extern struct exiftag gpstags[]; extern void gpsprop(struct exifprop *prop, struct exiftags *t); #endif Image-EXIF-2.01/exifutil.c0000644000076500000000000002632611753243142014175 0ustar aaronwheel/* * Copyright (c) 2001-2007, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: exifutil.c,v 1.31 2007/12/16 01:14:26 ejohnst Exp $ */ /* * Utilities for dealing with Exif data. * */ #include #include #include #include #include "exif.h" #include "exifint.h" /* * Some global variables we all need. */ int debug; const char *progname; /* * Logging and error functions. */ void exifdie(const char *msg) { fprintf(stderr, "%s: %s\n", progname, msg); exit(1); } void exifwarn(const char *msg) { fprintf(stderr, "%s: %s\n", progname, msg); } void exifwarn2(const char *msg1, const char *msg2) { fprintf(stderr, "%s: %s (%s)\n", progname, msg1, msg2); } /* * Sanity check a tag's count & value when used as an offset within * the TIFF. Checks for overflows. Returns 0 if OK; !0 if not OK. */ int offsanity(struct exifprop *prop, u_int16_t size, struct ifd *dir) { u_int32_t tifflen; const char *name; /* XXX Hrm. Should be OK with 64-bit addresses. */ tifflen = dir->md.etiff - dir->md.btiff; if (prop->name) name = prop->name; else name = "Unknown"; if (!prop->count) { if (prop->value > tifflen) { exifwarn2("invalid field offset", name); prop->lvl = ED_BAD; return (1); } return (0); } /* Does count * size overflow? */ if (size > (u_int32_t)(-1) / prop->count) { exifwarn2("invalid field count", name); prop->lvl = ED_BAD; return (1); } /* Does count * size + value overflow? */ if ((u_int32_t)(-1) - prop->value < prop->count * size) { exifwarn2("invalid field offset", name); prop->lvl = ED_BAD; return (1); } /* Is the offset valid? */ if (prop->value + prop->count * size > tifflen) { exifwarn2("invalid field offset", name); prop->lvl = ED_BAD; return (1); } return (0); } /* * Read an unsigned 2-byte int from the buffer. */ u_int16_t exif2byte(unsigned char *b, enum byteorder o) { if (o == BIG) return ((b[0] << 8) | b[1]); else return ((b[1] << 8) | b[0]); } /* * Read a signed 2-byte int from the buffer. */ int16_t exif2sbyte(unsigned char *b, enum byteorder o) { if (o == BIG) return ((b[0] << 8) | b[1]); else return ((b[1] << 8) | b[0]); } /* * Read an unsigned 4-byte int from the buffer. */ u_int32_t exif4byte(unsigned char *b, enum byteorder o) { if (o == BIG) return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]); else return ((b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]); } /* * Write an unsigned 4-byte int to a buffer. */ void byte4exif(u_int32_t n, unsigned char *b, enum byteorder o) { int i; if (o == BIG) for (i = 0; i < 4; i++) b[3 - i] = (unsigned char)((n >> (i * 8)) & 0xff); else for (i = 0; i < 4; i++) b[i] = (unsigned char)((n >> (i * 8)) & 0xff); } /* * Read a signed 4-byte int from the buffer. */ int32_t exif4sbyte(unsigned char *b, enum byteorder o) { if (o == BIG) return ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]); else return ((b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]); } /* * Lookup and allocate description for a value. */ char * finddescr(struct descrip *table, u_int16_t val) { int i; char *c; for (i = 0; table[i].val != -1 && table[i].val != val; i++); if (!(c = (char *)malloc(strlen(table[i].descr) + 1))) exifdie((const char *)strerror(errno)); strcpy(c, table[i].descr); return (c); } /* * Lookup and append description for a value. * Doesn't do anything if the value is unknown; first adds ", " if dest * contains a value; returns number of bytes added. len is total size * of destination buffer. */ int catdescr(char *c, struct descrip *table, u_int16_t val, int len) { int i, l; l = 0; len -= 1; c[len] = '\0'; for (i = 0; table[i].val != -1 && table[i].val != val; i++); if (table[i].val == -1) return (0); if (strlen(c)) { strncat(c, ", ", len - strlen(c)); l += 2; } strncat(c, table[i].descr, len - strlen(c)); l += strlen(table[i].descr); return (l); } /* * Lookup a property entry belonging to a particular set of tags. */ struct exifprop * findprop(struct exifprop *prop, struct exiftag *tagset, u_int16_t tag) { for (; prop && (prop->tagset != tagset || prop->tag != tag || prop->lvl == ED_BAD); prop = prop->next); return (prop); } /* * Allocate memory for an Exif property. */ struct exifprop * newprop(void) { struct exifprop *prop; prop = (struct exifprop *)malloc(sizeof(struct exifprop)); if (!prop) exifdie((const char *)strerror(errno)); memset(prop, 0, sizeof(struct exifprop)); return (prop); } /* * Given a parent, create a new child Exif property. These are * typically used by maker note modules when a single tag may contain * multiple items of interest. */ struct exifprop * childprop(struct exifprop *parent) { struct exifprop *prop; prop = newprop(); /* By default, the child inherits most values from its parent. */ prop->tag = parent->tag; prop->type = TIFF_UNKN; prop->name = parent->name; prop->descr = parent->descr; prop->lvl = parent->lvl; prop->ifdseq = parent->ifdseq; prop->par = parent; prop->next = parent->next; /* Now insert the new property into our list. */ parent->next = prop; return (prop); } /* * Allocate a buffer for a property's display string. */ void exifstralloc(char **str, int len) { if (*str) { exifwarn("tried to alloc over non-null string"); abort(); } if (!(*str = (char *)calloc(1, len))) exifdie((const char *)strerror(errno)); } /* * Print hex values of a buffer. */ void hexprint(unsigned char *b, int len) { int i; for (i = 0; i < len; i++) printf(" %02X", b[i]); } /* * Print debug info for a property. */ void dumpprop(struct exifprop *prop, struct field *afield) { int i; if (!debug) return; for (i = 0; ftypes[i].type && ftypes[i].type != prop->type; i++); if (afield) { printf(" %s (0x%04X): %s, %u; %u\n", prop->name, prop->tag, ftypes[i].name, prop->count, prop->value); printf(" "); hexprint(afield->tag, 2); printf(" |"); hexprint(afield->type, 2); printf(" |"); hexprint(afield->count, 4); printf(" |"); hexprint(afield->value, 4); printf("\n"); } else printf(" %s (0x%04X): %s, %d; %d, 0x%04X\n", prop->name, prop->tag, ftypes[i].name, prop->count, prop->value, prop->value); } /* * Allocate and read an individual IFD. Takes the beginning and end of the * Exif buffer, returns the IFD and an offset to the next IFD. */ u_int32_t readifd(u_int32_t offset, struct ifd **dir, struct exiftag *tagset, struct tiffmeta *md) { u_int32_t ifdsize, tifflen; unsigned char *b; struct ifdoff *ifdoffs, *lastoff; tifflen = md->etiff - md->btiff; b = md->btiff; ifdoffs = (struct ifdoff *)(md->ifdoffs); lastoff = NULL; *dir = NULL; /* * Check to see if we've already visited this offset. Otherwise * we could loop. (Need to add in TIFF start for Nikon makernotes.) */ while (ifdoffs && ifdoffs->offset != b + offset) { lastoff = ifdoffs; ifdoffs = ifdoffs->next; } if (ifdoffs) { /* We'll only complain if debugging. */ if (debug) exifwarn("loop in IFD reference"); return (0); } ifdoffs = (struct ifdoff *)malloc(sizeof(struct ifdoff)); if (!ifdoffs) { exifwarn2("can't allocate IFD offset record", (const char *)strerror(errno)); return (0); } ifdoffs->offset = offset + b; ifdoffs->next = NULL; /* The 0th (first) IFD establishes our list on the master tiffmeta. */ if (lastoff) lastoff->next = ifdoffs; else md->ifdoffs = (void *)ifdoffs; /* * Verify that we have a valid offset. Some maker note IFDs prepend * a string and will screw us up otherwise (e.g., Olympus). * (Number of directory entries is in the first 2 bytes.) */ if ((u_int32_t)(-1) - offset < 2 || offset + 2 > tifflen) return (0); *dir = (struct ifd *)malloc(sizeof(struct ifd)); if (!*dir) { exifwarn2("can't allocate IFD record", (const char *)strerror(errno)); return (0); } (*dir)->num = exif2byte(b + offset, md->order); (*dir)->par = NULL; (*dir)->tagset = tagset; (*dir)->md = *md; (*dir)->next = NULL; /* Make sure ifdsize doesn't overflow. */ if ((*dir)->num && sizeof(struct field) > (u_int32_t)(-1) / (*dir)->num) { free(*dir); *dir = NULL; return (0); } ifdsize = (*dir)->num * sizeof(struct field); b += offset + 2; /* Sanity check our size (and check for overflows). */ if ((u_int32_t)(-1) - (offset + 2) < ifdsize || offset + 2 + ifdsize > tifflen) { free(*dir); *dir = NULL; return (0); } /* Point to our array of fields. */ (*dir)->fields = (struct field *)b; /* * While we're here, find the offset to the next IFD. * * Note that this offset isn't always going to be valid. It * seems that some camera implementations of Exif ignore the spec * and do not include the offset for all IFDs (e.g., maker note). * Therefore, it may be necessary to call readifd() directly (in * leiu of readifds()) to avoid problems when reading these non- * standard IFDs. */ return ((b + ifdsize + 4 > md->etiff) ? 0 : exif4byte(b + ifdsize, md->order)); } /* * Read a chain of IFDs. Takes the IFD offset and returns the first * node in a chain of IFDs. Note that it can return NULL. */ struct ifd * readifds(u_int32_t offset, struct exiftag *tagset, struct tiffmeta *md) { struct ifd *firstifd, *curifd; /* Fetch our first one. */ offset = readifd(offset, &firstifd, tagset, md); curifd = firstifd; /* Fetch any remaining ones. */ while (offset) { offset = readifd(offset, &(curifd->next), tagset, md); curifd = curifd->next; } return (firstifd); } /* * Euclid's algorithm to find the GCD. */ u_int32_t gcd(u_int32_t a, u_int32_t b) { if (!b) return (a); return (gcd(b, a % b)); } Image-EXIF-2.01/fuji.c0000644000076500000000000001403111753243142013267 0ustar aaronwheel/* * Copyright (c) 2002, 2003, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: fuji.c,v 1.15 2004/12/23 20:38:52 ejohnst Exp $ */ /* * Exif tag definitions for Fuji maker notes. * */ #include #include #include #include "makers.h" /* Sharpness. */ static struct descrip fuji_sharp[] = { { 1, "Soft" }, { 2, "Soft" }, { 3, "Normal" }, { 4, "Hard" }, { 5, "Hard" }, { -1, "Unknown" }, }; /* White balance. */ static struct descrip fuji_white[] = { { 0, "Auto" }, { 256, "Daylight" }, { 512, "Cloudy" }, { 768, "Daylight Color Fluorescence" }, { 769, "Daywhite Color Fluorescence" }, { 769, "White Fluorescence" }, { 1024, "Incandescence" }, { 3840, "Custom" }, { -1, "Unknown" }, }; /* Color & tone settings. */ static struct descrip fuji_color[] = { { 0, "Normal" }, { 256, "High" }, { 512, "Low" }, { -1, "Unknown" }, }; /* Flash mode. */ static struct descrip fuji_flmode[] = { { 0, "Auto" }, { 1, "On" }, { 2, "Off" }, { 3, "Red Eye Reduction" }, { -1, "Unknown" }, }; /* Generic boolean. */ static struct descrip fuji_bool[] = { { 0, "Off" }, { 1, "On" }, { -1, "Unknown" }, }; /* Focus mode. */ static struct descrip fuji_focus[] = { { 0, "Auto" }, { 1, "Manual" }, { -1, "Unknown" }, }; /* Picture mode. */ static struct descrip fuji_picture[] = { { 0, "Auto" }, { 1, "Portrait" }, { 2, "Landscape" }, { 4, "Sports Scene" }, { 5, "Night Scene" }, { 6, "Program AE" }, { 256, "Aperture Prior AE" }, { 512, "Shutter Prior AE" }, { 768, "Manual Exposure" }, { -1, "Unknown" }, }; /* Blur warning. */ static struct descrip fuji_blurw[] = { { 0, "OK" }, { 1, "Blur Warning" }, { -1, "Unknown" }, }; /* Focus warning. */ static struct descrip fuji_focusw[] = { { 0, "OK" }, { 1, "Out of Focus" }, { -1, "Unknown" }, }; /* Auto exposure warning. */ static struct descrip fuji_aew[] = { { 0, "OK" }, { 1, "Over Exposed" }, { -1, "Unknown" }, }; /* Maker note IFD tags. */ static struct exiftag fuji_tags[] = { { 0x0000, TIFF_UNDEF, 4, ED_CAM, "FujiVersion", "Maker Note Version", NULL }, { 0x1000, TIFF_ASCII, 8, ED_UNK, "FujiQuality", "Quality Setting", NULL }, { 0x1001, TIFF_SHORT, 1, ED_IMG, "FujiSharpness", "Sharpness", fuji_sharp }, { 0x1002, TIFF_SHORT, 1, ED_IMG, "FujiWhiteBal", "White Balance", fuji_white }, { 0x1003, TIFF_SHORT, 1, ED_IMG, "FujiColor", "Chroma Saturation", fuji_color }, { 0x1004, TIFF_SHORT, 1, ED_IMG, "FujiTone", "Contrast", fuji_color }, { 0x1010, TIFF_SHORT, 1, ED_IMG, "FujiFlashMode", "Flash Mode", fuji_flmode }, { 0x1011, TIFF_SRTNL, 1, ED_UNK, "FujiFlashStrength", "Flash Strength", NULL }, { 0x1020, TIFF_SHORT, 1, ED_IMG, "FujiMacro", "Macro Mode", fuji_bool }, { 0x1021, TIFF_SHORT, 1, ED_IMG, "FujiFocusMode", "Focus Mode", fuji_focus }, { 0x1030, TIFF_SHORT, 1, ED_IMG, "FujiSlowSync", "Slow Synchro Mode", fuji_bool }, { 0x1031, TIFF_SHORT, 1, ED_IMG, "FujiPicMode", "Picture Mode", fuji_picture }, { 0x1100, TIFF_SHORT, 1, ED_IMG, "FujiBracket", "Continuous/Bracketing Mode", fuji_bool }, { 0x1300, TIFF_SHORT, 1, ED_IMG, "FujiBlurWarn", "Blur Status", fuji_blurw }, { 0x1301, TIFF_SHORT, 1, ED_IMG, "FujiFocusWarn", "Focus Status", fuji_focusw }, { 0x1302, TIFF_SHORT, 1, ED_IMG, "FujiAEWarn", "Auto Exposure Status", fuji_aew }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "FujiUnknown", "Fuji Unknown", NULL }, }; /* * Process Fuji maker note tags. */ void fuji_prop(struct exifprop *prop, struct exiftags *t) { switch (prop->tag) { /* Maker note version. */ case 0x0000: if (prop->count != 4) break; exifstralloc(&prop->str, prop->count + 1); byte4exif(prop->value, (unsigned char *)prop->str, LITTLE); break; } } /* * Try to read a Fuji maker note IFD. */ struct ifd * fuji_ifd(u_int32_t offset, struct tiffmeta *md) { struct ifd *myifd; int fujilen, fujioff; fujilen = strlen("FUJIFILM"); /* * The Fuji maker note appears to be in Intel byte order * regardless of the rest of the file (!). Also, it seems that * Fuji maker notes start with an ID string, followed by an IFD * offset relative to the MakerNote tag. */ if (!strncmp((const char *)(md->btiff + offset), "FUJIFILM", fujilen)) { fujioff = exif2byte(md->btiff + offset + fujilen, LITTLE); md->order = LITTLE; readifd(offset + fujioff, &myifd, fuji_tags, md); } else readifd(offset, &myifd, fuji_tags, md); return (myifd); } Image-EXIF-2.01/Image-EXIF.xs0000644000076500000000000000732411753243177014334 0ustar aaronwheel#define PERL_NO_GET_CONTEXT #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "exif.h" #include "jpeg.h" struct impl { SV *file_name; struct exiftags *et; }; typedef struct impl *Image__EXIF; #ifndef Newxz #define Newxz(ptr, n, type) Newz(705, ptr, n, type) #endif static void load(pTHX_ struct impl *impl, const char *name) { int mark, first = 0; unsigned int len, rlen; unsigned char *exifbuf = NULL; FILE *fp = fopen(name, "rb"); if (!fp) croak("Can't open file %s: %s", name, strerror(errno)); while (jpegscan(fp, &mark, &len, !(first++))) { if (mark != JPEG_M_APP1) { if (fseek(fp, len, SEEK_CUR)) { free(exifbuf); fclose(fp); croak("Can't seek in file %s: %s", name, strerror(errno)); } continue; } exifbuf = (unsigned char *) malloc(len); if (!exifbuf) { fclose(fp); croak("malloc failed"); } rlen = fread(exifbuf, 1, len, fp); if (rlen != len) { free(exifbuf); fclose(fp); croak("error reading JPEG %s: length mismatch", name); } impl->et = exifparse(exifbuf, len); break; } if (impl->et && !impl->et->props) { exiffree(impl->et); impl->et = 0; } free(exifbuf); fclose(fp); } static STRLEN trimmed_len(const char *p) { const char *endp = p + strlen(p); while (endp > p) { endp--; if (!isspace(*endp)) return endp - p + 1; } return 0; } static SV * get_props(pTHX_ struct impl *impl, unsigned short lvl) { struct exifprop *ep; HV *hv = 0; if (!impl->file_name) croak("no Image::EXIF data loaded"); if (!impl->et) return &PL_sv_undef; for (ep = impl->et->props; ep; ep = ep->next) { const char *name; if (ep->lvl == ED_PAS) /* Take care of point-and-shoot values. */ ep->lvl = ED_CAM; else if (ep->lvl == ED_OVR || ep->lvl == ED_BAD) /* For now, just treat overridden & bad values as verbose. */ ep->lvl = ED_VRB; if (ep->lvl != lvl) continue; name = ep->descr ? ep->descr : ep->name; if (!name || !*name) continue; if (!hv) hv = newHV(); hv_store(hv, name, strlen(name), ep->str ? newSVpvn(ep->str, trimmed_len(ep->str)) : newSViv(ep->value), 0); } return hv ? newRV_noinc((SV *) hv) : &PL_sv_undef; } MODULE = Image::EXIF PACKAGE = Image::EXIF PROTOTYPES: DISABLE Image::EXIF _new_instance(package) char *package CODE: struct impl *impl; Newxz(impl, 1, struct impl); RETVAL = impl; OUTPUT: RETVAL void _destroy_instance(impl) Image::EXIF impl CODE: if (impl->file_name) SvREFCNT_dec(impl->file_name); if (impl->et) exiffree(impl->et); Safefree(impl); void _load_file(impl, file_name) Image::EXIF impl SV *file_name; CODE: load(aTHX_ impl, SvPV_nolen(file_name)); impl->file_name = SvREFCNT_inc(file_name); SV * _file_name(impl) Image::EXIF impl CODE: RETVAL = newSVsv(impl->file_name); OUTPUT: RETVAL SV * get_camera_info(impl) Image::EXIF impl CODE: RETVAL = get_props(aTHX_ impl, ED_CAM); OUTPUT: RETVAL SV * get_image_info(impl) Image::EXIF impl CODE: RETVAL = get_props(aTHX_ impl, ED_IMG); OUTPUT: RETVAL SV * get_other_info(impl) Image::EXIF impl CODE: RETVAL = get_props(aTHX_ impl, ED_VRB); OUTPUT: RETVAL SV * get_unknown_info(impl) Image::EXIF impl CODE: RETVAL = get_props(aTHX_ impl, ED_UNK); OUTPUT: RETVAL Image-EXIF-2.01/jpeg.c0000644000076500000000000001525311753243142013266 0ustar aaronwheel/* * Copyright (c) 2001, 2002, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: jpeg.c,v 1.5 2002/10/15 02:57:09 ejohnst Exp $ */ /* * This module contains a minimal set of functions for parsing a JPEG * file, specific for use in extracting EXIF information. Primarily, it * reads the input file and looks for the markers which indicate the start * of APP1 and APP2 sections. * * Portions of this code were developed while referencing the public domain * 'Jhead' program (version 1.2) by Matthias Wandel . */ #include #include "jpeg.h" #include "exif.h" static FILE *infile; /* Some data we collect from a start of frame. */ static int jpg_prcsn; /* Precision. */ static int jpg_cmpnts; /* Number of components. */ static unsigned int jpg_height; /* Image height. */ static unsigned int jpg_width; /* Image width. */ static const char *jpg_prcss; /* Process. */ static int seensof; /* Process string lookup table. */ static struct jpgprocess { int sof; const char *str; } process[] = { { JPEG_M_SOF0, "Baseline" }, { JPEG_M_SOF1, "Extended sequential" }, { JPEG_M_SOF2, "Progressive" }, { JPEG_M_SOF3, "Lossless" }, { JPEG_M_SOF5, "Differential sequential" }, { JPEG_M_SOF6, "Differential progressive" }, { JPEG_M_SOF7, "Differential lossless" }, { JPEG_M_SOF9, "Extended sequential, arithmetic coding" }, { JPEG_M_SOF10, "Progressive, arithmetic coding" }, { JPEG_M_SOF11, "Lossless, arithmetic coding" }, { JPEG_M_SOF13, "Differential sequential, arithmetic coding" }, { JPEG_M_SOF14, "Differential progressive, arithmetic coding" }, { JPEG_M_SOF15, "Differential lossless, arithmetic coding" }, { JPEG_M_ERR, "Unknown" }, }; /* * Fetch one byte of the JPEG file. */ static int jpg1byte(void) { int b; b = fgetc(infile); if (b == EOF) exifdie("invalid JPEG format"); return (b); } /* * Fetch two bytes of the JPEG file. */ static unsigned int jpg2byte(void) { unsigned int b1, b2; b1 = fgetc(infile); b2 = fgetc(infile); if (b1 == EOF || b2 == EOF) exifdie("invalid JPEG format"); return ((b1 << 8) | b2); } /* * Fetch the length of a marker. */ static unsigned int mkrlen(void) { unsigned int l; /* Length includes itself. */ if ((l = jpg2byte()) < 2) exifdie("invalid JPEG marker (length mismatch)"); return (l - 2); } /* * Skip over an uninteresting marker. */ static void skipmkr(void) { unsigned int l; l = mkrlen(); while (l) { jpg1byte(); l--; } } /* * Check the first bytes of the file for a marker. */ static int topmkr(void) { if (jpg1byte() != JPEG_M_BEG) return (JPEG_M_ERR); return (jpg1byte()); } /* * Find the next JPEG marker in the file. */ static int nxtmkr(void) { int b; int bad = 0; /* Read until we see JPEG_MARKER. */ while ((b = jpg1byte()) != JPEG_M_BEG) bad++; /* Read all JPEG_M_BEGs (which may be used for padding). */ while ((b = jpg1byte()) == JPEG_M_BEG); if (bad) exifwarn("skipped spurious bytes in JPEG"); return (b); } /* * Collect image data from the start of frame. * XXX Note that we clobber any previously collected info... */ static void sofmrk(int mark) { int i; unsigned int l; l = mkrlen(); jpg_prcsn = jpg1byte(); jpg_height = jpg2byte(); jpg_width = jpg2byte(); jpg_cmpnts = jpg1byte(); for (i = 0; process[i].sof < JPEG_M_ERR; i++) if (process[i].sof == mark) break; jpg_prcss = process[i].str; /* Verify length. */ if (l != (unsigned int)(6 + jpg_cmpnts * 3)) exifdie("invalid JPEG SOF marker (length mismatch)"); /* Skip over component info we don't care about. */ for (i = 0; i < jpg_cmpnts; i++) { jpg1byte(); jpg1byte(); jpg1byte(); } seensof = TRUE; } /* * Scan through a JPEG file for markers, returning interesting ones. * Returns false when it's done with the file. */ int jpegscan(FILE *fp, int *mark, unsigned int *len, int first) { infile = fp; /* First time through. */ if (first && topmkr() != JPEG_M_SOI) { exifwarn("doesn't appear to be a JPEG file; " "searching for start of image"); if (nxtmkr() != JPEG_M_SOI) exifdie("start of image not found"); } /* Look for interesting markers. */ for (;;) { switch ((*mark = nxtmkr())) { case JPEG_M_EOI: case JPEG_M_SOS: return (FALSE); case JPEG_M_APP1: case JPEG_M_APP2: *len = mkrlen(); return (TRUE); /* We might as well collect some useful info from SOFs. */ case JPEG_M_SOF0: case JPEG_M_SOF1: case JPEG_M_SOF3: case JPEG_M_SOF5: case JPEG_M_SOF6: case JPEG_M_SOF7: case JPEG_M_SOF9: case JPEG_M_SOF10: case JPEG_M_SOF11: case JPEG_M_SOF13: case JPEG_M_SOF14: case JPEG_M_SOF15: sofmrk(*mark); break; /* Just skip past markers we don't care about. */ default: skipmkr(); } } return (FALSE); } /* * Returns some basic image info about the JPEG, gleaned from start of * frame sections. */ int jpeginfo(int *prcsn, int *cmpnts, unsigned int *height, unsigned int *width, const char *prcss) { *prcsn = jpg_prcsn; *cmpnts = jpg_cmpnts; *height = jpg_height; *width = jpg_width; prcss = jpg_prcss; return (seensof); } Image-EXIF-2.01/jpeg.h0000644000076500000000000000571311753243142013273 0ustar aaronwheel/* * Copyright (c) 2001, 2002, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: jpeg.h,v 1.4 2002/10/15 02:57:09 ejohnst Exp $ */ /* * Functions for parsing a JPEG file, specific to EXIF use. * * Portions of this code were developed while referencing the public domain * 'Jhead' program (version 1.2) by Matthias Wandel . * */ #ifndef _JPEG_H #define _JPEG_H /* The JPEG marker codes we're interested in. */ #define JPEG_M_BEG 0xff /* Start of marker. */ #define JPEG_M_SOF0 0xc0 /* Start of frame n... */ #define JPEG_M_SOF1 0xc1 #define JPEG_M_SOF2 0xc2 #define JPEG_M_SOF3 0xc3 #define JPEG_M_SOF5 0xc5 #define JPEG_M_SOF6 0xc6 #define JPEG_M_SOF7 0xc7 #define JPEG_M_SOF9 0xc9 #define JPEG_M_SOF10 0xca #define JPEG_M_SOF11 0xcb #define JPEG_M_SOF13 0xcd #define JPEG_M_SOF14 0xce #define JPEG_M_SOF15 0xcf #define JPEG_M_SOI 0xd8 /* Start of image. */ #define JPEG_M_EOI 0xd9 /* End of image. */ #define JPEG_M_SOS 0xda /* Start of scan. */ #define JPEG_M_APP1 0xe1 /* APP1 marker. */ #define JPEG_M_APP2 0xe2 /* APP2 marker. */ #define JPEG_M_ERR 0x100 /* Our JPEG utility functions. */ extern int jpegscan(FILE *fp, int *mark, unsigned int *len, int first); extern int jpeginfo(int *prcsn, int *cmpnts, unsigned int *height, unsigned int *width, const char *prcss); #endif Image-EXIF-2.01/leica.c0000644000076500000000000001246611753243142013421 0ustar aaronwheel/* * Copyright (c) 2004, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: leica.c,v 1.4 2004/04/20 22:12:51 ejohnst Exp $ */ /* * Exif tag definitions for Leica maker notes. Values were derived from * a Digilux 2. * * Note that the Digilux 4.3's maker notes are identical to Fuji's. */ #include #include #include #include "makers.h" /* White balance. */ static struct descrip leica_white[] = { { 1, "Auto" }, { 2, "Sunshine" }, { 3, "Cloudy" }, { 4, "Halogen" }, { 5, "Manual" }, { 8, "Electronic Flash" }, { 10, "Black & White" }, { -1, "Unknown" }, }; /* Compression rate. */ static struct descrip leica_compress[] = { { 2, "Low" }, { 3, "Normal" }, { 6, "Very Low" }, { 7, "Raw" }, { -1, "Unknown" }, }; /* Generic boolean. */ static struct descrip leica_bool[] = { { 1, "On" }, { 2, "Off" }, { -1, "Unknown" }, }; /* Focus mode. */ static struct descrip leica_focus[] = { { 1, "Auto" }, { 2, "Manual" }, { -1, "Unknown" }, }; /* Flash exposure compensation. */ static struct descrip leica_flashev[] = { { 0, "0 EV" }, { 1, "0.33 EV" }, { 2, "0.67 EV" }, { 3, "1 EV" }, { 4, "1.33 EV" }, { 5, "1.67 EV" }, { 6, "2 EV" }, { 0xfffa, "-2 EV" }, { 0xfffb, "-1.67 EV" }, { 0xfffc, "-1.33 EV" }, { 0xfffd, "-1 EV" }, { 0xfffe, "-0.67 EV" }, { 0xffff, "-0.33 EV" }, { -1, "Unknown" }, }; /* Contrast. */ static struct descrip leica_contrast[] = { { 0x100, "Low" }, { 0x110, "Standard" }, { 0x120, "High" }, { -1, "Unknown" }, }; /* Aperture mode. */ static struct descrip leica_aperture[] = { { 6, "Auto" }, { 7, "Manual" }, { -1, "Unknown" }, }; /* Spot autofocus. */ static struct descrip leica_spotaf[] = { { 256, "On" }, { 4096, "Off" }, { -1, "Unknown" }, }; /* Maker note IFD tags. */ static struct exiftag leica_tags[] = { { 0x0001, TIFF_ASCII, 8, ED_IMG, "LeicaCompress", "Compression Rate", leica_compress }, { 0x0003, TIFF_SHORT, 1, ED_IMG, "LeicaWhiteBal", "White Balance", leica_white }, { 0x0007, TIFF_SHORT, 1, ED_IMG, "LeicaFocusMode", "Focus Mode", leica_focus }, { 0x000f, TIFF_SHORT, 1, ED_IMG, "LeicaSpotAF", "Spot Autofocus", leica_spotaf }, { 0x001c, TIFF_SHORT, 1, ED_IMG, "LeicaMacro", "Macro Mode", leica_bool }, { 0x001f, TIFF_SHORT, 1, ED_IMG, "LeicaAperture", "Aperture Mode", leica_aperture }, { 0x0024, TIFF_SHORT, 1, ED_IMG, "LeicaFlashEV", "Flash Compensation", leica_flashev }, { 0x002c, TIFF_SHORT, 1, ED_IMG, "LeicaContrast", "Contrast", leica_contrast }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "LeicaUnknown", "Leica Unknown", NULL }, }; /* * Process Leica maker note tags. */ void leica_prop(struct exifprop *prop, struct exiftags *t) { /* * Assume that if the property's tag set is not our Leica one, * it must be Fuji's. */ if (prop->tagset != leica_tags) { fuji_prop(prop, t); return; } /* Override a couple of standard tags. */ switch (prop->tag) { /* White balance. */ case 0x0003: prop->override = EXIF_T_WHITEBAL; break; /* Contrast. */ case 0x002c: prop->override = EXIF_T_CONTRAST; break; } } /* * Try to read a Leica maker note IFD. */ struct ifd * leica_ifd(u_int32_t offset, struct tiffmeta *md) { /* * Leica maker notes start with an ID string, followed by an IFD * offset relative to the MakerNote tag. * * The Digilux 4.3 seems to just spit out Fuji maker notes. So, * go ahead and use the Fuji functions... */ if (!strncmp((const char *)(md->btiff + offset), "FUJIFILM", 8)) return (fuji_ifd(offset, md)); if (!strncmp((const char *)(md->btiff + offset), "LEICA", 5)) return (readifds(offset + 8, leica_tags, md)); return (readifds(offset, leica_tags, md)); } Image-EXIF-2.01/lib/0000755000076500000000000000000011753244231012735 5ustar aaronwheelImage-EXIF-2.01/lib/Image/0000755000076500000000000000000011753244231013757 5ustar aaronwheelImage-EXIF-2.01/lib/Image/EXIF.pm0000644000076500000000000000423311753243322015052 0ustar aaronwheelpackage Image::EXIF; use 5.008; use strict; use warnings; our $VERSION = '2.01'; use Carp (); use XSLoader; XSLoader::load(__PACKAGE__, $VERSION); sub new { my ($class, $file_name) = @_; my $self = $class->_new_instance; $self->file_name("$file_name") if defined $file_name; return $self; } # These exist for compatibility with the historical API sub error { 0 } sub errstr { undef } sub file_name { my $self = shift; if (@_) { my $file_name = shift; Carp::croak("Image::EXIF file name undefined") if !defined $file_name; $self->_load_file("$file_name"); } return $self->_file_name if defined wantarray; } sub get_all_info { my ($self) = @_; my %hash; for my $key (qw) { my $method = "get_$key\_info"; my $data = $self->$method or next; $hash{$key} = $data; } return %hash ? \%hash : undef; } sub DESTROY { my ($self) = @_; $self->_destroy_instance; } 1; __END__ =head1 NAME Image::EXIF - Perl extension for exif library =head1 SYNOPSIS use Image::EXIF; use Data::Dumper; my $exif = Image::EXIF->new($file_name); # or: my $exif = Image::EXIF->new; $exif->file_name($file_name); my $image_info = $exif->get_image_info(); # hash reference my $camera_info = $exif->get_camera_info(); # hash reference my $other_info = $exif->get_other_info(); # hash reference my $point_shoot_info = $exif->get_point_shoot_info(); # hash reference my $unknown_info = $exif->get_unknown_info(); # hash reference my $all_info = $exif->get_all_info(); # hash reference print Dumper($all_info); =head1 DESCRIPTION Perl package Image::EXIF based on exiftags by Eric M. Johnston: L. =head1 AUTHORS =over 4 =item * Aaron Crane Earc@cpan.orgE (current maintainer) =item * sergey s prozhogin Eccpro@rrelaxo.org.ruE =back =head1 REPORTING BUGS Please report bugs at either of the following locations: =over 4 =item * L =item * L =back =head1 SEE ALSO L. =cut Image-EXIF-2.01/Makefile.PL0000644000076500000000000000060111753243142014136 0ustar aaronwheeluse ExtUtils::MakeMaker; use 5.008; my $module_file = 'lib/Image/EXIF.pm'; WriteMakefile( NAME => 'Image::EXIF', VERSION_FROM => $module_file, PREREQ_PM => {}, ABSTRACT_FROM => $module_file, AUTHOR => 'sergey s prozhogin ', OBJECT => '$(O_FILES)', XS => { 'Image-EXIF.xs' => 'Image-EXIF.c' }, ); Image-EXIF-2.01/makers.c0000644000076500000000000000533411753243142013622 0ustar aaronwheel/* * Copyright (c) 2002-2004, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: makers.c,v 1.11 2004/09/15 23:35:55 ejohnst Exp $ */ /* * Maker note lookup table. Use makers_stub.c if you don't need * maker note modules linked in. */ #include #include "makers.h" struct makerfun makers[] = { { 0, "unknown", NULL, NULL }, /* default value */ { EXIF_MKR_CANON, "canon", canon_prop, canon_ifd }, { EXIF_MKR_OLYMPUS, "olympus", olympus_prop, olympus_ifd }, { EXIF_MKR_FUJI, "fujifilm", fuji_prop, fuji_ifd }, { EXIF_MKR_NIKON, "nikon", nikon_prop, nikon_ifd }, { EXIF_MKR_CASIO, "casio", NULL, casio_ifd }, { EXIF_MKR_MINOLTA, "minolta", minolta_prop, minolta_ifd }, { EXIF_MKR_SANYO, "sanyo", sanyo_prop, sanyo_ifd }, { EXIF_MKR_ASAHI, "asahi", asahi_prop, asahi_ifd }, { EXIF_MKR_PENTAX, "pentax", asahi_prop, asahi_ifd }, { EXIF_MKR_LEICA, "leica", leica_prop, leica_ifd }, { EXIF_MKR_PANASONIC, "panasonic", panasonic_prop, panasonic_ifd }, { EXIF_MKR_SIGMA, "sigma", sigma_prop, sigma_ifd }, { EXIF_MKR_UNKNOWN, "unknown", NULL, NULL }, }; Image-EXIF-2.01/makers.h0000644000076500000000000001024511753243142013624 0ustar aaronwheel/* * Copyright (c) 2001-2004, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: makers.h,v 1.18 2004/09/15 23:35:55 ejohnst Exp $ */ /* * Maker note module definitions. * * When adding a new module, include a #define, a property function, * and, if applicable, an IFD reading function. These need to be included * in the makers table found in makers.c. * */ #ifndef _MAKERS_H #define _MAKERS_H #include "exifint.h" /* Maker note function table. */ struct makerfun { int val; const char *name; void (*propfun)(); /* Function to parse properties. */ struct ifd *(*ifdfun)(); /* Function to read IFD. */ }; extern struct makerfun makers[]; /* Maker note defines (must match makers[] in makers.c). */ #define EXIF_MKR_CANON 1 #define EXIF_MKR_OLYMPUS 2 #define EXIF_MKR_FUJI 3 #define EXIF_MKR_NIKON 4 #define EXIF_MKR_CASIO 5 #define EXIF_MKR_MINOLTA 6 #define EXIF_MKR_SANYO 7 #define EXIF_MKR_ASAHI 8 #define EXIF_MKR_PENTAX 9 #define EXIF_MKR_LEICA 10 #define EXIF_MKR_PANASONIC 11 #define EXIF_MKR_SIGMA 12 #define EXIF_MKR_UNKNOWN -1 /* Maker note functions. */ extern void canon_prop(struct exifprop *prop, struct exiftags *t); extern struct ifd *canon_ifd(u_int32_t offset, struct tiffmeta *md); extern void olympus_prop(struct exifprop *prop, struct exiftags *t); extern struct ifd *olympus_ifd(u_int32_t offset, struct tiffmeta *md); extern void fuji_prop(struct exifprop *prop, struct exiftags *t); extern struct ifd *fuji_ifd(u_int32_t offset, struct tiffmeta *md); extern void nikon_prop(struct exifprop *prop, struct exiftags *t); extern struct ifd *nikon_ifd(u_int32_t offset, struct tiffmeta *md); extern struct ifd *casio_ifd(u_int32_t offset, struct tiffmeta *md); extern void minolta_prop(struct exifprop *prop, struct exiftags *t); extern struct ifd *minolta_ifd(u_int32_t offset, struct tiffmeta *md); extern void sanyo_prop(struct exifprop *prop, struct exiftags *t); extern struct ifd *sanyo_ifd(u_int32_t offset, struct tiffmeta *t); extern void asahi_prop(struct exifprop *prop, struct exiftags *t); extern struct ifd *asahi_ifd(u_int32_t offset, struct tiffmeta *md); extern void leica_prop(struct exifprop *prop, struct exiftags *t); extern struct ifd *leica_ifd(u_int32_t offset, struct tiffmeta *md); extern void panasonic_prop(struct exifprop *prop, struct exiftags *t); extern struct ifd *panasonic_ifd(u_int32_t offset, struct tiffmeta *md); extern void sigma_prop(struct exifprop *prop, struct exiftags *t); extern struct ifd *sigma_ifd(u_int32_t offset, struct tiffmeta *md); #endif Image-EXIF-2.01/MANIFEST0000644000076500000000000000076211753244231013325 0ustar aaronwheelChanges lib/Image/EXIF.pm Image-EXIF.xs Makefile.PL MANIFEST README test.pl typemap asahi.c canon.c casio.c exif.c exif.h exifgps.c exifint.h exifutil.c fuji.c jpeg.c jpeg.h leica.c makers.c makers.h minolta.c nikon.c olympus.c panasonic.c sanyo.c sigma.c tagdefs.c examples/create_web_gallery.pl examples/rename.pl examples/t.pl META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) Image-EXIF-2.01/META.json0000664000076500000000000000151611753244231013615 0ustar aaronwheel{ "abstract" : "Perl extension for exif library", "author" : [ "sergey s prozhogin " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.120630", "license" : [ "unknown" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Image-EXIF", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : {} } }, "release_status" : "stable", "version" : "2.01" } Image-EXIF-2.01/META.yml0000664000076500000000000000075011753244231013444 0ustar aaronwheel--- abstract: 'Perl extension for exif library' author: - 'sergey s prozhogin ' build_requires: ExtUtils::MakeMaker: 0 configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.120630' license: unknown meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Image-EXIF no_index: directory: - t - inc requires: {} version: 2.01 Image-EXIF-2.01/minolta.c0000644000076500000000000004515611753243142014011 0ustar aaronwheel/* * Copyright (c) 2003, Javier Crespo * Copyright (c) 2003-2007, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: minolta.c,v 1.29 2007/12/15 21:01:23 ejohnst Exp $ * */ /* * Exif tag definitions for Minolta DiMAGE maker notes. * Tags deciphered by Javier Crespo . * * Mostly supported models: DiMAGE 5, 7, 7i, and 7Hi. * */ #include #include #include #include #include "makers.h" /* Bracketing mode. */ static struct descrip minolta_brackmode[] = { { 0, "Exposure" }, { 1, "Contrast" }, { 2, "Saturation" }, { 3, "Filter" }, { -1, "Unknown" }, }; /* Bracketing step. */ static struct descrip minolta_brackstep[] = { { 0, "1/3" }, { 1, "1/2" }, { 2, "1" }, { -1, "Unknown" }, }; /* Sharpness. */ static struct descrip minolta_sharp[] = { { 0, "Hard" }, { 1, "Normal" }, { 2, "Soft" }, { -1, "Unknown" }, }; /* Color mode. */ static struct descrip minolta_color[] = { { 0, "Natural Color" }, { 1, "Black & White" }, { 2, "Vivid Color" }, { 3, "Solarization" }, { 4, "Adobe RGB" }, { -1, "Unknown" }, }; /* ISO. */ static struct descrip minolta_iso[] = { { 0, "100" }, { 1, "200" }, { 2, "400" }, { 3, "800" }, { 4, "Auto" }, { -1, "Unknown" }, }; /* Generic boolean. */ static struct descrip minolta_bool[] = { { 0, "No" }, { 1, "Yes" }, { -1, "Unknown" }, }; /* Focus mode. */ static struct descrip minolta_focusmode[] = { { 0, "Auto" }, { 1, "Manual" }, { -1, "Unknown" }, }; /* Focus area. */ static struct descrip minolta_focusarea[] = { { 0, "Wide Area" }, { 1, "Spot Focus Point" }, { -1, "Unknown" }, }; /* Wide area focus zone. */ static struct descrip minolta_widefocus[] = { { 0, "No Zone" }, { 1, "Center" }, { 3, "Left" }, { 4, "Right" }, { -1, "Unknown" }, }; /* Drive mode. */ static struct descrip minolta_drive[] = { { 0, "Single Frame" }, { 1, "Continous Advance" }, { 2, "Self Timer" }, { 4, "Bracketing" }, { 5, "Interval" }, { 6, "UHS" }, { 7, "HS" }, { -1, "Unknown" }, }; /* White balance. */ static struct descrip minolta_whitebal[] = { { 0, "Auto" }, { 1, "Daylight" }, { 2, "Cloudy" }, { 3, "Tungsten" }, { 5, "Custom" }, { 7, "Fluorescent" }, { 8, "Fluorescent 2" }, { 11, "Custom 2" }, { 12, "Custom 3" }, { -1, "Unknown" }, }; /* Flash mode. */ static struct descrip minolta_flash[] = { { 0, "Fill Flash" }, { 1, "Red-Eye Reduction" }, { 2, "Rear Sync" }, { 3, "Remote" }, { -1, "Unknown" }, }; /* Capture scene. */ static struct descrip minolta_scene[] = { { 0, "Normal" }, { 1, "Portrait" }, { 2, "Text" }, { 3, "Night Portrait" }, { 4, "Sunset" }, { 5, "Sports Action" }, { -1, "Unknown" }, }; /* Image quality. */ static struct descrip minolta_quality[] = { { 0, "Raw" }, { 1, "Super Fine" }, { 2, "Fine" }, { 3, "Standard" }, { 4, "Economy" }, { 5, "Extra Fine" }, { -1, "Unknown" }, }; /* Exposure program. */ static struct descrip minolta_prog[] = { { 0, "Program AE" }, { 1, "Aperture Priority" }, { 2, "Shutter Priority" }, { 3, "Manual" }, { -1, "Unknown" }, }; /* * Image size. * Valid only for 5 megapixel cameras (D7's), wrong for D5. */ static struct descrip minolta_size[] = { { 0, "2560x1920" }, { 1, "1600x1200" }, { 2, "1280x960" }, { 3, "640x480" }, { -1, "Unknown" }, }; /* Folder name. */ static struct descrip minolta_folder[] = { { 0, "Standard" }, { 1, "Date" }, { -1, "Unknown" }, }; /* Data imprinting. */ static struct descrip minolta_imprint[] = { { 0, "None" }, { 1, "DataTime Y/M/D" }, { 2, "DataTime M/D H:M" }, { 3, "Text" }, { 4, "Text + ID" }, { -1, "Unknown" }, }; /* Camera model. */ static struct descrip minolta_model[] = { { 0, "DiMAGE 7" }, { 1, "DiMAGE 5" }, { 4, "DiMAGE 7i" }, { 5, "DiMAGE 7Hi" }, { -1, "Unknown" }, }; /* Metering mode. */ static struct descrip minolta_metermode[] = { { 0, "Multi-Segment" }, { 1, "Center Weighted Average" }, { 2, "Spot" }, { -1, "Unknown" }, }; /* Maker note IFD tags. */ static struct exiftag minolta_tags[] = { { 0x0000, TIFF_UNDEF, 4, ED_UNK, "MinoltaMakerType", "Minolta Maker Note Type", NULL }, { 0x0001, TIFF_UNDEF, 0, ED_UNK, "Minolta1Tag", "Minolta Tag1 Offset", NULL }, { 0x0003, TIFF_UNDEF, 0, ED_UNK, "Minolta3Tag", "Minolta Tag3 Offset", NULL }, { 0x0040, TIFF_LONG, 1, ED_UNK, "MinoltaCompImgSz", "Minolta Compressed Image Size", NULL }, { 0x0088, TIFF_LONG, 1, ED_UNK, "MinoltaThumbOff", "Minolta Thumbnail Offset", NULL }, { 0x0089, TIFF_LONG, 1, ED_UNK, "MinoltaThumbLen", "Minolta Thumbnail Length", NULL }, { 0x0e00, TIFF_UNDEF, 0, ED_UNK, "MinoltaPIM", "Minolta Print Image Management", NULL }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "Unknown", "Minolta Unknown", NULL }, }; /* Fields under tags 0x0001 and 0x0003. */ static struct exiftag minolta_MLT0[] = { { 1, TIFF_LONG, 1, ED_IMG, "MinoltaExpProg", "Exposure Program", minolta_prog }, { 2, TIFF_LONG, 1, ED_IMG, "MinoltaFlashMode", "Flash Mode", minolta_flash }, { 3, TIFF_LONG, 1, ED_IMG, "MinoltaWhiteB", "White Balance", minolta_whitebal }, { 4, TIFF_LONG, 1, ED_UNK, "MinoltaSize", "Image Size", minolta_size }, { 5, TIFF_LONG, 1, ED_IMG, "MinoltaQuality", "Image Quality", minolta_quality }, { 6, TIFF_LONG, 1, ED_IMG, "MinoltaDriveMode", "Drive Mode", minolta_drive }, { 7, TIFF_LONG, 1, ED_IMG, "MinoltaMeterMode", "Metering Mode", minolta_metermode }, { 8, TIFF_LONG, 1, ED_UNK, "MinoltaFilmSpeed", "Film Speed", NULL }, { 9, TIFF_LONG, 1, ED_VRB, "MinoltaExpTime", "Exposure Time", NULL }, { 10, TIFF_LONG, 1, ED_UNK, "MinoltaAperture", "Lens Aperture", NULL }, { 11, TIFF_LONG, 1, ED_IMG, "MinoltaMacro", "Macro", minolta_bool }, { 12, TIFF_LONG, 1, ED_IMG, "MinoltaDigiZoom", "Digital Zoom", minolta_bool }, { 13, TIFF_LONG, 1, ED_UNK, "MinoltaExpComp", "Exposure Compensation", NULL }, { 14, TIFF_LONG, 1, ED_IMG, "MinoltaBracketStep", "Bracketing Step", minolta_brackstep }, { 16, TIFF_LONG, 1, ED_VRB, "MinoltaIntrvlTime", "Interval Time", NULL }, { 17, TIFF_LONG, 1, ED_VRB, "MinoltaIntrvlPics", "Interval Pics", NULL }, { 18, TIFF_LONG, 1, ED_UNK, "MinoltaFocalLen", "Focal Length", NULL }, { 19, TIFF_LONG, 1, ED_IMG, "MinoltaFocusDist", "Focus Distance", NULL }, { 20, TIFF_LONG, 1, ED_VRB, "MinoltaFlash", "Flash Fired", minolta_bool }, { 21, TIFF_LONG, 1, ED_VRB, "MinoltaDate", "Date", NULL }, { 22, TIFF_LONG, 1, ED_VRB, "MinoltaTime", "Time", NULL }, { 23, TIFF_LONG, 1, ED_UNK, "MinoltaMaxAperture", "Maximum Lens Aperture", NULL }, { 26, TIFF_LONG, 1, ED_VRB, "MinoltaRmbrFileNum", "File Number Memory", minolta_bool }, { 27, TIFF_LONG, 1, ED_VRB, "MinoltaSequence", "Sequence Number", NULL }, { 31, TIFF_LONG, 1, ED_IMG, "MinoltaSaturate", "Saturation", NULL }, { 32, TIFF_LONG, 1, ED_IMG, "MinoltaContrast", "Contrast", NULL }, { 33, TIFF_LONG, 1, ED_IMG, "MinoltaSharpness", "Sharpness", minolta_sharp }, { 34, TIFF_LONG, 1, ED_IMG, "MinoltaScene", "Scene Capture Type", minolta_scene }, { 35, TIFF_LONG, 1, ED_IMG, "MinoltaFlashComp", "Flash Compensation", NULL }, { 36, TIFF_LONG, 1, ED_VRB, "MinoltaISO", "ISO Speed Rating", minolta_iso }, { 37, TIFF_LONG, 1, ED_UNK, "MinoltaModel", "Camera Model", minolta_model }, { 38, TIFF_LONG, 1, ED_VRB, "MinoltaIntervalMode", "Interval Mode", minolta_bool }, { 39, TIFF_LONG, 1, ED_VRB, "MinoltaFolder", "Folder Name", minolta_folder }, { 40, TIFF_LONG, 1, ED_IMG, "MinoltaColorMode", "Color Mode", minolta_color }, { 41, TIFF_LONG, 1, ED_IMG, "MinoltaColorFilt", "Color Warming", NULL }, { 42, TIFF_LONG, 1, ED_IMG, "MinoltaBWFilt", "Black & White Tone", NULL }, { 43, TIFF_LONG, 1, ED_VRB, "MinoltaIntFlash", "Internal Flash", minolta_bool }, { 45, TIFF_LONG, 1, ED_VRB, "MinoltaFocusX", "AF Point X", NULL }, { 46, TIFF_LONG, 1, ED_VRB, "MinoltaFocusY", "AF Point Y", NULL }, { 47, TIFF_LONG, 1, ED_VRB, "MinoltaWFocusZone", "AF Zone", minolta_widefocus }, { 48, TIFF_LONG, 1, ED_IMG, "MinoltaFocusMode", "Focus Mode", minolta_focusmode }, { 49, TIFF_LONG, 1, ED_IMG, "MinoltaAFArea", "Wide Focus Area", minolta_focusarea }, { 50, TIFF_LONG, 1, ED_IMG, "MinoltaBracketMode", "Bracketing Mode", minolta_brackmode }, { 51, TIFF_LONG, 1, ED_VRB, "MinoltaDataImprint", "Data Imprint", minolta_imprint }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "MinoltaUnknown", "Minolta Field Unknown", NULL }, }; /* Stub to display unknown fields for some models. */ static struct exiftag minolta_unkn[] = { { 0xffff, TIFF_UNKN, 0, ED_UNK, "MinoltaUnknown", "Minolta Field Unknown", NULL }, }; /* * Process maker note tag 0x0001 and 0x0003 fields. */ void minolta_cprop(struct exifprop *prop, unsigned char *off, struct exiftags *t, struct exiftag *thetags) { unsigned int i, j, k; u_int32_t v; int32_t model; double d; char *valbuf; unsigned char buf[8]; struct exifprop *aprop; valbuf = NULL; model = -1; for (i = 0; i * 4 < prop->count; i++) { /* * XXX It appears that the 7Hi oddly inserts a value at * position 51, pushing everything down one. We'll just * skip #51. */ if (thetags == minolta_MLT0 && i >= 51 && model == 5) { if (i == 51) continue; k = i - 1; } else k = i; aprop = childprop(prop); aprop->tag = i; aprop->tagset = thetags; /* Note: these are big-endian regardless. */ aprop->value = exif4byte(off + (4 * i), BIG); /* Lookup property name and description. */ for (j = 0; thetags[j].tag < EXIF_T_UNKNOWN && thetags[j].tag != k; j++); aprop->name = thetags[j].name; aprop->descr = thetags[j].descr; aprop->lvl = thetags[j].lvl; if (thetags[j].table) aprop->str = finddescr(thetags[j].table, (u_int16_t)aprop->value); dumpprop(aprop, NULL); /* * Further process known properties. * XXX If currently unsupported fields are implemented, * this section will have to be specific to the set of * tags passed in. */ if (thetags != minolta_MLT0) continue; if (!valbuf) exifstralloc(&valbuf, 16); switch (k) { /* Interval time and sequence number. */ case 16: case 27: aprop->value += 1; break; /* Exposure and flash compensation. */ case 13: case 35: aprop->str = valbuf; valbuf = NULL; if (aprop->value != 6) snprintf(aprop->str, 15, "%+0.1f EV", ((double)aprop->value - 6) / 3); else snprintf(aprop->str, 15, "Normal"); break; /* Camera model (saved for 7Hi stupidity). */ case 37: model = aprop->value; break; /* Focal length. */ case 18: aprop->str = valbuf; valbuf = NULL; snprintf(aprop->str, 15, "%02f", (double)aprop->value / 256); break; /* Still unknown. */ case 28: case 29: case 30: aprop->str = valbuf; valbuf = NULL; snprintf(aprop->str, 15, "%0.6f", (double)aprop->value / 256); break; /* Film speed. */ case 8: aprop->str = valbuf; valbuf = NULL; v = (u_int16_t)(pow(2, ((double)aprop->value / 8) - 1) * (double)3.125); snprintf(aprop->str, 15, "%d", v); break; /* Aperture and max aperture. */ case 10: case 23: aprop->str = valbuf; valbuf = NULL; d = pow(2, ((double)aprop->value / 16) - 0.5); snprintf(aprop->str, 15, "%0.1f", d); break; /* Exposure time. */ case 9: aprop->str = valbuf; valbuf = NULL; d = (double)pow(2, ((double)abs(48 - aprop->value)) / 8); /* 1 sec limit. */ if (aprop->value < 56) snprintf(aprop->str, 15, "%0.1f", d); else snprintf(aprop->str, 15, "1/%d", (unsigned int)d); #if 0 /* * Bulb mode D7i bug: always recorded as 30 sec in * EXIF_T_EXPOSURE, so override. */ if (aprop->value < 32) { aprop->override = EXIF_T_EXPOSURE; aprop->lvl = ED_IMG; } #endif break; /* Focus distance. */ case 19: aprop->str = valbuf; valbuf = NULL; if (!aprop->value) strcpy(aprop->str, "Infinite"); else snprintf(aprop->str, 15, "%.1f", (float)(aprop->value / (float)1000)); aprop->value /= 100; break; /* Exposure program. */ case 1: aprop->override = EXIF_T_EXPPROG; break; /* Date. */ case 21: aprop->str = valbuf; valbuf = NULL; byte4exif(aprop->value, buf, LITTLE); snprintf(aprop->str, 15, "%02d/%02d/%04d", buf[0], buf[1], buf[3] << 8 | buf[2]); break; /* Time. */ case 22: aprop->str = valbuf; valbuf = NULL; byte4exif(aprop->value, buf, LITTLE); snprintf(aprop->str, 9, "%02d:%02d:%02d", buf[2], buf[1], buf[0]); break; /* White balance. */ case 3: aprop->override = EXIF_T_WHITEBAL; break; /* Sharpness. */ case 33: aprop->override = EXIF_T_SHARPNESS; break; /* Metering mode. */ case 7: aprop->override = EXIF_T_METERMODE; break; /* Saturation, contrast, & color filter. */ case 31: case 32: aprop->override = (i == 31 ? EXIF_T_SATURATION : EXIF_T_CONTRAST); /* FALLTHROUGH */ case 41: aprop->str = valbuf; valbuf = NULL; aprop->value -= 3; if (aprop->value) snprintf(aprop->str, 15, "%+d", aprop->value); else strcpy(aprop->str, "Normal"); break; /* Scene. */ case 34: aprop->override = EXIF_T_SCENECAPTYPE; break; } } if (valbuf) free(valbuf); } /* * Make sure meaningless values are meaningless. */ static void minolta_naval(struct exifprop *props, struct exiftag *tags, int16_t tag) { struct exifprop *prop; const char *na = "n/a"; if (!(prop = findprop(props, tags, tag))) return; free(prop->str); prop->str = NULL; exifstralloc(&prop->str, strlen(na) + 1); strcpy(prop->str, na); if (!(prop->lvl & ED_UNK)) prop->lvl = ED_VRB; } /* * Process Minolta maker note tags. */ void minolta_prop(struct exifprop *prop, struct exiftags *t) { struct exiftag *fielddefs = NULL; struct exifprop *tmpprop; if (debug) { static int once = 0; /* XXX Breaks on multiple files. */ if (!once) { printf("Processing Minolta Maker Note\n"); once = 1; } dumpprop(prop, NULL); } switch (prop->tag) { /* Maker note type. */ case 0x0000: if (prop->count < 4) break; exifstralloc(&prop->str, prop->count + 1); byte4exif(prop->value, (unsigned char *)prop->str, t->mkrmd.order); /* We recognize two types: MLT0 and mlt0. */ if (strcmp(prop->str, "MLT0") && strcmp(prop->str, "mlt0")) exifwarn2("Minolta maker note version not supported", prop->str); break; /* * Various image data. * For now, we only trust specifically-sized tags. */ case 0x0001: if (prop->count != 39 * 4) { exifwarn("Minolta maker note not fully supported"); fielddefs = minolta_unkn; } else fielddefs = minolta_MLT0; minolta_cprop(prop, t->mkrmd.btiff + prop->value, t, fielddefs); break; case 0x0003: if (prop->count != 56 * 4 && prop->count != 57 * 4) { exifwarn("Minolta maker note not fully supported"); fielddefs = minolta_unkn; } else fielddefs = minolta_MLT0; minolta_cprop(prop, t->mkrmd.btiff + prop->value, t, fielddefs); break; } /* Override meaningless values. */ if (fielddefs) { /* Drive mode (bracketing step & mode). */ if ((tmpprop = findprop(t->props, fielddefs, 6))) if (tmpprop->value != 4) { minolta_naval(t->props, fielddefs, 14); minolta_naval(t->props, fielddefs, 50); } /* Focus mode (wide focus area, AF zone, point X & Y). */ if ((tmpprop = findprop(t->props, fielddefs, 48))) if (tmpprop->value == 1) { minolta_naval(t->props, fielddefs, 45); minolta_naval(t->props, fielddefs, 46); minolta_naval(t->props, fielddefs, 47); minolta_naval(t->props, fielddefs, 49); } /* Flash fired (flash comp, mode, & internal flash). */ if ((tmpprop = findprop(t->props, fielddefs, 20))) if (tmpprop->value != 1) { minolta_naval(t->props, fielddefs, 2); minolta_naval(t->props, fielddefs, 35); minolta_naval(t->props, fielddefs, 43); } /* Exposure mode (meter mode, exposure comp). */ if ((tmpprop = findprop(t->props, tags, EXIF_T_EXPMODE))) if (tmpprop->value == 1) { minolta_naval(t->props, fielddefs, 7); minolta_naval(t->props, fielddefs, 13); } /* Exposure prog (scene capture type). */ if ((tmpprop = findprop(t->props, fielddefs, 1))) if (tmpprop->value != 0) minolta_naval(t->props, fielddefs, 34); /* Interval mode (interval pics, time). */ if ((tmpprop = findprop(t->props, fielddefs, 38))) if (tmpprop->value != 1) { minolta_naval(t->props, fielddefs, 16); minolta_naval(t->props, fielddefs, 17); } } } /* * Try to read a Minolta maker note IFD, which differs by model. */ struct ifd * minolta_ifd(u_int32_t offset, struct tiffmeta *md) { /* DiMAGE E201. */ if (!strcmp((const char *)(md->btiff + offset), "+M")) { exifwarn("Minolta maker note version not supported"); return (NULL); } /* * Assume that if IFD num > 255 or < 2, this isn't a real IFD. * Takes care of the unfortunate DiMAGE 2300 & EX. */ if (exif2byte(md->btiff + offset, md->order) > 0xff || exif2byte(md->btiff + offset, md->order) < 0x02) { exifwarn("Minolta maker note version not supported"); return (NULL); } return (readifds(offset, minolta_tags, md)); } Image-EXIF-2.01/nikon.c0000644000076500000000000004305211753243142013455 0ustar aaronwheel/* * Copyright (c) 2001-2005, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: nikon.c,v 1.27 2005/01/04 23:29:31 ejohnst Exp $ */ /* * Exif tag definitions for Nikon maker notes. * * Some information for Nikon D1X support obtained from JoJoThumb, version * 2.7.2 (http://www.jojosoftware.de/jojothumb/). * * Updated with data from * http://www.ozhiker.com/electronics/pjmt/jpeg_info/nikon_mn.html. * */ #include #include #include #include "makers.h" /* Quality. */ static struct descrip nikon_quality[] = { { 1, "VGA Basic" }, { 2, "VGA Normal" }, { 3, "VGA Fine" }, { 4, "SXGA Basic" }, { 5, "SXGA Normal" }, { 6, "SXGA Fine" }, { 10, "UXGA Basic" }, { 11, "UXGA Normal" }, { 12, "UXGA Fine" }, { -1, "Unknown" }, }; /* Color. */ static struct descrip nikon_color[] = { { 1, "Color" }, { 2, "Monochrome" }, { -1, "Unknown" }, }; /* Image adjustment. */ static struct descrip nikon_adjust[] = { { 0, "Normal" }, { 1, "Bright(+)" }, { 2, "Bright(-)" }, { 3, "Contrast(+)" }, { 4, "Contrast(-)" }, { -1, "Unknown" }, }; /* CCD sensitivity. */ static struct descrip nikon_ccd[] = { { 0, "ISO 80" }, { 2, "ISO 160" }, { 4, "ISO 320" }, { 5, "ISO 100" }, { -1, "Unknown" }, }; /* White balance. */ static struct descrip nikon_white[] = { { 0, "Auto" }, { 1, "Preset" }, { 2, "Daylight" }, { 3, "Incandescent" }, { 4, "Fluorescent" }, { 5, "Cloudy" }, { 6, "Speedlight" }, { -1, "Unknown" }, }; /* Converter. */ static struct descrip nikon_convert[] = { { 0, "None" }, { 2, "Fisheye" }, { -1, "Unknown" }, }; /* Flash. */ static struct descrip nikon_flash[] = { { 0, "No" }, { 9, "Fired" }, { -1, "Unknown" }, }; /* Lens type. */ static struct descrip nikon_lenstype[] = { { 6, "Nikon D Series" }, { 14, "Nikon G Series" }, { -1, "Unknown" }, }; /* Shooting mode. */ static struct descrip nikon_shoot[] = { { 0, "Single Frame" }, { 1, "Continuous" }, { 2, "Timer" }, { 3, "Remote Timer" }, { 4, "Remote" }, { -1, "Unknown" }, }; /* Auto focus position. */ static struct descrip nikon_afpos[] = { { 0, "Center" }, { 1, "Top" }, { 2, "Bottom" }, { 3, "Left" }, { 4, "Right" }, { -1, "Unknown" }, }; /* Auto focus mode. */ static struct descrip nikon_afmode[] = { { 0, "Single Area" }, { 1, "Dynamic Area" }, { 2, "Closest Subject" }, { -1, "Unknown" }, }; /* Old school Nikon "lookup" maker note IFD tags. */ static struct exiftag nikon_tags0[] = { { 0x0003, TIFF_SHORT, 1, ED_IMG, "NikonQuality", "Image Quality", nikon_quality }, { 0x0004, TIFF_SHORT, 1, ED_IMG, "NikonColor", "Color Mode", nikon_color }, { 0x0005, TIFF_SHORT, 1, ED_IMG, "NikonImgAdjust", "Image Adjustment", nikon_adjust }, { 0x0006, TIFF_SHORT, 1, ED_IMG, "NikonCCDSensitive", "CCD Sensitivity", nikon_ccd }, { 0x0007, TIFF_SHORT, 1, ED_IMG, "NikonWhiteBal", "White Balance", nikon_white }, { 0x0008, TIFF_RTNL, 1, ED_UNK, "NikonFocus", "Focus", NULL }, { 0x000a, TIFF_RTNL, 1, ED_IMG, "NikonDigiZoom", "Digital Zoom", NULL }, { 0x000b, TIFF_SHORT, 1, ED_IMG, "NikonAdapter", "Lens Adapter", nikon_convert }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "Unknown", "Nikon Unknown", NULL }, }; /* Newer Nikon ASCII maker note IFD tags. */ static struct exiftag nikon_tags1[] = { { 0x0001, TIFF_UNDEF, 4, ED_VRB, "NikonVersion", "Nikon Note Version", NULL }, { 0x0002, TIFF_SHORT, 2, ED_IMG, "NikonISOUsed", "ISO Speed Used", NULL }, { 0x0003, TIFF_ASCII, 0, ED_IMG, "NikonColorMode1", "Color Mode", NULL }, { 0x0004, TIFF_ASCII, 0, ED_IMG, "NikonQuality", "Image Quality", NULL }, { 0x0005, TIFF_ASCII, 0, ED_IMG, "NikonWhiteBal", "White Balance", NULL }, { 0x0006, TIFF_ASCII, 0, ED_IMG, "NikonImgSharp", "Image Sharpening", NULL }, { 0x0007, TIFF_ASCII, 0, ED_IMG, "NikonFocusMode", "Focus Mode", NULL }, { 0x0008, TIFF_ASCII, 0, ED_IMG, "NikonFlashSet", "Flash Setting", NULL }, { 0x0009, TIFF_ASCII, 0, ED_IMG, "NikonAutoFlash", "Auto Flash Mode", NULL }, { 0x000b, TIFF_SSHORT, 1, ED_UNK, "NikonWhiteBalBias", "White Balance Bias", NULL }, { 0x000f, TIFF_ASCII, 0, ED_IMG, "NikonISOSelect", "ISO Selection", NULL }, { 0x0012, TIFF_UNDEF, 4, ED_IMG, "NikonFlashComp", "Flash Compensation", NULL }, { 0x0013, TIFF_SHORT, 2, ED_IMG, "NikonISOReq", "ISO Speed Requested", NULL }, { 0x0018, TIFF_UNDEF, 4, ED_IMG, "NikonFlashBrackComp", "Flash Bracket Compensation", NULL }, { 0x0019, TIFF_SRTNL, 1, ED_IMG, "NikonAEBrackComp", "AE Bracket Compensation", NULL }, { 0x0080, TIFF_ASCII, 0, ED_IMG, "NikonImgAdjust", "Image Adjustment", NULL }, { 0x0081, TIFF_ASCII, 0, ED_IMG, "NikonToneComp", "Tone Compensation", NULL }, { 0x0082, TIFF_ASCII, 0, ED_IMG, "NikonLensAdapter", "Lens Adapter", NULL }, { 0x0083, TIFF_BYTE, 1, ED_IMG, "NikonLensType", "Lens Type", NULL }, { 0x0084, TIFF_RTNL, 4, ED_IMG, "NikonLensRange", "Lens Range", NULL }, { 0x0085, TIFF_RTNL, 1, ED_IMG, "NikonFocusDist", "Focus Distance", NULL }, { 0x0086, TIFF_RTNL, 1, ED_IMG, "NikonDigiZoom", "Digital Zoom", NULL }, { 0x0087, TIFF_BYTE, 1, ED_VRB, "NikonFlashUsed", "Flash Used", nikon_flash }, { 0x0088, TIFF_UNDEF, 4, ED_IMG, "NikonAutoFocus", "Auto Focus", NULL }, /* Is either BYTE (D100) or SHORT (D70). */ { 0x0089, TIFF_UNKN, 1, ED_IMG, "NikonShootBrack", "Shooting/Bracketing Mode", NULL }, { 0x008d, TIFF_ASCII, 0, ED_IMG, "NikonColorMode2", "Color Mode", NULL }, { 0x008f, TIFF_ASCII, 0, ED_IMG, "NikonSceneMode", "Scene Mode", NULL }, { 0x0090, TIFF_ASCII, 0, ED_IMG, "NikonLighting", "Lighting Type", NULL }, { 0x0092, TIFF_SSHORT, 1, ED_UNK, "NikonHueAdjust", "Hue Adjustment", NULL }, { 0x0094, TIFF_SSHORT, 1, ED_IMG, "NikonSaturate", "Saturation", NULL }, { 0x0095, TIFF_ASCII, 0, ED_IMG, "NikonNoiseReduce", "Noise Reduction", NULL }, { 0x00a0, TIFF_ASCII, 0, ED_CAM, "NikonSerial", "Serial Number", NULL }, { 0x00a7, TIFF_LONG, 1, ED_IMG, "NikonAcuations", "Camera Actuations", NULL }, { 0x00a9, TIFF_ASCII, 0, ED_IMG, "NikonImageOpt", "Image Optimization", NULL }, { 0x00aa, TIFF_ASCII, 0, ED_IMG, "NikonSaturate2", "Saturation 2", NULL }, { 0x00ab, TIFF_ASCII, 0, ED_IMG, "NikonDigiProg", "Digital Vari-Program", NULL }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "Unknown", "Nikon Unknown", NULL }, }; /* * Process older Nikon maker note tags. */ static void nikon_prop0(struct exifprop *prop, struct exiftags *t) { u_int32_t a, b; switch (prop->tag) { /* Digital zoom. */ case 0x000a: a = exif4byte(t->mkrmd.btiff + prop->value, t->mkrmd.order); b = exif4byte(t->mkrmd.btiff + prop->value + 4, t->mkrmd.order); if (!a) { snprintf(prop->str, 31, "None"); prop->lvl = ED_VRB; } else snprintf(prop->str, 31, "x%.1f", (float)a / (float)b); break; } } /* * Process newer Nikon maker note tags. */ static void nikon_prop1(struct exifprop *prop, struct exiftags *t) { int i; u_int32_t v[8]; char *c1, *c2, *c3; int32_t sn, sd; char buf[5]; switch (prop->tag) { /* * Nikon maker note version. * XXX Note that earlier versions aren't ASCII, and that we * don't handle them yet. */ case 0x0001: byte4exif(prop->value, (unsigned char *)buf, t->mkrmd.order); buf[4] = '\0'; v[1] = atoi(buf + 2); buf[2] = '\0'; v[0] = atoi(buf); exifstralloc(&prop->str, 8); snprintf(prop->str, 7, "%d.%d", v[0], v[1]); break; /* * ISO values. Two shorts stuffed into the value; we only care * about the second one. (First is always zero?) */ case 0x0002: case 0x0013: /* * XXX Well, this is messy. Nikon stuffs the two shorts into * into the tag value, rather than referencing an offset. * Byte order screws with us here... (Need to fix!) */ if (t->mkrmd.order == LITTLE) v[0] = (prop->value >> 16) & 0xffff; else v[0] = prop->value & 0xffff; exifstralloc(&prop->str, 32); snprintf(prop->str, 31, "%d", (u_int16_t)v[0]); if (!v[0]) prop->lvl = ED_VRB; break; /* White balance. */ case 0x0005: prop->override = EXIF_T_WHITEBAL; break; /* Flash [bracket] compensation. Four values here; we only know one. */ case 0x0012: case 0x0018: exifstralloc(&prop->str, 10); snprintf(prop->str, 9, "%.1f EV", (int16_t)(prop->value >> 24) / 6.0); break; /* AE bracket compensation. */ case 0x0019: sn = exif4byte(t->mkrmd.btiff + prop->value, t->mkrmd.order); sd = exif4byte(t->mkrmd.btiff + prop->value + 4, t->mkrmd.order); if (sn && !sd) { snprintf(prop->str, 31, "n/a"); prop->lvl = ED_VRB; } else snprintf(prop->str, 31, "%.1f EV", (float)sn / (float)sd); break; /* Lens type. */ case 0x0083: prop->str = finddescr(nikon_lenstype, (u_int16_t)((prop->value >> 24) & 0xff)); break; /* Lens range. */ case 0x0084: if (prop->value + prop->count * 8 > (u_int32_t)(t->mkrmd.etiff - t->mkrmd.btiff)) break; for (i = 0; i < 8; i++) v[i] = exif4byte(t->mkrmd.btiff + prop->value + (i * 4), t->mkrmd.order); if ((v[0] && !v[1]) || (v[2] && !v[3]) || (v[4] && !v[5]) || (v[6] && !v[7])) { snprintf(prop->str, 31, "n/a"); prop->lvl = ED_VRB; break; } /* XXX Err, kind of a mess. */ if (v[0] == v[2] && v[1] == v[3]) { if (v[4] == v[6] && v[5] == v[7]) { snprintf(prop->str, 31, "%.1f mm; f/%.1f", (float)v[0] / (float)v[1], (float)v[4] / (float)v[5]); break; } snprintf(prop->str, 31, "%.1f mm; f/%.1f - f/%.1f", (float)v[0] / (float)v[1], (float)v[4] / (float)v[5], (float)v[6] / (float)v[7]); break; } if (v[4] == v[6] && v[5] == v[7]) { snprintf(prop->str, 31, "%.1f - %.1f mm; f/%.1f", (float)v[0] / (float)v[1], (float)v[2] / (float)v[3], (float)v[4] / (float)v[5]); break; } snprintf(prop->str, 31, "%.1f - %.1f mm; f/%.1f - f/%.1f", (float)v[0] / (float)v[1], (float)v[2] / (float)v[3], (float)v[4] / (float)v[5], (float)v[6] / (float)v[7]); break; /* Manual focus distance. */ case 0x0085: v[0] = exif4byte(t->mkrmd.btiff + prop->value, t->mkrmd.order); v[1] = exif4byte(t->mkrmd.btiff + prop->value + 4, t->mkrmd.order); if (v[0] == v[1] || (v[0] && !v[1])) { snprintf(prop->str, 31, "n/a"); prop->lvl = ED_VRB; } else snprintf(prop->str, 31, "x%.1f m", (float)v[0] / (float)v[1]); break; /* Digital zoom. */ case 0x0086: v[0] = exif4byte(t->mkrmd.btiff + prop->value, t->mkrmd.order); v[1] = exif4byte(t->mkrmd.btiff + prop->value + 4, t->mkrmd.order); if (v[0] == v[1] || !v[0] || (v[0] && !v[1])) { snprintf(prop->str, 31, "None"); prop->lvl = ED_VRB; } else snprintf(prop->str, 31, "x%.1f", (float)v[0] / (float)v[1]); break; /* * Auto focus position. * XXX Need some feedback from users here -- guessing somewhat. */ case 0x0088: /* * An older/simpler method? (Byte 3 only.) * Note that cameras using the newer method will get caught * here on Single Area, Center (and just show Center). */ if (!(prop->value & 0xffff00ff)) { if (prop->str) printf("err, hello? overwriting?\n"); prop->str = finddescr(nikon_afpos, (u_int16_t)((prop->value >> 8) & 0xff)); break; } /* Byte 1, mode. */ c1 = finddescr(nikon_afmode, (u_int16_t)((prop->value >> 24) & 0xff)); /* Byte 2, area selected; byte 4, area focused. */ c2 = finddescr(nikon_afpos, (u_int16_t)(prop->value & 0xff)); if ((prop->value & 0xff) == ((prop->value >> 16) & 0xff)) { exifstralloc(&prop->str, strlen(c1) + strlen(c2) + 3); sprintf(prop->str, "%s, %s", c1, c2); } else { c3 = finddescr(nikon_afpos, (u_int16_t)((prop->value >> 16) & 0xff)); exifstralloc(&prop->str, strlen(c1) + strlen(c2) + strlen(c3) + 24); sprintf(prop->str, "%s, %s Selected, %s Focused", c1, c3, c2); free(c3); } free(c1); free(c2); break; /* * Bracketing/shooting mode. * XXX I've probably made this a lot more complicated than it * needs to be. Would be nice to be able to experiment... */ case 0x0089: /* XXX Shouldn't be necessary. */ if (prop->type == TIFF_BYTE) prop->value = (prop->value >> 24) & 0xff; else if (prop->type == TIFF_SHORT) prop->value = (prop->value >> 8) & 0xff; /* Bits 0 & 1. */ c1 = finddescr(nikon_shoot, (u_int16_t)(prop->value & 0x03)); /* Bit 4 = bracketing, bit 6 = white balance bracketing. */ if (prop->value & 0x40) { if (prop->value & 0x10) c2 = "On, White Balance"; else c2 = "Off, White Balance"; } else { if (prop->value & 0x10) c2 = "On"; else c2 = "Off"; } exifstralloc(&prop->str, strlen(c1) + strlen(c2) + 2); sprintf(prop->str, "%s/%s", c1, c2); free(c1); break; /* Color mode. */ case 0x008d: if (!(c1 = prop->str)) break; if (!strncmp(c1, "MODE1a", 6)) { free(c1); prop->str = NULL; c1 = "Portrait sRGB"; exifstralloc(&prop->str, strlen(c1) + 1); strcpy(prop->str, c1); break; } if (!strncmp(c1, "MODE2", 5)) { free(c1); prop->str = NULL; c1 = "Adobe RGB"; exifstralloc(&prop->str, strlen(c1) + 1); strcpy(prop->str, c1); break; } if (!strncmp(c1, "MODE3a", 6)) { free(c1); prop->str = NULL; c1 = "Landscape sRGB"; exifstralloc(&prop->str, strlen(c1) + 1); strcpy(prop->str, c1); break; } break; /* Saturation. (Signed, so can't just do lookup table.) */ case 0x0094: c1 = NULL; switch (prop->value) { case -3: c1 = "Black & White"; exifstralloc(&prop->str, strlen(c1) + 1); strcpy(prop->str, c1); break; case 0: c1 = "Normal"; exifstralloc(&prop->str, strlen(c1) + 1); strcpy(prop->str, c1); break; } if (!c1) { prop->lvl = ED_VRB; break; } /* FALLTHROUGH */ case 0x00aa: prop->override = EXIF_T_SATURATION; break; /* Serial number. */ case 0x00a0: /* Remove prefix. */ if (!strncmp(prop->str, "NO= ", 4)) memmove(prop->str, prop->str + 4, strlen(prop->str + 4) + 1); /* Remove leading whitespace. */ for (c1 = prop->str; *c1 && *c1 == (unsigned char)' '; c1++); if (*c1 && c1 > prop->str) memmove(prop->str, c1, strlen(c1) + 1); break; } } /* * Process Nikon maker note tags. */ void nikon_prop(struct exifprop *prop, struct exiftags *t) { int i; for (i = 0; prop->tagset[i].tag < EXIF_T_UNKNOWN && prop->tagset[i].tag != prop->tag; i++); if (prop->tagset[i].type && prop->tagset[i].type != prop->type) exifwarn2("field type mismatch", prop->name); /* * Check the field count. * XXX For whatever the reason, Sigma doesn't follow the * spec on count for FileSource. */ if (prop->tagset[i].count && prop->tagset[i].count != prop->count) exifwarn2("field count mismatch", prop->name); if (prop->tagset == nikon_tags0) { nikon_prop0(prop, t); return; } if (prop->tagset == nikon_tags1) { nikon_prop1(prop, t); return; } } /* * Try to read a Nikon maker note IFD. */ struct ifd * nikon_ifd(u_int32_t offset, struct tiffmeta *md) { struct ifd *myifd; unsigned char *b; b = md->btiff + offset; /* * Seems that some Nikon maker notes start with an ID string and * a version of some sort. */ if (!strcmp((const char *)b, "Nikon")) { b += 6; switch (exif2byte(b, BIG)) { case 0x0100: readifd(offset + 8, &myifd, nikon_tags0, md); return (myifd); case 0x0200: case 0x0210: b += 4; /* * So, this is interesting: they've put a full-fledged * TIFF header here. */ /* Determine endianness of the TIFF data. */ if (!memcmp(b, "MM", 2)) md->order = BIG; else if (!memcmp(b, "II", 2)) md->order = LITTLE; else { exifwarn("invalid Nikon TIFF header"); return (NULL); } md->btiff = b; /* Beginning of maker. */ b += 2; /* Verify the TIFF header. */ if (exif2byte(b, md->order) != 42) { exifwarn("invalid Nikon TIFF header"); return (NULL); } b += 2; readifd(exif4byte(b, md->order), &myifd, nikon_tags1, md); return (myifd); default: exifwarn("Nikon maker note version not supported"); return (NULL); } } /* * Others are just normal IFDs. */ readifd(offset, &myifd, nikon_tags1, md); return (myifd); } Image-EXIF-2.01/olympus.c0000644000076500000000000001200111753243142014035 0ustar aaronwheel/* * Copyright (c) 2001-2003, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: olympus.c,v 1.17 2004/12/23 20:38:52 ejohnst Exp $ */ /* * Exif tag definitions for Olympus maker notes. * XXX Support here is somewhat mediocre -- my example image doesn't seem * to have proper values for most tags. * */ #include #include #include #include "makers.h" /* Macro mode. */ static struct descrip olympus_macro[] = { { 0, "Normal" }, { 1, "Macro" }, { -1, "Unknown" }, }; /* Quality. */ static struct descrip olympus_quality[] = { { 1, "SQ" }, { 2, "HQ" }, { 3, "SHQ" }, { -1, "Unknown" }, }; /* Maker note IFD tags. */ static struct exiftag olympus_tags[] = { { 0x0200, TIFF_LONG, 3, ED_UNK, "OlympusShootMode", "Shooting Mode", NULL }, { 0x0201, TIFF_SHORT, 1, ED_IMG, "OlympusQuality", "Compression Setting", olympus_quality }, { 0x0202, TIFF_SHORT, 1, ED_IMG, "OlympusMacroMode", "Macro Mode", olympus_macro }, { 0x0204, TIFF_RTNL, 1, ED_UNK, "OlympusDigiZoom", "Digital Zoom", NULL }, { 0x0207, TIFF_ASCII, 5, ED_UNK, "FirmwareVer", "Firmware Version", NULL }, { 0x0208, TIFF_ASCII, 52, ED_UNK, "OlympusPicInfo", "Picture Info", NULL }, { 0x0209, TIFF_UNKN, 32, ED_UNK, "OlympusCameraID", "Camera ID", NULL }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "Unknown", "Olympus Unknown", NULL }, }; /* * Process Olympus maker note tags. */ void olympus_prop(struct exifprop *prop, struct exiftags *t) { u_int32_t a, b; unsigned char *offset; struct exifprop *aprop; switch (prop->tag) { /* Various image data. */ case 0x0200: offset = t->mkrmd.btiff + prop->value; /* * XXX Would be helpful to test this with a panoramic. * According to Peter Esherick these values are unsigned * longs; however, it appears they may be shorts. Need to * experiment. */ /* Picture taking mode. */ aprop = childprop(prop); aprop->value = exif4byte(offset, t->mkrmd.order); aprop->name = "OlympusPicMode"; aprop->descr = "Picture Mode"; aprop->lvl = ED_UNK; /* Sequence number. */ aprop = childprop(prop); aprop->value = exif4byte(offset + 4, t->mkrmd.order); aprop->name = "OlympusSeqNum"; aprop->descr = "Sequence Number"; aprop->lvl = ED_UNK; /* Panorama direction. */ aprop = childprop(prop); aprop->value = exif4byte(offset + 8, t->mkrmd.order); aprop->name = "OlympusPanDir"; aprop->descr = "Panoramic Direction"; aprop->lvl = ED_UNK; break; /* Digital zoom. */ case 0x0204: a = exif4byte(t->mkrmd.btiff + prop->value, t->mkrmd.order); b = exif4byte(t->mkrmd.btiff + prop->value + 4, t->mkrmd.order); if (a == b) snprintf(prop->str, 31, "None"); else snprintf(prop->str, 31, "x%.1f", (float)a / (float)b); break; /* Image number. */ case 0x0008: exifstralloc(&prop->str, 32); snprintf(prop->str, 31, "%03d-%04d", prop->value / 10000, prop->value % 10000); break; } } /* * Try to read an Olympus maker note IFD. */ struct ifd * olympus_ifd(u_int32_t offset, struct tiffmeta *md) { struct ifd *myifd; /* * Seems that Olympus maker notes start with an ID string. Therefore, * try reading the IFD starting at offset + 8 ("OLYMP" + 3). */ if (!strcmp((const char *)(md->btiff + offset), "OLYMP")) readifd(offset + strlen("OLYMP") + 3, &myifd, olympus_tags, md); else readifd(offset, &myifd, olympus_tags, md); return (myifd); } Image-EXIF-2.01/panasonic.c0000644000076500000000000001376211753243142014317 0ustar aaronwheel/* * Copyright (c) 2004, Tom Hughes * Copyright (c) 2004, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: panasonic.c,v 1.6 2004/12/28 17:33:22 ejohnst Exp $ * */ /* * Exif tag definitions for Panasonic Lumix maker notes. * Tags deciphered by Tom Hughes ; updated for FZ20 * by Laurent Monin & Lee Kindness . * * Tested models: DMC-FZ10, DMC-FZ20. * */ #include #include #include #include "makers.h" /* Image quality. */ static struct descrip panasonic_quality[] = { { 2, "Fine" }, { 3, "Standard" }, { -1, "Unknown" }, }; /* White balance. */ static struct descrip panasonic_whitebal[] = { { 1, "Auto" }, { 2, "Daylight" }, { 3, "Cloudy" }, { 4, "Halogen" }, { 5, "Manual" }, { 8, "Flash" }, { -1, "Unknown" }, }; /* Focus mode. */ static struct descrip panasonic_focus[] = { { 1, "Auto" }, { 2, "Manual" }, { -1, "Unknown" }, }; /* Spot mode. */ static struct descrip panasonic_spot[] = { { 256, "On" }, { 4096, "Off" }, { -1, "Unknown" }, }; /* Optical Image Stabilizer mode. */ static struct descrip panasonic_ois[] = { { 2, "Mode 1" }, { 3, "Off" }, { 4, "Mode 2" }, { -1, "Unknown" }, }; /* Macro. */ static struct descrip panasonic_macro[] = { { 1, "Macro" }, { 2, "Normal" }, { -1, "Unknown" }, }; /* Shooting mode. */ static struct descrip panasonic_shoot[] = { { 2, "Portrait" }, { 3, "Scenery" }, { 4, "Sports" }, { 5, "Night Portrait" }, { 6, "Program" }, { 7, "Aperture Priority" }, { 8, "Shutter Priority" }, { 9, "Macro" }, { 11, "Manual" }, { 13, "Panning" }, { 18, "Fireworks" }, { 19, "Party" }, { 20, "Snow" }, { 21, "Night Scenery" }, { -1, "Unknown" }, }; /* Audio. */ static struct descrip panasonic_audio[] = { { 1, "Yes" }, { 2, "No" }, { -1, "Unknown" }, }; /* Color effect. */ static struct descrip panasonic_color[] = { { 1, "Off" }, { 2, "Warm" }, { 3, "Cool" }, { 4, "Black & White" }, { 5, "Sepia" }, { -1, "Unknown" }, }; /* Contrast & noise. */ static struct descrip panasonic_range[] = { { 0, "Standard" }, { 1, "Low" }, { 2, "High" }, { -1, "Unknown" }, }; /* Maker note IFD tags. */ static struct exiftag panasonic_tags0[] = { { 0x0001, TIFF_SHORT, 1, ED_IMG, "PanasonicQuality", "Image Quality", panasonic_quality }, { 0x0003, TIFF_SHORT, 1, ED_IMG, "PanasonicWhiteB", "White Balance", panasonic_whitebal }, { 0x0007, TIFF_SHORT, 1, ED_IMG, "PanasonicFocus", "Focus Mode", panasonic_focus }, { 0x000f, TIFF_BYTE, 1, ED_IMG, "PanasonicSpotMode", "Spot Mode", panasonic_spot }, { 0x001a, TIFF_SHORT, 1, ED_IMG, "PanasonicOIS", "Image Stabilizer", panasonic_ois }, { 0x001c, TIFF_SHORT, 1, ED_IMG, "PanasonicMacroMode", "Macro Mode", panasonic_macro }, { 0x001f, TIFF_SHORT, 1, ED_IMG, "PanasonicShootMode", "Shooting Mode", panasonic_shoot }, { 0x0020, TIFF_SHORT, 1, ED_IMG, "PanasonicAudio", "Audio", panasonic_audio }, { 0x0023, TIFF_SHORT, 1, ED_UNK, "PanasonicWBAdjust", "White Balance Adjust", NULL }, { 0x0024, TIFF_SSHORT, 1, ED_IMG, "PanasonicFlashBias", "Flash Bias", NULL }, { 0x0028, TIFF_SHORT, 1, ED_IMG, "PanasonicColorEffect", "Color Effect", panasonic_color }, { 0x002c, TIFF_SHORT, 1, ED_IMG, "PanasonicContrast", "Contrast", panasonic_range }, { 0x002d, TIFF_SHORT, 1, ED_IMG, "PanasonicNoiseReduce", "Noise Reduction", panasonic_range }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "PanasonicUnknown", "Panasonic Unknown", NULL }, }; /* * Process Panasonic maker note tags. */ void panasonic_prop(struct exifprop *prop, struct exiftags *t) { switch (prop->tag) { /* White balance. */ case 0x0003: prop->override = EXIF_T_WHITEBAL; break; /* White balance adjust (unknown). */ case 0x0023: exifstralloc(&prop->str, 10); snprintf(prop->str, 9, "%d", (int16_t)prop->value); break; /* Flash bias. */ case 0x0024: exifstralloc(&prop->str, 10); snprintf(prop->str, 9, "%.2f EV", (int16_t)prop->value / 3.0); break; /* Contrast. */ case 0x002c: prop->override = EXIF_T_CONTRAST; break; } } /* * Try to read a Panasonic maker note IFD. */ struct ifd * panasonic_ifd(u_int32_t offset, struct tiffmeta *md) { if (memcmp("Panasonic\0\0\0", md->btiff + offset, 12)) { exifwarn("Maker note format not supported"); return (NULL); } return (readifds(offset + 12, panasonic_tags0, md)); } Image-EXIF-2.01/README0000644000076500000000000000476011753243142013056 0ustar aaronwheelImage::EXIF =========== Perl package Image::EXIF based on exiftags by Eric M. Johnston: http://johnst.org/sw/exiftags/. Installation ============ To install this module type the following: perl Makefile.PL make make test make install COPYRIGHT AND LICENCE ===================== This package contains code taken from exiftags, which is distributed under the following terms: Copyright (c) 2001-2007, Eric M. Johnston All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by Eric M. Johnston. 4. Neither the name of the author nor the names of any co-contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The remaining code is: Copyright 2003, 2004, 2005 Sergey s Prozhogin Copyright 2012 Aaron Crane and it may be modified and/or redistributed under the same terms. BUG REPORTING ============= Please report bugs at either of the following locations: https://rt.cpan.org/Public/Dist/Display.html?Name=Image-EXIF https://github.com/arc/p5-image-exif Image-EXIF-2.01/sanyo.c0000644000076500000000000002224211753243142013466 0ustar aaronwheel/* * Copyright (c) 2003, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: sanyo.c,v 1.4 2004/12/23 20:38:52 ejohnst Exp $ */ /* * Exif tag definitions for Sanyo maker notes. * Developed from http://www.exif.org/makernotes/SanyoMakerNote.html. * */ #include #include #include #include "makers.h" /* Macro mode. */ static struct descrip sanyo_macro[] = { { 0, "Normal" }, { 1, "Macro" }, { -1, "Unknown" }, }; /* Quality. */ static struct descrip sanyo_quality[] = { { 0, "Normal" }, { 1, "Fine" }, { 2, "Superfine" }, { -1, "Unknown" }, }; /* Resolution. */ static struct descrip sanyo_res[] = { { 0, "Very Low Resolution" }, { 1, "Low Resolution" }, { 2, "Medium Low Resolution" }, { 3, "Medium Resolution" }, { 4, "Medium High Resolution" }, { 5, "High Resolution" }, { 6, "Very High Resolution" }, { 7, "Super High Resolution" }, { -1, "Unknown Resolution" }, }; /* Sequential shot method. */ static struct descrip sanyo_seqshot[] = { { 0, "None" }, { 1, "Standard" }, { 2, "Best" }, { 3, "Adjust Exposure" }, { -1, "Unknown" }, }; /* Boolean value. */ static struct descrip sanyo_offon[] = { { 0, "Off" }, { 1, "On" }, { -1, "Unknown" }, }; /* Record shutter release. */ static struct descrip sanyo_shutter[] = { { 0, "Record While Held" }, { 1, "Press to Start, Stop" }, { -1, "Unknown" }, }; /* Enabled/disabled value. */ static struct descrip sanyo_toggle[] = { { 0, "Disabled" }, { 1, "Enabled" }, { -1, "Unknown" }, }; /* Yes/no value. */ static struct descrip sanyo_noyes[] = { { 0, "No" }, { 1, "Yes" }, { -1, "Unknown" }, }; /* Scene selection. */ static struct descrip sanyo_scene[] = { { 0, "Off" }, { 1, "Sport" }, { 2, "TV" }, { 3, "Night" }, { 4, "User 1" }, { 5, "User 2" }, { -1, "Unknown" }, }; /* Sequential shot interval. */ static struct descrip sanyo_interval[] = { { 0, "5 frames/sec" }, { 1, "10 frames/sec" }, { 2, "15 frames/sec" }, { 3, "20 frames/sec" }, { -1, "Unknown" }, }; /* Flash mode. */ static struct descrip sanyo_flash[] = { { 0, "Auto" }, { 1, "Force" }, { 2, "Disabled" }, { 3, "Red-Eye" }, { -1, "Unknown" }, }; /* Maker note IFD tags. */ static struct exiftag sanyo_tags[] = { { 0x0100, TIFF_UNKN, 0, ED_UNK, "SanyoThumb", "JPEG Thumbnail", NULL }, { 0x0200, TIFF_LONG, 3, ED_VRB, "SanyoShootMode", "Shooting Mode", NULL }, { 0x0201, TIFF_SHORT, 1, ED_IMG, "SanyoQuality", "Quality Setting", NULL }, { 0x0202, TIFF_SHORT, 1, ED_IMG, "SanyoMacroMode", "Macro Mode", sanyo_macro }, { 0x0204, TIFF_RTNL, 1, ED_IMG, "SanyoDigiZoom", "Digital Zoom", NULL }, { 0x0207, TIFF_ASCII, 5, ED_IMG, "SanyoFirmware", "Firmware Version", NULL }, { 0x0208, TIFF_ASCII, 52, ED_IMG, "SanyoPicInfo", "Picture Info", NULL }, { 0x0209, TIFF_UNKN, 32, ED_UNK, "SanyoCameraID", "Camera ID", NULL }, { 0x020e, TIFF_SHORT, 1, ED_IMG, "SanyoSeqShot", "Sequential Shot Method", sanyo_seqshot }, { 0x020f, TIFF_SHORT, 1, ED_IMG, "SanyoWideRange", "Wide Range", sanyo_offon }, { 0x0210, TIFF_SHORT, 1, ED_IMG, "SanyoColorAdjust", "Color Adjustment", NULL }, { 0x0213, TIFF_SHORT, 1, ED_IMG, "SanyoQuickShot", "Quick Shot", sanyo_offon }, { 0x0214, TIFF_SHORT, 1, ED_IMG, "SanyoSelfTime", "Self Timer", sanyo_offon }, { 0x0216, TIFF_SHORT, 1, ED_IMG, "SanyoVoiceMemo", "Voice Memo", sanyo_offon }, { 0x0217, TIFF_SHORT, 1, ED_IMG, "SanyoRecShutter", "Record Shutter Release", sanyo_shutter }, { 0x0218, TIFF_SHORT, 1, ED_IMG, "SanyoFlicker", "Flicker Reduce", sanyo_offon }, { 0x0219, TIFF_SHORT, 1, ED_IMG, "SanyoOpticalZoom", "Optical Zoom", sanyo_toggle }, { 0x021b, TIFF_SHORT, 1, ED_IMG, "SanyoDigiZoom", "Digital Zoom", sanyo_toggle }, { 0x021d, TIFF_SHORT, 1, ED_IMG, "SanyoLightSrc", "Special Light Source", sanyo_offon }, { 0x021e, TIFF_SHORT, 1, ED_IMG, "SanyoResaved", "Image Re-saved", sanyo_noyes }, { 0x021f, TIFF_SHORT, 1, ED_IMG, "SanyoScene", "Scene Selection", sanyo_scene }, { 0x0223, TIFF_SHORT, 1, ED_IMG, "SanyoFocalDist", "Focal Distance", NULL }, { 0x0224, TIFF_SHORT, 1, ED_IMG, "SanyoSeqInterval", "Sequential Shot Interval", sanyo_interval }, { 0x0225, TIFF_SHORT, 1, ED_IMG, "SanyoFlash", "Flash Mode", sanyo_flash }, { 0x0e00, TIFF_UNKN, 0, ED_UNK, "SanyoPrintIM", "Print IM Flags", NULL }, { 0x0f00, TIFF_UNKN, 0, ED_UNK, "SanyoDump", "Data Dump", NULL }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "SanyoUnknown", "Sanyo Unknown", NULL }, }; /* Picture mode. */ static struct descrip sanyo_picmode[] = { { 0, "Normal" }, { 2, "Fast" }, { 3, "Panorama" }, { -1, "Unknown" }, }; /* Panoramic direction. */ static struct descrip sanyo_pandir[] = { { 1, "Left to Right" }, { 2, "Right to Left" }, { 3, "Bottom to Top" }, { 4, "Top to Bottom" }, { -1, "Unknown" }, }; /* Shooting mode subtags. */ static struct exiftag sanyo_shoottags[] = { { 0x0000, TIFF_UNKN, 0, ED_IMG, "SanyoPicMode", "Picture Mode", sanyo_picmode }, { 0x0001, TIFF_UNKN, 0, ED_IMG, "SanyoSeqNum", "Sequence Number", NULL }, { 0x0002, TIFF_UNKN, 0, ED_IMG, "SanyoPanDir", "Panoramic Direction", sanyo_pandir }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "SanyoShootUnknown", "Sanyo Shooting Unknown", NULL }, }; /* * Process Sanyo maker note tags. */ void sanyo_prop(struct exifprop *prop, struct exiftags *t) { int i, j; u_int32_t a, b; char *c1, *c2; struct exifprop *aprop; switch (prop->tag) { /* Various image data. */ case 0x0200: if (debug) printf("Processing %s (0x%04X) directory, %d entries\n", prop->name, prop->tag, prop->count); for (i = 0; i < (int)prop->count; i++) { a = exif4byte(t->mkrmd.btiff + prop->value + i * 2, t->mkrmd.order); aprop = childprop(prop); aprop->value = a; aprop->tag = i; aprop->tagset = sanyo_shoottags; aprop->type = prop->type; aprop->count = 1; /* Lookup property name and description. */ for (j = 0; sanyo_shoottags[j].tag < EXIF_T_UNKNOWN && sanyo_shoottags[j].tag != i; j++); aprop->name = sanyo_shoottags[j].name; aprop->descr = sanyo_shoottags[j].descr; aprop->lvl = sanyo_shoottags[j].lvl; if (sanyo_shoottags[j].table) aprop->str = finddescr(sanyo_shoottags[j].table, (u_int16_t)a); switch (aprop->tag) { case 0x0001: if (!aprop->value) aprop->lvl = ED_VRB; aprop->value += 1; break; } dumpprop(aprop, NULL); } break; /* Image quality & resolution. */ case 0x0201: c1 = finddescr(sanyo_quality, (u_int16_t)((prop->value >> 8) & 0xff)); c2 = finddescr(sanyo_res, (u_int16_t)(prop->value & 0xff)); exifstralloc(&prop->str, strlen(c1) + strlen(c2) + 3); sprintf(prop->str, "%s, %s", c1, c2); free(c1); free(c2); break; /* Digital zoom. */ case 0x0204: a = exif4byte(t->mkrmd.btiff + prop->value, t->mkrmd.order); b = exif4byte(t->mkrmd.btiff + prop->value + 4, t->mkrmd.order); if (!a || !b || a == b) snprintf(prop->str, 31, "None"); else snprintf(prop->str, 31, "x%.1f", (float)a / (float)b); break; /* Color adjust. */ case 0x0210: prop->str = finddescr(sanyo_offon, (u_int16_t)(!!prop->value)); break; } } /* * Try to read a Sanyo maker note IFD. */ struct ifd * sanyo_ifd(u_int32_t offset, struct tiffmeta *md) { struct ifd *myifd; /* * Seems that Sanyo maker notes start with an ID string. Therefore, * try reading the IFD starting at offset + 8 ("SANYO" + 3). */ if (!strcmp((const char *)(md->btiff + offset), "SANYO")) readifd(offset + strlen("SANYO") + 3, &myifd, sanyo_tags, md); else readifd(offset, &myifd, sanyo_tags, md); return (myifd); } Image-EXIF-2.01/sigma.c0000644000076500000000000001276311753243142013444 0ustar aaronwheel/* * Copyright (c) 2004, 2005, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: sigma.c,v 1.6 2005/01/04 23:37:57 ejohnst Exp $ */ /* * Exif tag definitions for Sigma/Foveon maker notes. * Developed from http://www.x3f.info/technotes/FileDocs/MakerNoteDoc.html. * */ #include #include #include #include "makers.h" /* Maker note IFD tags. */ static struct exiftag sigma_tags[] = { { 0x0002, TIFF_ASCII, 0, ED_CAM, "SigmaSerial", "Serial Number", NULL }, { 0x0003, TIFF_ASCII, 0, ED_IMG, "SigmaDrive", "Drive Mode", NULL }, { 0x0004, TIFF_ASCII, 0, ED_IMG, "SigmaResolution", "Resolution", NULL }, { 0x0005, TIFF_ASCII, 0, ED_IMG, "SigmaAutofocus", "Autofocus Mode", NULL }, { 0x0006, TIFF_ASCII, 0, ED_IMG, "SigmaFocusSet", "Focus Setting", NULL }, { 0x0007, TIFF_ASCII, 0, ED_IMG, "SigmaWhiteBal", "White Balance", NULL }, { 0x0008, TIFF_ASCII, 0, ED_IMG, "SigmaExpMode", "Exposure Mode", NULL }, { 0x0009, TIFF_ASCII, 0, ED_IMG, "SigmaMeterMode", "Metering Mode", NULL }, { 0x000a, TIFF_ASCII, 0, ED_CAM, "SigmaLensRange", "Focal Length Range", NULL }, { 0x000b, TIFF_ASCII, 0, ED_VRB, "SigmaColor", "Color Space", NULL }, { 0x000c, TIFF_ASCII, 0, ED_IMG, "SigmaExposure", "Exposure", NULL }, { 0x000d, TIFF_ASCII, 0, ED_IMG, "SigmaContrast", "Contrast", NULL }, { 0x000e, TIFF_ASCII, 0, ED_IMG, "SigmaShadow", "Shadow", NULL }, { 0x000f, TIFF_ASCII, 0, ED_IMG, "SigmaHighlight", "Highlight", NULL }, { 0x0010, TIFF_ASCII, 0, ED_IMG, "SigmaSaturate", "Saturation", NULL }, { 0x0011, TIFF_ASCII, 0, ED_IMG, "SigmaSharp", "Sharpness", NULL }, { 0x0012, TIFF_ASCII, 0, ED_IMG, "SigmaFill", "Fill Light", NULL }, { 0x0014, TIFF_ASCII, 0, ED_IMG, "SigmaColorAdj", "Color Adjustment", NULL }, { 0x0015, TIFF_ASCII, 0, ED_IMG, "SigmaAdjMode", "Adjustment Mode", NULL }, { 0x0016, TIFF_ASCII, 0, ED_IMG, "SigmaQuality", "Quality", NULL }, { 0x0017, TIFF_ASCII, 0, ED_CAM, "SigmaFirmware", "Firmware Version", NULL }, { 0x0018, TIFF_ASCII, 0, ED_CAM, "SigmaSoftware", "Camera Software", NULL }, { 0x0019, TIFF_ASCII, 0, ED_IMG, "SigmaAutoBrack", "Auto Bracket", NULL }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "SigmaUnknown", "Sigma Unknown", NULL }, }; static void sigma_deprefix(char *str, const char *prefix) { int l; l = strlen(prefix); if (!strncmp(str, prefix, l)) memmove(str, str + l, strlen(str + l) + 1); } /* * Process Sigma maker note tags. */ void sigma_prop(struct exifprop *prop, struct exiftags *t) { /* Couldn't grok the value somewhere upstream, so nevermind. */ if (prop->type == TIFF_ASCII && !prop->str) return; /* * For these, I suppose it's safe to assume that the value prefix * will always be the same. But, for safety's sake... */ switch (prop->tag) { case 0x000c: sigma_deprefix(prop->str, "Expo:"); break; case 0x000d: sigma_deprefix(prop->str, "Cont:"); break; case 0x000e: sigma_deprefix(prop->str, "Shad:"); break; case 0x000f: sigma_deprefix(prop->str, "High:"); break; case 0x0010: sigma_deprefix(prop->str, "Satu:"); break; case 0x0011: sigma_deprefix(prop->str, "Shar:"); break; case 0x0012: sigma_deprefix(prop->str, "Fill:"); break; case 0x0014: sigma_deprefix(prop->str, "CC:"); break; case 0x0016: sigma_deprefix(prop->str, "Qual:"); break; } } /* * Try to read a Sigma maker note IFD. */ struct ifd * sigma_ifd(u_int32_t offset, struct tiffmeta *md) { /* * The IFD starts after an 10 byte ID string offset. The first * 8 bytes are a usual offset, but the next two bytes might be a * version of some sort. For now, we'll ignore it... */ if (memcmp("SIGMA\0\0\0", md->btiff + offset, 8) || memcmp("FOVEON\0\0", md->btiff + offset, 8)) return (readifds(offset + 10, sigma_tags, md)); exifwarn("Sigma maker note version not supported"); return (NULL); } Image-EXIF-2.01/tagdefs.c0000644000076500000000000004147611753243142013764 0ustar aaronwheel/* * Copyright (c) 2001-2004, Eric M. Johnston * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Eric M. Johnston. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: tagdefs.c,v 1.24 2004/12/28 07:13:01 ejohnst Exp $ */ /* * Exif tag definitions. * * Developed using the TIFF 6.0 specification: * (http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf) * and the EXIF 2.21 standard: (http://tsc.jeita.or.jp/avs/data/cp3451_1.pdf). * */ #include #include "exif.h" #include "exifint.h" /* TIFF 6.0 field types. */ struct fieldtype ftypes[] = { { TIFF_BYTE, "byte", 1 }, { TIFF_ASCII, "ascii", 1 }, { TIFF_SHORT, "short", 2 }, { TIFF_LONG, "long", 4 }, { TIFF_RTNL, "rational", 8 }, { TIFF_SBYTE, "sbyte", 1 }, /* not in Exif 2.2 */ { TIFF_UNDEF, "undefined", 1 }, { TIFF_SSHORT, "sshort", 2 }, /* not in Exif 2.2 */ { TIFF_SLONG, "slong", 4 }, { TIFF_SRTNL, "srational", 8 }, { TIFF_FLOAT, "float", 4 }, /* not in Exif 2.2 */ { TIFF_DBL, "double", 8 }, /* not in Exif 2.2 */ { TIFF_UNKN, "unknown", 0 }, }; /* * User comment types. All should be 8 bytes. */ struct descrip ucomment[] = { { TIFF_ASCII, "ASCII\0\0\0" }, { TIFF_UNDEF, "JIS\0\0\0\0\0" }, { TIFF_UNDEF, "UNICODE\0" }, { TIFF_UNDEF, "\0\0\0\0\0\0\0\0" }, { TIFF_UNDEF, NULL }, }; /* * Various tag value lookup tables. All are terminated by the value -1. */ /* Compression schemes. */ struct descrip compresss[] = { { 1, "Uncompressed" }, { 6, "JPEG Compression (Thumbnail)" }, { -1, "Unknown" }, }; /* Pixel compositions. */ struct descrip pixelcomps[] = { { 2, "RGB" }, { 6, "YCbCr" }, { -1, "Unknown" }, }; /* Image orientation in terms of rows and columns. */ struct descrip orients[] = { { 1, "Top, Left-Hand" }, { 2, "Top, Right-Hand" }, { 3, "Bottom, Right-Hand" }, { 4, "Bottom, Left-Hand" }, { 5, "Left-Hand, Top" }, { 6, "Right-Hand, Top" }, { 7, "Right-Hand, Bottom" }, { 8, "Left-Hand, Bottom" }, { -1, "Unknown" }, }; /* Planar configurations. */ struct descrip planarconfigs[] = { { 1, "Chunky Format" }, { 2, "Planar Format" }, { -1, "Unknown" }, }; /* Resolution units. */ struct descrip resunits[] = { { 2, "i" }, { 3, "cm" }, { -1, "" }, }; /* * Chrominance components sampling ratio. * Note: This only refers to the second short; first is assumed to be 2. */ struct descrip chromratios[] = { { 1, "YCbCr4:2:2" }, { 2, "YCbCr4:2:0" }, { -1, "Unknown" }, }; /* Chrominance components positioning. */ struct descrip chrompos[] = { { 1, "Centered" }, { 2, "Co-Sited" }, { -1, "Unknown" }, }; /* Exposure programs. */ struct descrip expprogs[] = { { 0, "Not Defined" }, { 1, "Manual" }, { 2, "Normal Program" }, { 3, "Aperture Priority" }, { 4, "Shutter Priority" }, { 5, "Creative" }, { 6, "Action" }, { 7, "Portrait Mode" }, { 8, "Landscape Mode" }, { -1, "Unknown" }, }; /* Component configuration. */ struct descrip compconfig[] = { { 0, "Does Not Exist" }, { 1, "Y" }, { 2, "Cb" }, { 3, "Cr" }, { 4, "R" }, { 5, "G" }, { 6, "B" }, { -1, "Unknown" }, }; /* Metering modes. */ struct descrip metermodes[] = { { 0, "Unknown" }, { 1, "Average" }, { 2, "Center Weighted Average" }, { 3, "Spot" }, { 4, "Multi Spot" }, { 5, "Pattern" }, { 6, "Partial" }, { 255, "Other" }, { -1, "Unknown" }, }; /* Light sources. */ struct descrip lightsrcs[] = { { 0, "Unknown" }, { 1, "Daylight" }, { 2, "Fluorescent" }, { 3, "Tungsten" }, { 4, "Flash" }, { 9, "Fine Weather" }, { 10, "Cloudy Weather" }, { 11, "Shade" }, { 12, "Daylight Fluorescent" }, { 13, "Day White Fluorescent" }, { 14, "Cool White Fluorescent" }, { 15, "White Fluorescent" }, { 17, "Standard Light A" }, { 18, "Standard Light B" }, { 19, "Standard Light C" }, { 20, "D55" }, { 21, "D65" }, { 22, "D75" }, { 23, "D50" }, { 24, "ISO Studio Tungsten" }, { 255, "Other" }, { -1, "Unknown" }, }; /* * Flash modes. * * The value is split into 5 sub-values: * Flash fired, bit 0; * Flash return, bits 1 & 2; * Flash mode, bits 3 & 4; * Flash function, bit 5; and * Red-eye mode, bit 6. * Bit 7 is unused in the 2.21 spec. * * We'll just process each sub-value individually and concatenate them. */ struct descrip flash_fire[] = { { 0x00, "No Flash" }, { 0x01, "Flash" }, { -1, "Unknown" }, }; struct descrip flash_return[] = { { 0x04, "Return Not Detected" }, { 0x06, "Return Detected" }, { -1, "Unknown" }, }; struct descrip flash_mode[] = { { 0x08, "Compulsory" }, { 0x10, "Compulsory" }, { 0x18, "Auto" }, { -1, "Unknown" }, }; struct descrip flash_func[] = { { 0x20, "No Flash Function" }, { -1, "Unknown" }, }; struct descrip flash_redeye[] = { { 0x40, "Red-Eye Reduce" }, { -1, "Unknown" }, }; /* Color spaces. */ struct descrip colorspcs[] = { { 1, "sRGB" }, {0xffff,"Uncalibrated" }, { -1, "Unknown" }, }; /* Image sensor types. */ struct descrip imgsensors[] = { { 1, "Not Defined" }, { 2, "One-Chip Color Area" }, { 3, "Two-Chip Color Area" }, { 4, "Three-Chip Color Area" }, { 5, "Color Sequential Area" }, { 7, "Trilinear" }, { 8, "Color Sequential Linear" }, { -1, "Unknown" }, }; /* File sources */ struct descrip filesrcs[] = { { 0, "Other" }, { 1, "Scanner (Transparent)" }, { 2, "Scanner (Reflex)" }, { 3, "Digital Still Camera" }, { -1, "Unknown" }, }; /* Scene types. */ struct descrip scenetypes[] = { { 1, "Directly Photographed" }, { -1, "Unknown" }, }; /* Custom rendering. */ struct descrip customrend[] = { { 0, "Normal" }, { 1, "Custom" }, { -1, "Unknown" }, }; /* Exposure mode. */ struct descrip expmode[] = { { 0, "Auto" }, { 1, "Manual" }, { 2, "Auto Bracket" }, { -1, "Unknown" }, }; /* White balance. */ struct descrip whitebal[] = { { 0, "Auto" }, { 1, "Manual" }, { -1, "Unknown" }, }; /* Scene capture type. */ struct descrip scenecaptypes[] = { { 0, "Standard" }, { 1, "Landscape" }, { 2, "Portrait" }, { 3, "Night Scene" }, { -1, "Unknown" }, }; /* Gain control. */ struct descrip gainctrl[] = { { 0, "None" }, { 1, "Low Gain Up" }, { 2, "High Gain Up" }, { 3, "Low Gain Down" }, { 4, "High Gain Down" }, { -1, "Unknown" }, }; /* Contrast & sharpness. */ struct descrip processrange[] = { { 0, "Normal" }, { 1, "Soft" }, { 2, "Hard" }, { -1, "Unknown" }, }; /* Saturation. */ struct descrip saturate[] = { { 0, "Normal" }, { 1, "Low" }, { 2, "High" }, { -1, "Unknown" }, }; /* Subject distance range. */ struct descrip subjdist[] = { { 1, "Macro" }, { 2, "Close View" }, { 3, "Distant View" }, { -1, "Unknown" }, }; /* Exif 2.2 tags. */ struct exiftag tags[] = { { 0x0100, TIFF_UNKN, 1, ED_IMG, /* columns */ "ImageWidth", "Image Width", NULL }, { 0x0101, TIFF_UNKN, 1, ED_IMG, /* rows */ "ImageLength", "Image Height", NULL }, { 0x0102, TIFF_SHORT, 3, ED_IMG, /* bits */ "BitsPerSample", "Number of Bits Per Component", NULL }, { 0x0103, TIFF_SHORT, 1, ED_IMG, "Compression", "Compression Scheme", compresss }, { 0x0106, TIFF_SHORT, 1, ED_IMG, "PhotometricInterpretation", "Pixel Composition", pixelcomps }, { 0x010a, TIFF_UNKN, 0, ED_UNK, "FillOrder", NULL, NULL }, { 0x010d, TIFF_UNKN, 0, ED_UNK, "DocumentName", NULL, NULL }, { 0x010e, TIFF_ASCII, 0, ED_UNK, "ImageDescription", "Title", NULL }, { 0x010f, TIFF_ASCII, 0, ED_CAM, "Make", "Equipment Make", NULL }, { 0x0110, TIFF_ASCII, 0, ED_CAM, "Model", "Camera Model", NULL }, { 0x0111, TIFF_UNKN, 0, ED_VRB, /* bytes */ "StripOffsets", "Image Data Location", NULL }, { 0x0112, TIFF_SHORT, 1, ED_IMG, "Orientation", "Image Orientation", orients }, { 0x0115, TIFF_SHORT, 1, ED_VRB, "SamplesPerPixel", "Number of Components", NULL }, { 0x0116, TIFF_UNKN, 1, ED_VRB, /* rows */ "RowsPerStrip", "Number of Rows Per Strip", NULL }, { 0x0117, TIFF_UNKN, 0, ED_VRB, /* bytes */ "StripByteCounts", "Bytes per Compressed Strip", NULL }, { 0x011a, TIFF_RTNL, 1, ED_IMG, /* dp[i|cm] */ "XResolution", "Horizontal Resolution", NULL }, { 0x011b, TIFF_RTNL, 1, ED_IMG, /* dp[i|cm] */ "YResolution", "Vertical Resolution", NULL }, { 0x011c, TIFF_SHORT, 1, ED_IMG, "PlanarConfiguration", "Image Data Arrangement", planarconfigs }, { 0x0128, TIFF_SHORT, 1, ED_VRB, "ResolutionUnit", "Resolution Unit", resunits }, { 0x012d, TIFF_SHORT, 0, ED_VRB, "TransferFunction", "Transfer Function", NULL }, { 0x0131, TIFF_ASCII, 0, ED_CAM, "Software", "Camera Software", NULL }, { 0x0132, TIFF_ASCII, 20, ED_IMG, "DateTime", "Image Created", NULL }, { 0x013b, TIFF_ASCII, 0, ED_CAM, "Artist", "Photographer", NULL }, { 0x013e, TIFF_RTNL, 2, ED_IMG, "WhitePoint", "White Point Chromaticity", NULL }, { 0x013f, TIFF_RTNL, 6, ED_VRB, "PrimaryChromaticities", "Chromaticities of Primary Colors", NULL }, { 0x0156, TIFF_UNKN, 0, ED_UNK, "TransferRange", NULL, NULL }, { 0x0200, TIFF_UNKN, 0, ED_UNK, "JPEGProc", NULL, NULL }, { 0x0201, TIFF_LONG, 1, ED_VRB, "JPEGInterchangeFormat", "Offset to JPEG SOI", NULL }, { 0x0202, TIFF_LONG, 1, ED_VRB, /* bytes */ "JPEGInterchangeFormatLength", "Bytes of JPEG Data", NULL }, { 0x0211, TIFF_RTNL, 3, ED_VRB, "YCbCrCoefficients", "Color Space Xform Matrix Coeff's", NULL }, { 0x0212, TIFF_SHORT, 2, ED_VRB, "YCbCrSubSampling", "Chrominance Comp Samp Ratio", chromratios }, { 0x0213, TIFF_SHORT, 1, ED_VRB, "YCbCrPositioning", "Chrominance Comp Positioning", chrompos }, { 0x0214, TIFF_RTNL, 6, ED_VRB, "ReferenceBlackWhite", "Black and White Ref Point Values", NULL }, { 0x828d, TIFF_UNKN, 0, ED_UNK, "CFARepeatPatternDim", NULL, NULL }, { 0x828e, TIFF_UNKN, 0, ED_UNK, "CFAPattern", NULL, NULL }, { 0x828f, TIFF_UNKN, 0, ED_UNK, "BatteryLevel", NULL, NULL }, { 0x8298, TIFF_ASCII, 0, ED_UNK, "Copyright", "Copyright", NULL }, { 0x829a, TIFF_RTNL, 1, ED_IMG, /* s */ "ExposureTime", "Exposure Time", NULL }, { 0x829d, TIFF_RTNL, 1, ED_IMG, "FNumber", "F-Number", NULL }, { 0x83bb, TIFF_UNKN, 0, ED_UNK, "IPTC/NAA", NULL, NULL }, { 0x8769, TIFF_LONG, 1, ED_VRB, "ExifOffset", "Exif IFD Pointer", NULL }, { 0x8773, TIFF_UNKN, 0, ED_UNK, "InterColorProfile", NULL, NULL }, { 0x8822, TIFF_SHORT, 1, ED_IMG, "ExposureProgram", "Exposure Program", expprogs }, { 0x8824, TIFF_ASCII, 0, ED_CAM, "SpectralSensitivity", "Spectral Sensitivity", NULL }, { 0x8825, TIFF_LONG, 1, ED_UNK, "GPSInfo", "GPS Info IFD Pointer", NULL }, { 0x8827, TIFF_SHORT, 0, ED_IMG, "ISOSpeedRatings", "ISO Speed Rating", NULL }, { 0x8828, TIFF_UNDEF, 0, ED_CAM, "OECF", "Opto-Electric Conversion Factor", NULL }, { 0x9000, TIFF_UNDEF, 4, ED_VRB, "ExifVersion", "Exif Version", NULL }, { 0x9003, TIFF_ASCII, 20, ED_VRB, "DateTimeOriginal", "Image Generated", NULL }, { 0x9004, TIFF_ASCII, 20, ED_VRB, "DateTimeDigitized", "Image Digitized", NULL }, { 0x9101, TIFF_UNDEF, 4, ED_VRB, "ComponentsConfiguration", "Meaning of Each Comp", compconfig }, { 0x9102, TIFF_RTNL, 1, ED_VRB, "CompressedBitsPerPixel", "Image Compression Mode", NULL }, { 0x9201, TIFF_SRTNL, 1, ED_IMG, /* s */ "ShutterSpeedValue", "Shutter Speed", NULL }, { 0x9202, TIFF_RTNL, 1, ED_IMG, "ApertureValue", "Lens Aperture", NULL }, { 0x9203, TIFF_SRTNL, 1, ED_IMG, "BrightnessValue", "Brightness", NULL }, { 0x9204, TIFF_SRTNL, 1, ED_IMG, "ExposureBiasValue", "Exposure Bias", NULL }, { 0x9205, TIFF_RTNL, 1, ED_PAS, "MaxApertureValue", "Maximum Lens Aperture", NULL }, { 0x9206, TIFF_RTNL, 1, ED_IMG, /* m */ "SubjectDistance", "Subject Distance", NULL }, { 0x9207, TIFF_SHORT, 1, ED_IMG, "MeteringMode", "Metering Mode", metermodes }, { 0x9208, TIFF_SHORT, 1, ED_IMG, "LightSource", "Light Source", lightsrcs }, { 0x9209, TIFF_SHORT, 1, ED_IMG, "Flash", "Flash", NULL }, { 0x920a, TIFF_RTNL, 1, ED_IMG, /* mm */ "FocalLength", "Focal Length", NULL }, { 0x9214, TIFF_SHORT, 0, ED_VRB, "SubjectArea", "Subject Area", NULL }, { 0x927c, TIFF_UNDEF, 0, ED_UNK, "MakerNote", "Manufacturer Notes", NULL }, { 0x9286, TIFF_UNDEF, 0, ED_UNK, "UserComment", "Comment", NULL }, { 0x9290, TIFF_ASCII, 0, ED_VRB, "SubsecTime", "DateTime Second Fraction", NULL }, { 0x9291, TIFF_ASCII, 0, ED_VRB, "SubsecTimeOrginal", "DateTimeOriginal Second Fraction", NULL }, { 0x9292, TIFF_ASCII, 0, ED_VRB, "SubsecTimeDigitized", "DateTimeDigitized Second Fraction", NULL }, { 0xa000, TIFF_UNDEF, 4, ED_UNK, "FlashPixVersion", "Supported FlashPix Version", NULL }, { 0xa001, TIFF_SHORT, 1, ED_IMG, "ColorSpace", "Color Space Information", colorspcs }, { 0xa002, TIFF_UNKN, 1, ED_IMG, /* pixels */ "PixelXDimension", "Image Width", NULL }, { 0xa003, TIFF_UNKN, 1, ED_IMG, /* pixels */ "PixelYDimension", "Image Height", NULL }, { 0xa004, TIFF_ASCII, 13, ED_UNK, "RelatedSoundFile", "Related Audio File", NULL }, { 0xa005, TIFF_LONG, 1, ED_UNK, "InteroperabilityOffset", "Interoperability IFD Pointer", NULL }, { 0xa20b, TIFF_RTNL, 1, ED_IMG, /* bcps */ "FlashEnergy", "Flash Energy", NULL }, { 0xa20c, TIFF_UNDEF, 0, ED_VRB, "SpatialFrequencyResponse", "Spatial Frequency Response", NULL }, { 0xa20e, TIFF_RTNL, 1, ED_VRB, /* dp[i|cm] */ "FocalPlaneXResolution", "Focal Plane Horiz Resolution", NULL }, { 0xa20f, TIFF_RTNL, 1, ED_VRB, /* dp[i|cm] */ "FocalPlaneYResolution", "Focal Plane Vert Resolution", NULL }, { 0xa210, TIFF_SHORT, 1, ED_VRB, "FocalPlaneResolutionUnit", "Focal Plane Res Unit", resunits }, { 0xa214, TIFF_SHORT, 2, ED_VRB, "SubjectLocation", "Subject Location", NULL }, { 0xa215, TIFF_RTNL, 1, ED_IMG, "ExposureIndex", "Exposure Index", NULL }, { 0xa217, TIFF_SHORT, 1, ED_CAM, "SensingMethod", "Sensing Method", imgsensors }, { 0xa300, TIFF_UNDEF, 1, ED_VRB, "FileSource", "File Source", NULL }, { 0xa301, TIFF_UNDEF, 1, ED_VRB, "SceneType", "Scene Type", scenetypes }, { 0xa302, TIFF_UNDEF, 0, ED_CAM, "CFAPattern", "Color Filter Array Pattern", NULL }, { 0xa401, TIFF_SHORT, 1, ED_IMG, "CustomRendered", "Rendering", customrend }, { 0xa402, TIFF_SHORT, 1, ED_IMG, "ExposureMode", "Exposure Mode", expmode }, { 0xa403, TIFF_SHORT, 1, ED_IMG, "WhiteBalance", "White Balance", whitebal }, { 0xa404, TIFF_RTNL, 1, ED_IMG, "DigitalZoomRatio", "Digital Zoom Ratio", NULL }, { 0xa405, TIFF_SHORT, 1, ED_PAS, /* mm */ "FocalLenIn35mmFilm", "Focal Length (35mm Equiv)", NULL }, { 0xa406, TIFF_SHORT, 1, ED_IMG, "SceneCaptureType", "Scene Capture Type", scenecaptypes }, { 0xa407, TIFF_SHORT, 1, ED_IMG, /* XXX typo in spec? */ "GainControl", "Gain Control", gainctrl }, { 0xa408, TIFF_SHORT, 1, ED_IMG, "Contrast", "Contrast", processrange }, { 0xa409, TIFF_SHORT, 1, ED_IMG, "Saturation", "Saturation", saturate }, { 0xa40a, TIFF_SHORT, 1, ED_IMG, "Sharpness", "Sharpness", processrange }, { 0xa40b, TIFF_UNDEF, 0, ED_UNK, "DeviceSettingDescr", "Device Settings", NULL }, { 0xa40c, TIFF_SHORT, 1, ED_IMG, "SubjectDistRange", "Subject Distance Range", subjdist }, { 0xa420, TIFF_ASCII, 33, ED_IMG, "ImageUniqueID", "Unique Image ID", NULL }, { 0xa500, TIFF_RTNL, 1, ED_UNK, "GammaCoefficient", "Gamma Coefficient", NULL }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "Unknown", NULL, NULL }, }; Image-EXIF-2.01/test.pl0000644000076500000000000000075311753243142013510 0ustar aaronwheel# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl test.pl' ######################### # change 'tests => 1' to 'tests => last_test_to_print'; use Test; BEGIN { plan tests => 1 }; use Image::EXIF; ok(1); # If we made it this far, we're ok. ######################### # Insert your test code below, the Test module is use()ed here so read # its man page ( perldoc Test ) for help writing this test script. Image-EXIF-2.01/typemap0000644000076500000000000000003411753243142013566 0ustar aaronwheelImage::EXIF T_PTROBJ