/* * 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: nikon.c,v 1.17 2003/08/16 03:02:16 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/). */ #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" }, { -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" }, { 2, "Preset" }, { 4, "Daylight" }, { 5, "Incandescent" }, { 5, "Fluorescent" }, { 5, "Cloudy" }, { 5, "Speedlight" }, { -1, "Unknown" }, }; /* Converter. */ static struct descrip nikon_convert[] = { { 0, "None" }, { 2, "Fisheye" }, { -1, "Unknown" }, }; /* Maker note IFD tags. */ static struct exiftag nikon_tags0[] = { { 0x0002, TIFF_SHORT, 2, ED_UNK, "NikonISOSet", "ISO Setting", NULL }, { 0x0003, TIFF_ASCII, 0, ED_IMG, "NikonColor", "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, "NikonSharp", "Image Sharpening", NULL }, { 0x0007, TIFF_ASCII, 0, ED_IMG, "NikonFocusMode", "Focus Mode", NULL }, { 0x0008, TIFF_ASCII, 0, ED_IMG, "NikonFlashSet", "Flash Setting", NULL }, { 0x000f, TIFF_ASCII, 0, ED_IMG, "NikonISOSelect", "ISO Selection", NULL }, { 0x0080, TIFF_ASCII, 0, ED_IMG, "NikonImgAdjust", "Image Adjustment", NULL }, { 0x0082, TIFF_ASCII, 0, ED_IMG, "NikonAdapter", "Lens Adapter", NULL }, { 0x0085, TIFF_ASCII, 0, ED_IMG, "NikonFocusDist", "Focus Distance", NULL }, { 0x0086, TIFF_ASCII, 0, ED_IMG, "NikonDigiZoom", "Digital Zoom", NULL }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "Unknown", "Nikon Unknown", NULL }, }; static struct exiftag nikon_tags1[] = { { 0x0003, TIFF_SHORT, 1, ED_UNK, "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 }, }; static struct exiftag nikon_tags2[] = { { 0x0001, TIFF_UNDEF, 4, ED_VRB, "NikonVersion", "Nikon Note Version", NULL }, { 0x0002, TIFF_SHORT, 2, ED_UNK, "NikonISOSetting", "ISO Setting", NULL }, { 0x0003, TIFF_ASCII, 0, ED_IMG, "NikonColor", "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, "NikonFocus", "Focus Mode", NULL }, { 0x0008, TIFF_ASCII, 0, ED_IMG, "NikonFlash", "Flash Setting", NULL }, { 0x000b, TIFF_UNKN, 0, ED_UNK, "NikonWhiteBalBias", "White Balance Bias", NULL }, { 0x0081, TIFF_ASCII, 0, ED_IMG, "NikonImgAdjust", "Image Adjustment", NULL }, { 0x0088, TIFF_UNDEF, 0, ED_UNK, "NikonAutoFocus", "Auto Focus Position", NULL }, { 0x0092, TIFF_UNDEF, 0, ED_UNK, "NikonHueAdjust", "Hue Adjustment", NULL }, { 0xffff, TIFF_UNKN, 0, ED_UNK, "NikonUnknown", "Nikon Unknown", NULL }, }; /* * Process normal Nikon maker note tags. */ static void nikon_prop0(struct exifprop *prop, struct exiftags *t) { u_int32_t a, b; switch (prop->tag) { /* Manual focus distance. */ case 0x0085: a = exif4byte(t->md.btiff + prop->value, t->md.order); b = exif4byte(t->md.btiff + prop->value + 4, t->md.order); if (a == b) { snprintf(prop->str, 31, "N/A"); prop->lvl = ED_VRB; } else snprintf(prop->str, 31, "x%.1f m", (float)a / (float)b); break; /* Digital zoom. */ case 0x0086: a = exif4byte(t->md.btiff + prop->value, t->md.order); b = exif4byte(t->md.btiff + prop->value + 4, t->md.order); if (a == b) { snprintf(prop->str, 31, "None"); prop->lvl = ED_VRB; } else snprintf(prop->str, 31, "x%.1f", (float)a / (float)b); break; } } /* * Process Nikon maker note tags that start from an offset. */ static void nikon_prop1(struct exifprop *prop, struct exiftags *t) { u_int32_t a, b; switch (prop->tag) { /* Digital zoom. */ case 0x000a: a = exif4byte(t->md.btiff + prop->value, t->md.order); b = exif4byte(t->md.btiff + prop->value + 4, t->md.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 Nikon maker note tags. */ void nikon_prop(struct exifprop *prop, struct exiftags *t) { if (prop->tagset == nikon_tags1) nikon_prop1(prop, t); else nikon_prop0(prop, t); } /* * 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; struct tiffmeta mkrmd; b = md->btiff + offset; mkrmd = *md; /* * Seems that some Nikon maker notes start with an ID string. */ if (!strcmp((const char *)b, "Nikon")) { b += 6; switch (exif2byte(b, md->order)) { case 0x0001: readifd(offset + 8, &myifd, nikon_tags1, &mkrmd); return (myifd); case 0x0200: b += 4; /* * So, this is interesting: they've put a full-fledged * TIFF header here. */ /* Determine endianness of the TIFF data. */ if (*((u_int16_t *)b) == 0x4d4d) mkrmd.order = BIG; else if (*((u_int16_t *)b) == 0x4949) mkrmd.order = LITTLE; else { exifwarn("invalid Nikon TIFF header"); return (NULL); } mkrmd.btiff = b; /* Beginning of maker. */ b += 2; /* Verify the TIFF header. */ if (exif2byte(b, mkrmd.order) != 42) { exifwarn("invalid Nikon TIFF header"); return (NULL); } b += 2; readifd(exif4byte(b, mkrmd.order), &myifd, nikon_tags2, &mkrmd); return (myifd); } } readifd(offset, &myifd, nikon_tags0, &mkrmd); return (myifd); }