134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Program to pull the information out of various types of EXIF digital 334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// camera files and show it in a reasonably consistent way 434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// This module parses the very complicated exif structures. 634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Matthias Wandel 834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include "jhead.h" 1034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <math.h> 1234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <ctype.h> 1334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#include <utils/Log.h> 1434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic unsigned char * DirWithThumbnailPtrs; 1634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic double FocalplaneXRes; 1734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic double FocalplaneUnits; 1834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int ExifImageWidth; 1934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int MotorolaOrder = 0; 2034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 2134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// for fixing the rotation. 2234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void * OrientationPtr[2]; 2334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic int OrientationNumFormat[2]; 2434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectint NumOrientations = 0; 2534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 2634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 2734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Define the line below to turn on poor man's debugging output 2834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#undef SUPERDEBUG 2934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 3034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 317a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block#define printf ALOGE 3234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 3334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 3434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 3534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Table of Jpeg encoding process names 3634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic const TagTable_t ProcessTable[] = { 3734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF0, "Baseline", 0, 0}, 3834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF1, "Extended sequential", 0, 0}, 3934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF2, "Progressive", 0, 0}, 4034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF3, "Lossless", 0, 0}, 4134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF5, "Differential sequential", 0, 0}, 4234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF6, "Differential progressive", 0, 0}, 4334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF7, "Differential lossless", 0, 0}, 4434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF9, "Extended sequential, arithmetic coding", 0, 0}, 4534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF10, "Progressive, arithmetic coding", 0, 0}, 4634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF11, "Lossless, arithmetic coding", 0, 0}, 4734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF13, "Differential sequential, arithmetic coding", 0, 0}, 4834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF14, "Differential progressive, arithmetic coding", 0, 0}, 4934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { M_SOF15, "Differential lossless, arithmetic coding", 0, 0}, 5034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}; 5134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define PROCESS_TABLE_SIZE (sizeof(ProcessTable) / sizeof(TagTable_t)) 5334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 1 - "The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side." 5534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 2 - "The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side." 5634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 3 - "The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side." 5734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 4 - "The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side." 5834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 5934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 5 - "The 0th row is the visual left-hand side of of the image, and the 0th column is the visual top." 6034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 6 - "The 0th row is the visual right-hand side of of the image, and the 0th column is the visual top." 6134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 7 - "The 0th row is the visual right-hand side of of the image, and the 0th column is the visual bottom." 6234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// 8 - "The 0th row is the visual left-hand side of of the image, and the 0th column is the visual bottom." 6334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Note: The descriptions here are the same as the name of the command line 6534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// option to pass to jpegtran to right the image 6634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 6734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic const char * OrientTab[9] = { 6834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "Undefined", 6934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "Normal", // 1 7034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "flip horizontal", // left right reversed mirror 7134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "rotate 180", // 3 7234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "flip vertical", // upside down mirror 7334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "transpose", // Flipped about top-left <--> bottom-right axis. 7434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "rotate 90", // rotate 90 cw to right it. 7534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "transverse", // flipped about top-right <--> bottom-left axis 7634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project "rotate 270", // rotate 270 to right it. 7734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project}; 7834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 7934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectconst int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8}; 8034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 8134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 8234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Describes tag values 8334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 84d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_INTEROP_INDEX 0x0001 85d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_INTEROP_VERSION 0x0002 86d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_IMAGE_WIDTH 0x0100 87d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_IMAGE_LENGTH 0x0101 88d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_BITS_PER_SAMPLE 0x0102 89d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_COMPRESSION 0x0103 90d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_PHOTOMETRIC_INTERP 0x0106 91d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_FILL_ORDER 0x010A 92d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_DOCUMENT_NAME 0x010D 93d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_IMAGE_DESCRIPTION 0x010E 94d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_MAKE 0x010F 95d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_MODEL 0x0110 96d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SRIP_OFFSET 0x0111 97d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_ORIENTATION 0x0112 98d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SAMPLES_PER_PIXEL 0x0115 99d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_ROWS_PER_STRIP 0x0116 100d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_STRIP_BYTE_COUNTS 0x0117 101d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_X_RESOLUTION 0x011A 102d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_Y_RESOLUTION 0x011B 103d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_PLANAR_CONFIGURATION 0x011C 104d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_RESOLUTION_UNIT 0x0128 105d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_TRANSFER_FUNCTION 0x012D 106d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SOFTWARE 0x0131 107d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_DATETIME 0x0132 108d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_ARTIST 0x013B 109d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_WHITE_POINT 0x013E 110d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_PRIMARY_CHROMATICITIES 0x013F 111d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_TRANSFER_RANGE 0x0156 112d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_JPEG_PROC 0x0200 113d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_THUMBNAIL_OFFSET 0x0201 114d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_THUMBNAIL_LENGTH 0x0202 115d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_Y_CB_CR_COEFFICIENTS 0x0211 116d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_Y_CB_CR_SUB_SAMPLING 0x0212 117d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_Y_CB_CR_POSITIONING 0x0213 118d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_REFERENCE_BLACK_WHITE 0x0214 119d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_RELATED_IMAGE_WIDTH 0x1001 120d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_RELATED_IMAGE_LENGTH 0x1002 121d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_CFA_REPEAT_PATTERN_DIM 0x828D 122d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_CFA_PATTERN1 0x828E 123d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_BATTERY_LEVEL 0x828F 124d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_COPYRIGHT 0x8298 125d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_EXPOSURETIME 0x829A 126d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_FNUMBER 0x829D 127d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_IPTC_NAA 0x83BB 128d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_EXIF_OFFSET 0x8769 129d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_INTER_COLOR_PROFILE 0x8773 130d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_EXPOSURE_PROGRAM 0x8822 131d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SPECTRAL_SENSITIVITY 0x8824 132d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_GPSINFO 0x8825 133d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_ISO_EQUIVALENT 0x8827 134d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_OECF 0x8828 135d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_EXIF_VERSION 0x9000 136d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_DATETIME_ORIGINAL 0x9003 137d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_DATETIME_DIGITIZED 0x9004 138d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_COMPONENTS_CONFIG 0x9101 139d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_CPRS_BITS_PER_PIXEL 0x9102 140d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SHUTTERSPEED 0x9201 141d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_APERTURE 0x9202 142d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_BRIGHTNESS_VALUE 0x9203 143d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_EXPOSURE_BIAS 0x9204 144d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_MAXAPERTURE 0x9205 145d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SUBJECT_DISTANCE 0x9206 146d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_METERING_MODE 0x9207 147d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_LIGHT_SOURCE 0x9208 148d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_FLASH 0x9209 149d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_FOCALLENGTH 0x920A 150d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_MAKER_NOTE 0x927C 151d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_USERCOMMENT 0x9286 152d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SUBSEC_TIME 0x9290 153d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SUBSEC_TIME_ORIG 0x9291 154d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SUBSEC_TIME_DIG 0x9292 155d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 156d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_WINXP_TITLE 0x9c9b // Windows XP - not part of exif standard. 157d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_WINXP_COMMENT 0x9c9c // Windows XP - not part of exif standard. 158d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_WINXP_AUTHOR 0x9c9d // Windows XP - not part of exif standard. 159d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_WINXP_KEYWORDS 0x9c9e // Windows XP - not part of exif standard. 160d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_WINXP_SUBJECT 0x9c9f // Windows XP - not part of exif standard. 161d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 162d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_FLASH_PIX_VERSION 0xA000 163d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_COLOR_SPACE 0xA001 164d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_EXIF_IMAGEWIDTH 0xA002 165d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_EXIF_IMAGELENGTH 0xA003 166d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_RELATED_AUDIO_FILE 0xA004 167d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_INTEROP_OFFSET 0xA005 168d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_FLASH_ENERGY 0xA20B 169d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SPATIAL_FREQ_RESP 0xA20C 170d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_FOCAL_PLANE_XRES 0xA20E 171d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_FOCAL_PLANE_YRES 0xA20F 172d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_FOCAL_PLANE_UNITS 0xA210 173d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SUBJECT_LOCATION 0xA214 174d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_EXPOSURE_INDEX 0xA215 175d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SENSING_METHOD 0xA217 176d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_FILE_SOURCE 0xA300 177d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SCENE_TYPE 0xA301 178d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_CFA_PATTERN 0xA302 179d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_CUSTOM_RENDERED 0xA401 180d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_EXPOSURE_MODE 0xA402 181d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_WHITEBALANCE 0xA403 182d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_DIGITALZOOMRATIO 0xA404 183d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_FOCALLENGTH_35MM 0xA405 184d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SCENE_CAPTURE_TYPE 0xA406 185d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_GAIN_CONTROL 0xA407 186d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_CONTRAST 0xA408 187d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SATURATION 0xA409 188d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_SHARPNESS 0xA40A 189d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang#define TAG_DISTANCE_RANGE 0xA40C 19034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 19134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// TODO: replace the ", 0" values in this table with the correct format, e.g. ", FMT_USHORT" 19234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic const TagTable_t TagTable[] = { 193d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_INTEROP_INDEX, "InteropIndex", 0, 0}, 194d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_INTEROP_VERSION, "InteropVersion", 0, 0}, 195d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_IMAGE_WIDTH, "ImageWidth", FMT_USHORT, 1}, 196d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_IMAGE_LENGTH, "ImageLength", FMT_USHORT, 1}, 197d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_BITS_PER_SAMPLE, "BitsPerSample", FMT_USHORT, 3}, 198d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_COMPRESSION, "Compression", FMT_USHORT, 1}, 199d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_PHOTOMETRIC_INTERP, "PhotometricInterpretation", FMT_USHORT, 1}, 200d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_FILL_ORDER, "FillOrder", 0, 0}, 201d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_DOCUMENT_NAME, "DocumentName", 0, 0}, 202d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_IMAGE_DESCRIPTION, "ImageDescription", 0, 0 }, 203d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_MAKE, "Make", FMT_STRING, -1}, 204d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_MODEL, "Model", FMT_STRING, -1}, 205d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SRIP_OFFSET, "StripOffsets", FMT_USHORT, 1}, 206d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_ORIENTATION, "Orientation", FMT_USHORT, 1}, 207d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SAMPLES_PER_PIXEL, "SamplesPerPixel", FMT_USHORT, 3}, 208d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_ROWS_PER_STRIP, "RowsPerStrip", FMT_USHORT, 1}, 209d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_STRIP_BYTE_COUNTS, "StripByteCounts", FMT_USHORT, 1}, 210d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_X_RESOLUTION, "XResolution", FMT_URATIONAL, 1}, 211d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_Y_RESOLUTION, "YResolution", FMT_URATIONAL, 1}, 212d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_PLANAR_CONFIGURATION, "PlanarConfiguration", FMT_USHORT, 1}, 213d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_RESOLUTION_UNIT, "ResolutionUnit", FMT_USHORT, 1}, 214d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_TRANSFER_FUNCTION, "TransferFunction", FMT_USHORT, 768}, 215d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SOFTWARE, "Software", FMT_STRING, -1}, 216d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_DATETIME, "DateTime", FMT_STRING, 20}, 217d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_ARTIST, "Artist", FMT_STRING, -1}, 218d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_WHITE_POINT, "WhitePoint", FMT_SRATIONAL, 2}, 219d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_PRIMARY_CHROMATICITIES, "PrimaryChromaticities", FMT_SRATIONAL, 6}, 220d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_TRANSFER_RANGE, "TransferRange", 0, 0}, 221d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_JPEG_PROC, "JPEGProc", 0, 0}, 222d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_THUMBNAIL_OFFSET, "ThumbnailOffset", 0, 0}, 223d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_THUMBNAIL_LENGTH, "ThumbnailLength", 0, 0}, 224d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_Y_CB_CR_COEFFICIENTS, "YCbCrCoefficients", FMT_SRATIONAL, 3}, 225d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_Y_CB_CR_SUB_SAMPLING, "YCbCrSubSampling", FMT_USHORT, 2}, 226d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_Y_CB_CR_POSITIONING, "YCbCrPositioning", FMT_USHORT, 1}, 227d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_REFERENCE_BLACK_WHITE, "ReferenceBlackWhite", FMT_SRATIONAL, 6}, 228d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_RELATED_IMAGE_WIDTH, "RelatedImageWidth", 0, 0}, 229d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_RELATED_IMAGE_LENGTH, "RelatedImageLength", 0, 0}, 230d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_CFA_REPEAT_PATTERN_DIM, "CFARepeatPatternDim", 0, 0}, 231d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_CFA_PATTERN1, "CFAPattern", 0, 0}, 232d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_BATTERY_LEVEL, "BatteryLevel", 0, 0}, 233d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_COPYRIGHT, "Copyright", FMT_STRING, -1}, 234754078052c687f6721536009c816644c73e4f145Tyler Luu { TAG_EXPOSURETIME, "ExposureTime", FMT_SRATIONAL, 1}, 235d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_FNUMBER, "FNumber", FMT_SRATIONAL, 1}, 236d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_IPTC_NAA, "IPTC/NAA", 0, 0}, 237d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_EXIF_OFFSET, "ExifOffset", 0, 0}, 238d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_INTER_COLOR_PROFILE, "InterColorProfile", 0, 0}, 239d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_EXPOSURE_PROGRAM, "ExposureProgram", FMT_SSHORT, 1}, 240d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SPECTRAL_SENSITIVITY, "SpectralSensitivity", FMT_STRING, -1}, 241d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_GPSINFO, "GPS Dir offset", 0, 0}, 242d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_ISO_EQUIVALENT, "ISOSpeedRatings", FMT_SSHORT, -1}, 243d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_OECF, "OECF", 0, 0}, 244d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_EXIF_VERSION, "ExifVersion", FMT_BYTE, 4}, 245d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_DATETIME_ORIGINAL, "DateTimeOriginal", FMT_STRING, 20}, 246d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_DATETIME_DIGITIZED, "DateTimeDigitized", FMT_STRING, 20}, 247d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_COMPONENTS_CONFIG, "ComponentsConfiguration", FMT_BYTE, 4}, 248d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_CPRS_BITS_PER_PIXEL, "CompressedBitsPerPixel", FMT_SRATIONAL, 1}, 249d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SHUTTERSPEED, "ShutterSpeedValue", FMT_SRATIONAL, 1}, 250d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_APERTURE, "ApertureValue", FMT_URATIONAL, 1}, 251d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_BRIGHTNESS_VALUE, "BrightnessValue", FMT_SRATIONAL, 1}, 252d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_EXPOSURE_BIAS, "ExposureBiasValue", FMT_SRATIONAL, 1}, 253d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_MAXAPERTURE, "MaxApertureValue", FMT_URATIONAL, 1}, 254d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SUBJECT_DISTANCE, "SubjectDistance", FMT_URATIONAL, 1}, 255d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_METERING_MODE, "MeteringMode", FMT_USHORT, 1}, 256d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_LIGHT_SOURCE, "LightSource", FMT_USHORT, 1}, 257d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_FLASH, "Flash", FMT_USHORT, 1}, 258d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_FOCALLENGTH, "FocalLength", FMT_URATIONAL, 1}, 259d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_MAKER_NOTE, "MakerNote", FMT_STRING, -1}, 260d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_USERCOMMENT, "UserComment", FMT_STRING, -1}, 261d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SUBSEC_TIME, "SubSecTime", FMT_STRING, -1}, 262d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SUBSEC_TIME_ORIG, "SubSecTimeOriginal", FMT_STRING, -1}, 263d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SUBSEC_TIME_DIG, "SubSecTimeDigitized", FMT_STRING, -1}, 264d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_WINXP_TITLE, "Windows-XP Title", 0, 0}, 265d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_WINXP_COMMENT, "Windows-XP comment", 0, 0}, 266d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_WINXP_AUTHOR, "Windows-XP author", 0, 0}, 267d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_WINXP_KEYWORDS, "Windows-XP keywords", 0, 0}, 268d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_WINXP_SUBJECT, "Windows-XP subject", 0, 0}, 269d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_FLASH_PIX_VERSION, "FlashPixVersion", FMT_BYTE, 4}, 270d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_COLOR_SPACE, "ColorSpace", FMT_USHORT, 1}, 271d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_EXIF_IMAGEWIDTH, "ExifImageWidth", 0, 0}, 272d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_EXIF_IMAGELENGTH, "ExifImageLength", 0, 0}, 273d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_RELATED_AUDIO_FILE, "RelatedAudioFile", 0, 0}, 274d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_INTEROP_OFFSET, "InteroperabilityOffset", 0, 0}, 275d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_FLASH_ENERGY, "FlashEnergy", FMT_URATIONAL, 1}, 276d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SPATIAL_FREQ_RESP, "SpatialFrequencyResponse", FMT_STRING, -1}, 277d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_FOCAL_PLANE_XRES, "FocalPlaneXResolution", FMT_URATIONAL, 1}, 278d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_FOCAL_PLANE_YRES, "FocalPlaneYResolution", FMT_URATIONAL, 1}, 279d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_FOCAL_PLANE_UNITS, "FocalPlaneResolutionUnit", FMT_USHORT, 1}, 280d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SUBJECT_LOCATION, "SubjectLocation", FMT_USHORT, 2}, 281d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_EXPOSURE_INDEX, "ExposureIndex", FMT_URATIONAL, 1}, 282d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SENSING_METHOD, "SensingMethod", FMT_USHORT, 1}, 283d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_FILE_SOURCE, "FileSource", 0, 1}, 284d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SCENE_TYPE, "SceneType", 0, 1}, 285d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_CFA_PATTERN, "CFA Pattern", 0, -1}, 286d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_CUSTOM_RENDERED, "CustomRendered", FMT_USHORT, 1}, 287d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_EXPOSURE_MODE, "ExposureMode", FMT_USHORT, 1}, 288d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_WHITEBALANCE, "WhiteBalance", FMT_USHORT, 1}, 289d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_DIGITALZOOMRATIO, "DigitalZoomRatio", FMT_URATIONAL, 1}, 290d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_FOCALLENGTH_35MM, "FocalLengthIn35mmFilm", FMT_USHORT, 1}, 291d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SCENE_CAPTURE_TYPE, "SceneCaptureType", FMT_USHORT, 1}, 292d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_GAIN_CONTROL, "GainControl", FMT_URATIONAL, 1}, 293d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_CONTRAST, "Contrast", FMT_USHORT, 1}, 294d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SATURATION, "Saturation", FMT_USHORT, 1}, 295d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_SHARPNESS, "Sharpness", FMT_USHORT, 1}, 296d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang { TAG_DISTANCE_RANGE, "SubjectDistanceRange", FMT_USHORT, 1}, 29734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} ; 29834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 29934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#define TAG_TABLE_SIZE (sizeof(TagTable) / sizeof(TagTable_t)) 30034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 30134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectint TagNameToValue(const char* tagName) 30234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 30334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned int i; 30434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (i = 0; i < TAG_TABLE_SIZE; i++) { 30534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (strcmp(TagTable[i].Desc, tagName) == 0) { 30634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("found tag %s val %d", TagTable[i].Desc, TagTable[i].Tag); 30734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return TagTable[i].Tag; 30834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 30934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 31034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("tag %s NOT FOUND", tagName); 31134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return -1; 31234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 31334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 314482486a3d21c4d4c933f3081ff14122292314bc7Angus Kongint IsDateTimeTag(unsigned short tag) 315482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong{ 316482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong return ((tag == TAG_DATETIME)? TRUE: FALSE); 317482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong} 318482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong 31934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 32034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Convert a 16 bit unsigned value to file's native byte order 32134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 32234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void Put16u(void * Short, unsigned short PutValue) 32334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 32434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (MotorolaOrder){ 32534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Short)[0] = (uchar)(PutValue>>8); 32634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Short)[1] = (uchar)PutValue; 32734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 32834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Short)[0] = (uchar)PutValue; 32934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Short)[1] = (uchar)(PutValue>>8); 33034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 33134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 33234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 33334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 33434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Convert a 16 bit unsigned value from file's native byte order 33534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 33634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectint Get16u(void * Short) 33734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 33834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (MotorolaOrder){ 33934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1]; 34034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 34134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return (((uchar *)Short)[1] << 8) | ((uchar *)Short)[0]; 34234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 34334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 34434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 34534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 34634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Convert a 32 bit signed value from file's native byte order 34734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 34834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectint Get32s(void * Long) 34934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 35034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (MotorolaOrder){ 35134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return ((( char *)Long)[0] << 24) | (((uchar *)Long)[1] << 16) 35234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project | (((uchar *)Long)[2] << 8 ) | (((uchar *)Long)[3] << 0 ); 35334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 35434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return ((( char *)Long)[3] << 24) | (((uchar *)Long)[2] << 16) 35534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project | (((uchar *)Long)[1] << 8 ) | (((uchar *)Long)[0] << 0 ); 35634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 35734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 35834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 35934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 36034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Convert a 32 bit unsigned value to file's native byte order 36134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 36234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid Put32u(void * Value, unsigned PutValue) 36334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 36434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (MotorolaOrder){ 36534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Value)[0] = (uchar)(PutValue>>24); 36634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Value)[1] = (uchar)(PutValue>>16); 36734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Value)[2] = (uchar)(PutValue>>8); 36834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Value)[3] = (uchar)PutValue; 36934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 37034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Value)[0] = (uchar)PutValue; 37134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Value)[1] = (uchar)(PutValue>>8); 37234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Value)[2] = (uchar)(PutValue>>16); 37334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)Value)[3] = (uchar)(PutValue>>24); 37434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 37534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 37634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 37734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 37834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Convert a 32 bit unsigned value from file's native byte order 37934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 38034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectunsigned Get32u(void * Long) 38134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 38234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return (unsigned)Get32s(Long) & 0xffffffff; 38334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 38434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 38534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 38634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Display a number as one of its many formats 38734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 38834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid PrintFormatNumber(void * ValuePtr, int Format, int ByteCount) 38934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 39034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int s,n; 39134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 392d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang for(n=0;n<16;n++){ 39334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(Format){ 39434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SBYTE: 39534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_BYTE: printf("%02x",*(uchar *)ValuePtr); s=1; break; 39634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_USHORT: printf("%d",Get16u(ValuePtr)); s=2; break; 39734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_ULONG: 39834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SLONG: printf("%d",Get32s(ValuePtr)); s=4; break; 39934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SSHORT: printf("%hd",(signed short)Get16u(ValuePtr)); s=2; break; 40034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_URATIONAL: 40134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SRATIONAL: 40234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("%d/%d",Get32s(ValuePtr), Get32s(4+(char *)ValuePtr)); 40334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project s = 8; 40434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 40534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 40634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SINGLE: printf("%f",(double)*(float *)ValuePtr); s=8; break; 40734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_DOUBLE: printf("%f",*(double *)ValuePtr); s=8; break; 40834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project default: 40934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Unknown format %d:", Format); 41034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 41134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 41234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ByteCount -= s; 41334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ByteCount <= 0) break; 41434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(", "); 41534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ValuePtr = (void *)((char *)ValuePtr + s); 41634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 41734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 418d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (n >= 16) printf("..."); 41934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 42034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 42134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 42234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 42334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Evaluate number, be it int, rational, or float from directory. 42434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 42534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectdouble ConvertAnyFormat(void * ValuePtr, int Format) 42634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 42734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project double Value; 42834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Value = 0; 42934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 43034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(Format){ 43134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SBYTE: Value = *(signed char *)ValuePtr; break; 43234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_BYTE: Value = *(uchar *)ValuePtr; break; 43334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 43434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_USHORT: Value = Get16u(ValuePtr); break; 43534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_ULONG: Value = Get32u(ValuePtr); break; 43634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 43734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_URATIONAL: 43834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SRATIONAL: 43934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 44034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int Num,Den; 44134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Num = Get32s(ValuePtr); 44234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Den = Get32s(4+(char *)ValuePtr); 44334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Den == 0){ 44434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Value = 0; 44534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 44634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Value = (double)Num/Den; 44734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 44834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 44934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 45034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 45134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SSHORT: Value = (signed short)Get16u(ValuePtr); break; 45234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SLONG: Value = Get32s(ValuePtr); break; 45334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 45434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Not sure if this is correct (never seen float used in Exif format) 45534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break; 45634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_DOUBLE: Value = *(double *)ValuePtr; break; 45734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 45834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project default: 45934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Illegal format code %d",Format,0); 46034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 46134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return Value; 46234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 46334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 46434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 46542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang// Convert a double value into a signed or unsigned rational number. 46642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang//-------------------------------------------------------------------------- 46742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Changstatic void float2urat(double value, unsigned int max, unsigned int *numerator, 46842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang unsigned int *denominator) { 46942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang if (value <= 0) { 47042c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *numerator = 0; 47142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *denominator = 1; 47242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang return; 47342c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } 47442c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang 47542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang if (value > max) { 47642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *numerator = max; 47742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *denominator = 1; 47842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang return; 47942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } 48042c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang 48142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // For values less than 1e-9, scale as much as possible 48242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang if (value < 1e-9) { 48342c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang unsigned int n = (unsigned int)(value * max); 48442c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang if (n == 0) { 48542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *numerator = 0; 48642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *denominator = 1; 48742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } else { 48842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *numerator = n; 48942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *denominator = max; 49042c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } 49142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang return; 49242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } 49342c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang 49442c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // Try to use a denominator of 1e9, 1e8, ..., until the numerator fits 49542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang unsigned int d; 49642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang for (d = 1000000000; d >= 1; d /= 10) { 49742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang double s = value * d; 49842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang if (s <= max) { 49942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // Remove the trailing zeros from both. 50042c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang unsigned int n = (unsigned int)s; 50142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang while (n % 10 == 0 && d >= 10) { 50242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang n /= 10; 50342c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang d /= 10; 50442c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } 50542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *numerator = n; 50642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *denominator = d; 50742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang return; 50842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } 50942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } 51042c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang 51142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // Shouldn't reach here because the denominator 1 should work 51242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // above. But just in case. 51342c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *numerator = 0; 51442c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *denominator = 1; 51542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang} 51642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang 51742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Changstatic void ConvertDoubleToURational(double value, unsigned int *numerator, 51842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang unsigned int *denominator) { 51942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang float2urat(value, 0xFFFFFFFFU, numerator, denominator); 52042c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang} 52142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang 52242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Changstatic void ConvertDoubleToSRational(double value, int *numerator, 52342c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang int *denominator) { 52442c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang int negative = 0; 52542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang 52642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang if (value < 0) { 52742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang value = -value; 52842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang negative = 1; 52942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } 53042c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang 53142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang unsigned int n, d; 53242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang float2urat(value, 0x7FFFFFFFU, &n, &d); 53342c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *numerator = (int)n; 53442c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *denominator = (int)d; 53542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang if (negative) { 53642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang *numerator = -*numerator; 53742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } 53842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang} 53942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang 54042c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang//-------------------------------------------------------------------------- 54134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Process one of the nested EXIF directories. 54234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 54334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, 54434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned ExifLength, int NestingLevel) 54534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 54634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int de; 54734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int a; 54834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int NumDirEntries; 54934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned ThumbnailOffset = 0; 55034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned ThumbnailSize = 0; 55134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char IndentString[25]; 55234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 55334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("ProcessExifDir"); 55434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (NestingLevel > 4){ 55534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Maximum directory nesting exceeded (corrupt exif header)", 0,0); 55634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 55734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 55834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 55934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memset(IndentString, ' ', 25); 56034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project IndentString[NestingLevel * 4] = '\0'; 56134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 56234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 56334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project NumDirEntries = Get16u(DirStart); 56434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry)) 56534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 56634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 56734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * DirEnd; 56834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries); 56934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (DirEnd+4 > (OffsetBase+ExifLength)){ 57034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (DirEnd+2 == OffsetBase+ExifLength || DirEnd == OffsetBase+ExifLength){ 57134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Version 1.3 of jhead would truncate a bit too much. 57234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // This also caught later on as well. 57334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 574d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang ErrNonfatal("Illegally sized exif subdirectory (%d entries)",NumDirEntries,0); 57534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 57634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 57734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 57834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (DumpExifMap){ 579d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("Map: %05d-%05d: Directory\n",(int)(DirStart-OffsetBase), (int)(DirEnd+4-OffsetBase)); 58034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 58134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 58234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 58334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 58434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 58534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags){ 58634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("(dir has %d entries)\n",NumDirEntries); 58734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 58834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 58934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (de=0;de<NumDirEntries;de++){ 59034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int Tag, Format, Components; 59134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * ValuePtr; 59234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int ByteCount; 59334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * DirEntry; 59434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirEntry = DIR_ENTRY_ADDR(DirStart, de); 59534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 59634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Tag = Get16u(DirEntry); 59734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Format = Get16u(DirEntry+2); 59834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Components = Get32u(DirEntry+4); 59934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 60034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if ((Format-1) >= NUM_FORMATS) { 60134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // (-1) catches illegal zero case as unsigned underflows to positive large. 60234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Illegal number format %d for tag %04x", Format, Tag); 60334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 60434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 60534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 60634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if ((unsigned)Components > 0x10000){ 60734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Illegal number of components %d for tag %04x", Components, Tag); 60834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 60934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 61034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 61134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ByteCount = Components * BytesPerFormat[Format]; 61234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 61334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ByteCount > 4){ 61434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned OffsetVal; 61534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project OffsetVal = Get32u(DirEntry+8); 61634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If its bigger than 4 bytes, the dir entry contains an offset. 61734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (OffsetVal+ByteCount > ExifLength){ 61834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Bogus pointer offset and / or bytecount value 61934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Illegal value pointer for tag %04x", Tag,0); 62034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 62134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 62234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ValuePtr = OffsetBase+OffsetVal; 62334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 62434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (OffsetVal > ImageInfo.LargestExifOffset){ 62534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.LargestExifOffset = OffsetVal; 62634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 62734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 62834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (DumpExifMap){ 62934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Map: %05d-%05d: Data for tag %04x\n",OffsetVal, OffsetVal+ByteCount, Tag); 63034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 63134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 63234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // 4 bytes or less and value is in the dir entry itself 63334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ValuePtr = DirEntry+8; 63434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 63534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 63634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Tag == TAG_MAKER_NOTE){ 63734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags){ 63834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("%s Maker note: ",IndentString); 63934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 64034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ProcessMakerNote(ValuePtr, ByteCount, OffsetBase, ExifLength); 64134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 64234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 64334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 64434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags){ 64534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Show tag name 64634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (a=0;;a++){ 64734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (a >= (int)TAG_TABLE_SIZE){ 64870059dd640afdce1016a7f86a81f625730eb65e4Nick Kralevich printf("%s", IndentString); 64934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" Unknown Tag %04x Value = ", Tag); 65034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 65134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 65234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (TagTable[a].Tag == Tag){ 65370059dd640afdce1016a7f86a81f625730eb65e4Nick Kralevich printf("%s", IndentString); 65434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" %s = ",TagTable[a].Desc); 65534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 65634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 65734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 65834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 65934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Show tag value. 66034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(Format){ 66134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_BYTE: 66234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if(ByteCount>1){ 66334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("%.*ls\n", ByteCount/2, (wchar_t *)ValuePtr); 66434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 66534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project PrintFormatNumber(ValuePtr, Format, ByteCount); 66634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("\n"); 66734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 66834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 66934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 67034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_UNDEFINED: 67134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Undefined is typically an ascii string. 67234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 67334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_STRING: 67434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // String arrays printed without function call (different from int arrays) 67534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 67634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("\"%s\"", ValuePtr); 67734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// int NoPrint = 0; 67834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// printf("\""); 67934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// for (a=0;a<ByteCount;a++){ 68034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// if (ValuePtr[a] >= 32){ 68134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// putchar(ValuePtr[a]); 68234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// NoPrint = 0; 68334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// }else{ 68434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // Avoiding indicating too many unprintable characters of proprietary 68534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// // bits of binary information this program may not know how to parse. 68634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// if (!NoPrint && a != ByteCount-1){ 68734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// putchar('?'); 68834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// NoPrint = 1; 68934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// } 69034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// } 69134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// } 69234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// printf("\"\n"); 69334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 69434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 69534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 69634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project default: 69734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Handle arrays of numbers later (will there ever be?) 69834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project PrintFormatNumber(ValuePtr, Format, ByteCount); 69934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("\n"); 70034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 70134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 70234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 70334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Extract useful components of tag 70434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(Tag){ 70534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 70634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_MAKE: 70734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strncpy(ImageInfo.CameraMake, (char *)ValuePtr, ByteCount < 31 ? ByteCount : 31); 70834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 70934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 71034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_MODEL: 71134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strncpy(ImageInfo.CameraModel, (char *)ValuePtr, ByteCount < 39 ? ByteCount : 39); 71234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 71334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 71434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_DATETIME_ORIGINAL: 71534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If we get a DATETIME_ORIGINAL, we use that one. 71634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strncpy(ImageInfo.DateTime, (char *)ValuePtr, 19); 71734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Fallthru... 71834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 71934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_DATETIME_DIGITIZED: 72034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_DATETIME: 72134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (!isdigit(ImageInfo.DateTime[0])){ 72234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If we don't already have a DATETIME_ORIGINAL, use whatever 72334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // time fields we may have. 72434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strncpy(ImageInfo.DateTime, (char *)ValuePtr, 19); 72534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 72634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 72734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.numDateTimeTags >= MAX_DATE_COPIES){ 72834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("More than %d date fields! This is nuts", MAX_DATE_COPIES, 0); 72934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 73034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 73134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.DateTimeOffsets[ImageInfo.numDateTimeTags++] = 73234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (char *)ValuePtr - (char *)OffsetBase; 73334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 73434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 735d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case TAG_WINXP_COMMENT: 736d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (ImageInfo.Comments[0]){ // We already have a jpeg comment. 737d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang // Already have a comment (probably windows comment), skip this one. 738d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (ShowTags) printf("Windows XP commend and other comment in header\n"); 739d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang break; // Already have a windows comment, skip this one. 740d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang } 741d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 742d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (ByteCount > 1){ 743d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (ByteCount > MAX_COMMENT_SIZE) ByteCount = MAX_COMMENT_SIZE; 744d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang memcpy(ImageInfo.Comments, ValuePtr, ByteCount); 745d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang ImageInfo.CommentWidchars = ByteCount/2; 746d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang } 747d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang break; 74834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 74934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_USERCOMMENT: 750d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (ImageInfo.Comments[0]){ // We already have a jpeg comment. 751d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang // Already have a comment (probably windows comment), skip this one. 752d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (ShowTags) printf("Multiple comments in exif header\n"); 753d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang break; // Already have a windows comment, skip this one. 754d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang } 755d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 756d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang // Comment is often padded with trailing spaces. Remove these first. 75734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (a=ByteCount;;){ 75834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project a--; 75934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if ((ValuePtr)[a] == ' '){ 76034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (ValuePtr)[a] = '\0'; 76134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 76234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 76334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 76434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (a == 0) break; 76534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 76634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 76734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Copy the comment 76842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang { 76942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // We want to set copied comment length (msize) to be the 77042c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // minimum of: 77142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // (1) The space still available in Exif 77242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // (2) The given comment length (ByteCount) 77342c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // (3) MAX_COMMENT_SIZE - 1 77442c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang int msiz = ExifLength - (ValuePtr-OffsetBase); 77542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang if (msiz > ByteCount) msiz = ByteCount; 77642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang if (msiz > MAX_COMMENT_SIZE - 1) msiz = MAX_COMMENT_SIZE - 1; 77742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang if (msiz > 5 && memcmp(ValuePtr, "ASCII", 5) == 0) { 77842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang for (a = 5; a < 10 && a < msiz; a++) { 77942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang int c = (ValuePtr)[a]; 78042c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang if (c != '\0' && c != ' ') { 78142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang strncpy(ImageInfo.Comments, 78242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang (char *)ValuePtr + a, msiz - a); 78342c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang break; 78442c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } 78534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 78642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } else { 78742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang strncpy(ImageInfo.Comments, (char *)ValuePtr, msiz); 78834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 78934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 79034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 79134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 79234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_FNUMBER: 79334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Simplest way of expressing aperture, so I trust it the most. 79434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // (overwrite previously computd value if there is one) 79534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format); 79634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 79734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 79834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_APERTURE: 79934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_MAXAPERTURE: 80034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // More relevant info always comes earlier, so only use this field if we don't 80134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // have appropriate aperture information yet. 80234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ApertureFNumber == 0){ 80334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ApertureFNumber 80434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project = (float)exp(ConvertAnyFormat(ValuePtr, Format)*log(2)*0.5); 80534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 80634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 80734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 80834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_FOCALLENGTH: 80934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Nice digital cameras actually save the focal length as a function 81034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // of how farthey are zoomed in. 811574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li ImageInfo.FocalLength.num = Get32u(ValuePtr); 812574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li ImageInfo.FocalLength.denom = Get32u(4+(char *)ValuePtr); 81334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 81434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 81534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_SUBJECT_DISTANCE: 81634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Inidcates the distacne the autofocus camera is focused to. 81734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Tends to be less accurate as distance increases. 81834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.Distance = (float)ConvertAnyFormat(ValuePtr, Format); 81934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 82034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 82134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_EXPOSURETIME: 82234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Simplest way of expressing exposure time, so I trust it most. 82334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // (overwrite previously computd value if there is one) 82434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ExposureTime = (float)ConvertAnyFormat(ValuePtr, Format); 82534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 82634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 82734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_SHUTTERSPEED: 82834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // More complicated way of expressing exposure time, so only use 82934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // this value if we don't already have it from somewhere else. 83034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureTime == 0){ 83134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ExposureTime 83234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project = (float)(1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2))); 83334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 83434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 83534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 83634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 83734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_FLASH: 83834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.FlashUsed=(int)ConvertAnyFormat(ValuePtr, Format); 83934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 84034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 84134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_ORIENTATION: 84234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (NumOrientations >= 2){ 84334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Can have another orientation tag for the thumbnail, but if there's 84434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // a third one, things are stringae. 84534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("More than two orientation tags!",0,0); 84634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 84734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 84834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project OrientationPtr[NumOrientations] = ValuePtr; 84934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project OrientationNumFormat[NumOrientations] = Format; 85034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (NumOrientations == 0){ 85134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.Orientation = (int)ConvertAnyFormat(ValuePtr, Format); 85234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 85334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.Orientation < 0 || ImageInfo.Orientation > 8){ 85434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Undefined rotation value %d", ImageInfo.Orientation, 0); 85534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.Orientation = 0; 85634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 85734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project NumOrientations += 1; 85834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 85934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 86034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_EXIF_IMAGELENGTH: 86134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_EXIF_IMAGEWIDTH: 86234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Use largest of height and width to deal with images that have been 86334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // rotated to portrait format. 86434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project a = (int)ConvertAnyFormat(ValuePtr, Format); 86534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ExifImageWidth < a) ExifImageWidth = a; 86634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 86734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 868d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case TAG_FOCAL_PLANE_XRES: 86934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FocalplaneXRes = ConvertAnyFormat(ValuePtr, Format); 87034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 87134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 872d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case TAG_FOCAL_PLANE_UNITS: 87334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch((int)ConvertAnyFormat(ValuePtr, Format)){ 87434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 1: FocalplaneUnits = 25.4; break; // inch 87534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 2: 87634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // According to the information I was using, 2 means meters. 87734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // But looking at the Cannon powershot's files, inches is the only 87834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // sensible value. 87934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FocalplaneUnits = 25.4; 88034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 88134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 88234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 3: FocalplaneUnits = 10; break; // centimeter 88334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 4: FocalplaneUnits = 1; break; // millimeter 88434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 5: FocalplaneUnits = .001; break; // micrometer 88534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 88634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 88734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 88834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_EXPOSURE_BIAS: 88934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ExposureBias = (float)ConvertAnyFormat(ValuePtr, Format); 89034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 89134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 89234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_WHITEBALANCE: 89334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.Whitebalance = (int)ConvertAnyFormat(ValuePtr, Format); 89434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 89534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 89634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_LIGHT_SOURCE: 89734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.LightSource = (int)ConvertAnyFormat(ValuePtr, Format); 89834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 89934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 90034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_METERING_MODE: 90134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.MeteringMode = (int)ConvertAnyFormat(ValuePtr, Format); 90234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 90334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 90434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_EXPOSURE_PROGRAM: 90534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ExposureProgram = (int)ConvertAnyFormat(ValuePtr, Format); 90634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 90734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 90834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_EXPOSURE_INDEX: 90934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ISOequivalent == 0){ 91034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Exposure index and ISO equivalent are often used interchangeably, 91134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // so we will do the same in jhead. 91234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // http://photography.about.com/library/glossary/bldef_ei.htm 91334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format); 91434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 91534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 91634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 91734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_EXPOSURE_MODE: 91834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ExposureMode = (int)ConvertAnyFormat(ValuePtr, Format); 91934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 92034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 92134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_ISO_EQUIVALENT: 92234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format); 92334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if ( ImageInfo.ISOequivalent < 50 ){ 92434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Fixes strange encoding on some older digicams. 92534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ISOequivalent *= 200; 92634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 92734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 92834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 92934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_DIGITALZOOMRATIO: 93034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.DigitalZoomRatio = (float)ConvertAnyFormat(ValuePtr, Format); 93134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 93234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 93334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_THUMBNAIL_OFFSET: 93434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format); 93534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirWithThumbnailPtrs = DirStart; 93634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 93734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 93834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_THUMBNAIL_LENGTH: 93934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format); 94034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ThumbnailSizeOffset = ValuePtr-OffsetBase; 94134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 94234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 94334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_EXIF_OFFSET: 94434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags) printf("%s Exif Dir:",IndentString); 94534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 94634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_INTEROP_OFFSET: 94734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Tag == TAG_INTEROP_OFFSET && ShowTags) printf("%s Interop Dir:",IndentString); 94834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 94934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * SubdirStart; 95034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project SubdirStart = OffsetBase + Get32u(ValuePtr); 95134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (SubdirStart < OffsetBase || SubdirStart > OffsetBase+ExifLength){ 95234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Illegal exif or interop ofset directory link",0,0); 95334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 95434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ProcessExifDir(SubdirStart, OffsetBase, ExifLength, NestingLevel+1); 95534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 95634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 95734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 95834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 95934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 96034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_GPSINFO: 96134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags) printf("%s GPS info dir:",IndentString); 96234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 96334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * SubdirStart; 96434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project SubdirStart = OffsetBase + Get32u(ValuePtr); 96534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (SubdirStart < OffsetBase || SubdirStart > OffsetBase+ExifLength){ 96634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Illegal GPS directory link",0,0); 96734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 96834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ProcessGpsInfo(SubdirStart, ByteCount, OffsetBase, ExifLength); 96934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 97034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 97134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 97234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 97334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 97434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case TAG_FOCALLENGTH_35MM: 97534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // The focal length equivalent 35 mm is a 2.2 tag (defined as of April 2002) 97634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // if its present, use it to compute equivalent focal length instead of 97734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // computing it from sensor geometry and actual focal length. 97834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.FocalLength35mmEquiv = (unsigned)ConvertAnyFormat(ValuePtr, Format); 97934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 980d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 981d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case TAG_DISTANCE_RANGE: 982d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang // Three possible standard values: 983d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang // 1 = macro, 2 = close, 3 = distant 984d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang ImageInfo.DistanceRange = (int)ConvertAnyFormat(ValuePtr, Format); 985d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang break; 98634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 98734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 98834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 98934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 99034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 99134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // In addition to linking to subdirectories via exif tags, 99234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // there's also a potential link to another directory at the end of each 99334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // directory. this has got to be the result of a committee! 99434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * SubdirStart; 99534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned Offset; 99634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 99734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (DIR_ENTRY_ADDR(DirStart, NumDirEntries) + 4 <= OffsetBase+ExifLength){ 99834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("DirStart %d offset from dirstart %d", (int)DirStart, 2+12*NumDirEntries); 99934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Offset = Get32u(DirStart+2+12*NumDirEntries); 100034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Offset){ 100134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project SubdirStart = OffsetBase + Offset; 100234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (SubdirStart > OffsetBase+ExifLength || SubdirStart < OffsetBase){ 100334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("SubdirStart %d OffsetBase %d ExifLength %d Offset %d", 100434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (int)SubdirStart, (int)OffsetBase, ExifLength, Offset); 100534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (SubdirStart > OffsetBase && SubdirStart < OffsetBase+ExifLength+20){ 100634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Jhead 1.3 or earlier would crop the whole directory! 100734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // As Jhead produces this form of format incorrectness, 100834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // I'll just let it pass silently 100934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags) printf("Thumbnail removed with Jhead 1.3 or earlier\n"); 101034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 101134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Illegal subdirectory link",0,0); 101234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 101334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 101434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (SubdirStart <= OffsetBase+ExifLength){ 101534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags) printf("%s Continued directory ",IndentString); 101634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ProcessExifDir(SubdirStart, OffsetBase, ExifLength, NestingLevel+1); 101734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 101834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 101934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Offset > ImageInfo.LargestExifOffset){ 102034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.LargestExifOffset = Offset; 102134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 102234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 102334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 102434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // The exif header ends before the last next directory pointer. 102534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 102634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 102734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 102834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ThumbnailOffset){ 102934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ThumbnailAtEnd = FALSE; 103034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 103134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (DumpExifMap){ 103234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Map: %05d-%05d: Thumbnail\n",ThumbnailOffset, ThumbnailOffset+ThumbnailSize); 103334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 103434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 103534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ThumbnailOffset <= ExifLength){ 103634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ThumbnailSize > ExifLength-ThumbnailOffset){ 103734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If thumbnail extends past exif header, only save the part that 103834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // actually exists. Canon's EOS viewer utility will do this - the 103934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // thumbnail extracts ok with this hack. 104034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ThumbnailSize = ExifLength-ThumbnailOffset; 104134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags) printf("Thumbnail incorrectly placed in header\n"); 104234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 104334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 104434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // The thumbnail pointer appears to be valid. Store it. 104534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ThumbnailOffset = ThumbnailOffset; 104634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ThumbnailSize = ThumbnailSize; 104734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 104834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags){ 104934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Thumbnail size: %d bytes\n",ThumbnailSize); 105034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 105134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 105234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 105334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("returning from ProcessExifDir"); 105434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 105534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 105634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 105734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 105834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Process a EXIF marker 105934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Describes all the drivel that most digital cameras include... 106034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 106134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid process_EXIF (unsigned char * ExifSection, unsigned int length) 106234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 106334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int FirstOffset; 106434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 106534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FocalplaneXRes = 0; 106634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FocalplaneUnits = 0; 106734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ExifImageWidth = 0; 106834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project NumOrientations = 0; 106934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 107034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags){ 107134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exif header %d bytes long\n",length); 107234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 107334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 107434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { // Check the EXIF header component 107534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project static uchar ExifHeader[] = "Exif\0\0"; 107634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (memcmp(ExifSection+2, ExifHeader,6)){ 107734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Incorrect Exif header",0,0); 107834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 107934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 108034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 108134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 108234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (memcmp(ExifSection+8,"II",2) == 0){ 108334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags) printf("Exif section in Intel order\n"); 108434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project MotorolaOrder = 0; 108534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 108634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (memcmp(ExifSection+8,"MM",2) == 0){ 108734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowTags) printf("Exif section in Motorola order\n"); 108834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project MotorolaOrder = 1; 108934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 109034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Invalid Exif alignment marker.",0,0); 109134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 109234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 109334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 109434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 109534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Check the next value for correctness. 109634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Get16u(ExifSection+10) != 0x2a){ 109734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Invalid Exif start (1)",0,0); 109834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 109934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 110034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 110134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FirstOffset = Get32u(ExifSection+12); 110234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (FirstOffset < 8 || FirstOffset > 16){ 110334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Usually set to 8, but other values valid too. 110434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Suspicious offset of first IFD value",0,0); 110534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return; 110634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 110734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 110834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirWithThumbnailPtrs = NULL; 110934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 111034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 111134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // First directory starts 16 bytes in. All offset are relative to 8 bytes in. 111234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ProcessExifDir(ExifSection+8+FirstOffset, ExifSection+8, length-8, 0); 111334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 111434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ThumbnailAtEnd = ImageInfo.ThumbnailOffset >= ImageInfo.LargestExifOffset ? TRUE : FALSE; 111534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 111634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Thumbnail %s end", (ImageInfo.ThumbnailAtEnd ? "at" : "NOT at")); 111734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 111834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (DumpExifMap){ 111934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned a,b; 112034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Map: %05d- End of exif\n",length-8); 112134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// for (a=0;a<length-8;a+= 10){ 112234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// printf("Map: %05d ",a); 112334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// for (b=0;b<10;b++) printf(" %02x",*(ExifSection+8+a+b)); 112434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// printf("\n"); 112534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// } 112634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (a = 0; a < length - 8; ++a) { 112734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char c = *(ExifSection+8+a); 112834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned pc = isprint(c) ? c : ' '; 112934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Map: %4d %02x %c", a, c, pc); 113034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 113134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 113234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 113334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 113434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Compute the CCD width, in millimeters. 113534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (FocalplaneXRes != 0){ 113634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Note: With some cameras, its not possible to compute this correctly because 113734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // they don't adjust the indicated focal plane resolution units when using less 113834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // than maximum resolution, so the CCDWidth value comes out too small. Nothing 113934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // that Jhad can do about it - its a camera problem. 114034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.CCDWidth = (float)(ExifImageWidth * FocalplaneUnits / FocalplaneXRes); 114134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1142574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li if (ImageInfo.FocalLength.num != 0 && ImageInfo.FocalLength.denom != 0 1143574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li && ImageInfo.FocalLength35mmEquiv == 0){ 114434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Compute 35 mm equivalent focal length based on sensor geometry if we haven't 114534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // already got it explicitly from a tag. 1146574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li ImageInfo.FocalLength35mmEquiv = (int)( 1147574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li (double)ImageInfo.FocalLength.num / ImageInfo.FocalLength.denom 1148574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li / ImageInfo.CCDWidth * 36 + 0.5); 114934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 115034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 115134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 115234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 115334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic const TagTable_t* TagToTagTableEntry(unsigned short tag) 115434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 115534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned int i; 115634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (i = 0; i < TAG_TABLE_SIZE; i++) { 115734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (TagTable[i].Tag == tag) { 115834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("found tag %d", tag); 115934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int format = TagTable[i].Format; 116034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (format == 0) { 116134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("tag %s format not defined ***** YOU MUST ADD THE FORMAT TO THE TagTable in exif.c!!!!", TagTable[i].Desc); 116234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return NULL; 116334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 116434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return &TagTable[i]; 116534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 116634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 116734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("tag %d NOT FOUND", tag); 116834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return NULL; 116934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 117034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 117134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectstatic void writeExifTagAndData(int tag, 117234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int format, 117334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project long components, 117434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project long value, 117534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int valueInString, 117634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* Buffer, 117734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int* DirIndex, 117834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int* DataWriteIndex) { 1179754078052c687f6721536009c816644c73e4f145Tyler Luu void* componentsPosition = NULL; // for saving component position 1180754078052c687f6721536009c816644c73e4f145Tyler Luu 118134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put16u(Buffer+ (*DirIndex), tag); // Tag 118234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put16u(Buffer+(*DirIndex) + 2, format); // Format 118334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (format == FMT_STRING && components == -1) { 118434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project components = strlen((char*)value) + 1; // account for null terminator 118534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (components & 1) ++components; // no odd lengths 118642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } else if (format == FMT_SSHORT && components == -1) { 118742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // jhead only supports reading one SSHORT anyway 118842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang components = 1; 118934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 1190bd90094d709a579d8d74c326269e492627be9daaTyler Luu if (format == FMT_UNDEFINED && components == -1) { 1191bd90094d709a579d8d74c326269e492627be9daaTyler Luu // check if this UNDEFINED format is actually ASCII (as it usually is) 1192bd90094d709a579d8d74c326269e492627be9daaTyler Luu // if so, we can calculate the size 1193bd90094d709a579d8d74c326269e492627be9daaTyler Luu if(memcmp((char*)value, ExifAsciiPrefix, sizeof(ExifAsciiPrefix)) == 0) { 1194bd90094d709a579d8d74c326269e492627be9daaTyler Luu components = sizeof(ExifAsciiPrefix) + 1195bd90094d709a579d8d74c326269e492627be9daaTyler Luu strlen((char*)value + sizeof(ExifAsciiPrefix)) + 1; 1196bd90094d709a579d8d74c326269e492627be9daaTyler Luu if (components & 1) ++components; // no odd lengths 1197bd90094d709a579d8d74c326269e492627be9daaTyler Luu } 1198bd90094d709a579d8d74c326269e492627be9daaTyler Luu } 119934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put32u(Buffer+(*DirIndex) + 4, components); // Components 1200754078052c687f6721536009c816644c73e4f145Tyler Luu componentsPosition = Buffer+(*DirIndex) + 4; // components # can change for lists 120134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("# components: %ld", components); 120234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (format == FMT_STRING) { 120334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // short strings can fit right in the long, otherwise have to 120434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // go in the data area 120534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (components <= 4) { 120634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strcpy(Buffer+(*DirIndex) + 8, (char*)value); 120734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else { 120834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put32u(Buffer+(*DirIndex) + 8, (*DataWriteIndex)-8); // Pointer 120934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("copying value %s to %d", (char*)value, (*DataWriteIndex)); 121034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project strncpy(Buffer+(*DataWriteIndex), (char*)value, components); 121134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*DataWriteIndex) += components; 121234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 1213bd90094d709a579d8d74c326269e492627be9daaTyler Luu } else if ((format == FMT_UNDEFINED) && 1214bd90094d709a579d8d74c326269e492627be9daaTyler Luu (memcmp((char*)value, ExifAsciiPrefix, sizeof(ExifAsciiPrefix)) == 0)) { 1215bd90094d709a579d8d74c326269e492627be9daaTyler Luu // short strings can fit right in the long, otherwise have to 1216bd90094d709a579d8d74c326269e492627be9daaTyler Luu // go in the data area 1217bd90094d709a579d8d74c326269e492627be9daaTyler Luu if (components <= 4) { 1218bd90094d709a579d8d74c326269e492627be9daaTyler Luu memcpy(Buffer+(*DirIndex) + 8, (char*)value, components); 1219bd90094d709a579d8d74c326269e492627be9daaTyler Luu } else { 1220bd90094d709a579d8d74c326269e492627be9daaTyler Luu Put32u(Buffer+(*DirIndex) + 8, (*DataWriteIndex)-8); // Pointer 1221bd90094d709a579d8d74c326269e492627be9daaTyler Luu printf("copying %s to %d", (char*)value + sizeof(ExifAsciiPrefix), (*DataWriteIndex)); 1222bd90094d709a579d8d74c326269e492627be9daaTyler Luu memcpy(Buffer+(*DataWriteIndex), (char*)value, components); 1223bd90094d709a579d8d74c326269e492627be9daaTyler Luu (*DataWriteIndex) += components; 1224bd90094d709a579d8d74c326269e492627be9daaTyler Luu } 122534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else if (!valueInString) { 122634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put32u(Buffer+(*DirIndex) + 8, value); // Value 122734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else { 122834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put32u(Buffer+(*DirIndex) + 8, (*DataWriteIndex)-8); // Pointer 122942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // Usually the separator is ',', but sometimes ':' is used, like 123042c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang // TAG_GPS_TIMESTAMP. 123142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang char* curElement = strtok((char*)value, ",:"); 123234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int i; 1233658ad712aea2756b797d1042b3b4171fccdc5ecfTyler Luu 1234658ad712aea2756b797d1042b3b4171fccdc5ecfTyler Luu // (components == -1) Need to handle lists with unknown length too 1235658ad712aea2756b797d1042b3b4171fccdc5ecfTyler Luu for (i = 0; ((i < components) || (components == -1)) && curElement != NULL; i++) { 123634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 123734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("processing component %s format %s", curElement, formatStr(format)); 123834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 123934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // elements are separated by commas 124034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (format == FMT_URATIONAL) { 124142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang unsigned int numerator; 124242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang unsigned int denominator; 124334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* separator = strchr(curElement, '/'); 124434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (separator) { 124542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang numerator = atoi(curElement); 124642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang denominator = atoi(separator + 1); 124742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } else { 124842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang double value = atof(curElement); 124942c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang ConvertDoubleToURational(value, &numerator, &denominator); 125034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 125142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang Put32u(Buffer+(*DataWriteIndex), numerator); 125242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang Put32u(Buffer+(*DataWriteIndex) + 4, denominator); 125342c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang (*DataWriteIndex) += 8; 125434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else if (format == FMT_SRATIONAL) { 125542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang int numerator; 125642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang int denominator; 125734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* separator = strchr(curElement, '/'); 125834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (separator) { 1259dc4fa4c9d4d0246b900c587cbeb6dabbbe813199Chih-Chung Chang numerator = atoi(curElement); 1260dc4fa4c9d4d0246b900c587cbeb6dabbbe813199Chih-Chung Chang denominator = atoi(separator + 1); 126142c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang } else { 126242c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang double value = atof(curElement); 126342c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang ConvertDoubleToSRational(value, &numerator, &denominator); 126434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 126542c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang Put32u(Buffer+(*DataWriteIndex), numerator); 126642c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang Put32u(Buffer+(*DataWriteIndex) + 4, denominator); 126742c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang (*DataWriteIndex) += 8; 1268658ad712aea2756b797d1042b3b4171fccdc5ecfTyler Luu } else if ((components == -1) && ((format == FMT_USHORT) || (format == FMT_SSHORT))) { 1269658ad712aea2756b797d1042b3b4171fccdc5ecfTyler Luu // variable components need to go into data write area 1270658ad712aea2756b797d1042b3b4171fccdc5ecfTyler Luu value = atoi(curElement); 1271658ad712aea2756b797d1042b3b4171fccdc5ecfTyler Luu Put16u(Buffer+(*DataWriteIndex), value); 1272658ad712aea2756b797d1042b3b4171fccdc5ecfTyler Luu (*DataWriteIndex) += 4; 127334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else { 127434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // TODO: doesn't handle multiple components yet -- if more than one, have to put in data write area. 127534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project value = atoi(curElement); 127634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put32u(Buffer+(*DirIndex) + 8, value); // Value 127734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 127842c1e4bde9be6b05412e6482cc20c3581b6d3b0bChih-Chung Chang curElement = strtok(NULL, ",:"); 127934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 1280754078052c687f6721536009c816644c73e4f145Tyler Luu if (components == -1) Put32u(componentsPosition, i); // update component # for unknowns 128134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 128234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (*DirIndex) += 12; 128334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 128434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 128534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 128634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectchar* formatStr(int format) { 128734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch (format) { 128834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_BYTE: return "FMT_BYTE"; break; 128934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_STRING: return "FMT_STRING"; break; 129034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_USHORT: return "FMT_USHORT"; break; 129134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_ULONG: return "FMT_ULONG"; break; 129234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_URATIONAL: return "FMT_URATIONAL"; break; 129334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SBYTE: return "FMT_SBYTE"; break; 129434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_UNDEFINED: return "FMT_UNDEFINED"; break; 129534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SSHORT: return "FMT_SSHORT"; break; 129634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SLONG: return "FMT_SLONG"; break; 129734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SRATIONAL: return "FMT_SRATIONAL"; break; 129834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SINGLE: return "FMT_SINGLE"; break; 129934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_DOUBLE: return "FMT_SINGLE"; break; 130034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project default: return "UNKNOWN"; 130134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 130234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 130334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 130434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 130534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 130634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Create minimal exif header - just date and thumbnail pointers, 130734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// so that date and thumbnail may be filled later. 130834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 1309482486a3d21c4d4c933f3081ff14122292314bc7Angus Kongstatic void create_EXIF_internal(ExifElement_t* elements, int exifTagCount, int gpsTagCount, int hasDateTimeTag, char* Buffer) 131034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 131134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned short NumEntries; 131234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int DataWriteIndex; 131334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int DirIndex; 13140aba81d4c228ec0681f030ef77a583a8fd9f555aTyler Luu int DirExifLink = 0; 131534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 131634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 13177a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("create_EXIF %d exif elements, %d gps elements", exifTagCount, gpsTagCount); 131834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 1319d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 132034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project MotorolaOrder = 0; 132134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 132234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memcpy(Buffer+2, "Exif\0\0II",8); 132334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put16u(Buffer+10, 0x2a); 132434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 132534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DataWriteIndex = 16; 132634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put32u(Buffer+12, DataWriteIndex-8); // first IFD offset. Means start 16 bytes in. 132734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 132834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 132934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirIndex = DataWriteIndex; 1330482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong NumEntries = 1 + exifTagCount; // the extra is the thumbnail 133134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (gpsTagCount) { 133234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ++NumEntries; // allow for the GPS info tag 133334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 1334482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong if (!hasDateTimeTag) { 1335482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong // We have to write extra date time tag. The entry number should be 1336482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong // adjusted. 1337482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong ++NumEntries; 1338482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong } 133934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DataWriteIndex += 2 + NumEntries*12 + 4; 134034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 134134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put16u(Buffer+DirIndex, NumEntries); // Number of entries 134234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirIndex += 2; 1343d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 1344d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang // Entries go here... 1345482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong if (!hasDateTimeTag) { 134634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Date/time entry 134734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char* dateTime = NULL; 134834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char dateBuf[20]; 1349482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong if (ImageInfo.numDateTimeTags) { 135034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If we had a pre-existing exif header, use time from that. 135134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project dateTime = ImageInfo.DateTime; 135234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else { 135334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Oterwise, use the file's timestamp. 135434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FileTimeAsString(dateBuf); 135534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project dateTime = dateBuf; 135634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 135734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project writeExifTagAndData(TAG_DATETIME, 135834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FMT_STRING, 135934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 20, 136034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (long)(char*)dateBuf, 136134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FALSE, 136234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Buffer, 136334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DirIndex, 136434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DataWriteIndex); 136534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 136634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 136734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (exifTagCount > 0) { 136834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int i; 136934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (i = 0; i < exifTagCount + gpsTagCount; i++) { 137034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (elements[i].GpsTag) { 137134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 137234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 137334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const TagTable_t* entry = TagToTagTableEntry(elements[i].Tag); 137434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (entry == NULL) { 137534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 137634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 137734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 13787a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("create_EXIF saving tag %x value \"%s\"",elements[i].Tag, elements[i].Value); 137934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 138034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project writeExifTagAndData(elements[i].Tag, 138134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project entry->Format, 138234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project entry->DataLength, 138334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (long)elements[i].Value, 138434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project TRUE, 138534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Buffer, 138634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DirIndex, 138734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DataWriteIndex); 138834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 1389482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong 139034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (gpsTagCount) { 139134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Link to gps dir entry 139234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project writeExifTagAndData(TAG_GPSINFO, 139334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FMT_ULONG, 139434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1, 139534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DataWriteIndex-8, 139634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FALSE, 139734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Buffer, 139834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DirIndex, 139934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DataWriteIndex); 140034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 140134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 140234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Link to exif dir entry 140334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int exifDirPtr = DataWriteIndex-8; 140434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (gpsTagCount) { 140534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifDirPtr += 2 + gpsTagCount*12 + 4; 140634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 14070aba81d4c228ec0681f030ef77a583a8fd9f555aTyler Luu DirExifLink = DirIndex; 140834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project writeExifTagAndData(TAG_EXIF_OFFSET, 140934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FMT_ULONG, 141034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1, 141134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project exifDirPtr, 141234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FALSE, 141334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Buffer, 141434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DirIndex, 141534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DataWriteIndex); 141634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 141734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 141834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // End of directory - contains optional link to continued directory. 14190aba81d4c228ec0681f030ef77a583a8fd9f555aTyler Luu Put32u(Buffer+DirIndex, 0); 142034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Ending Exif section DirIndex = %d DataWriteIndex %d", DirIndex, DataWriteIndex); 142134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 142234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1423d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 142434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // GPS Section 142534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (gpsTagCount) { 142634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirIndex = DataWriteIndex; 142734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Starting GPS section DirIndex = %d", DirIndex); 142834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project NumEntries = gpsTagCount; 142934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DataWriteIndex += 2 + NumEntries*12 + 4; 143034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 143134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put16u(Buffer+DirIndex, NumEntries); // Number of entries 143234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirIndex += 2; 143334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 143434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int i; 143534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (i = 0; i < exifTagCount + gpsTagCount; i++) { 143634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (!elements[i].GpsTag) { 143734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 143834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 143934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project const TagTable_t* entry = GpsTagToTagTableEntry(elements[i].Tag); 144034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (entry == NULL) { 144134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project continue; 144234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 144334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#ifdef SUPERDEBUG 14447a314dab81f01bac02d617ffca9dbf7b6cc00700Steve Block ALOGE("create_EXIF saving GPS tag %x value \"%s\"",elements[i].Tag, elements[i].Value); 144534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project#endif 144634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project writeExifTagAndData(elements[i].Tag, 144734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project entry->Format, 144834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project entry->DataLength, 144934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project (long)elements[i].Value, 145034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project TRUE, 145134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Buffer, 145234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DirIndex, 145334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DataWriteIndex); 145434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 145534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 145634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 145734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // End of directory - contains optional link to continued directory. 145834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put32u(Buffer+DirIndex, 0); 145934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Ending GPS section DirIndex = %d DataWriteIndex %d", DirIndex, DataWriteIndex); 146034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 146134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 146234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 14630aba81d4c228ec0681f030ef77a583a8fd9f555aTyler Luu // Overwriting TAG_EXIF_OFFSET which links to this directory 14640aba81d4c228ec0681f030ef77a583a8fd9f555aTyler Luu Put32u(Buffer+DirExifLink+8, DataWriteIndex-8); 146534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 146634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Starting Thumbnail section DirIndex = %d", DirIndex); 146734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirIndex = DataWriteIndex; 146834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project NumEntries = 2; 146934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DataWriteIndex += 2 + NumEntries*12 + 4; 147034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 147134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put16u(Buffer+DirIndex, NumEntries); // Number of entries 147234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirIndex += 2; 147334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 147434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Link to exif dir entry 147534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project writeExifTagAndData(TAG_THUMBNAIL_OFFSET, 147634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FMT_ULONG, 147734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1, 147834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DataWriteIndex-8, 147934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FALSE, 148034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Buffer, 148134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DirIndex, 148234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DataWriteIndex); 148334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 148434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 148534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 148634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Link to exif dir entry 148734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project writeExifTagAndData(TAG_THUMBNAIL_LENGTH, 148834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FMT_ULONG, 148934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1, 149034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 0, 149134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FALSE, 149234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Buffer, 149334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DirIndex, 149434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &DataWriteIndex); 149534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 149634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 149734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // End of directory - contains optional link to continued directory. 149834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put32u(Buffer+DirIndex, 0); 149934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Ending Thumbnail section DirIndex = %d DataWriteIndex %d", DirIndex, DataWriteIndex); 150034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 150134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1502d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 150334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Buffer[0] = (unsigned char)(DataWriteIndex >> 8); 150434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Buffer[1] = (unsigned char)DataWriteIndex; 150534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 150634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Remove old exif section, if there was one. 150734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project RemoveSectionType(M_EXIF); 150834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 150934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 151034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Sections need malloced buffers, so do that now, especially because 151134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // we now know how big it needs to be allocated. 151234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * NewBuf = malloc(DataWriteIndex); 151334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (NewBuf == NULL){ 151434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrFatal("Could not allocate memory"); 151534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 151634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memcpy(NewBuf, Buffer, DataWriteIndex); 151734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 151834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project CreateSection(M_EXIF, NewBuf, DataWriteIndex); 151934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 152034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Re-parse new exif section, now that its in place 152134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // otherwise, we risk touching data that has already been freed. 152234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project process_EXIF(NewBuf, DataWriteIndex); 152334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 152434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 152534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1526482486a3d21c4d4c933f3081ff14122292314bc7Angus Kongvoid create_EXIF(ExifElement_t* elements, int exifTagCount, int gpsTagCount, int hasDateTimeTag) 15272645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada{ 15282645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada // It is hard to calculate exact necessary size for editing the exif 15292645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada // header dynamically, so we are using the maximum size of EXIF, 64K 15302645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada const int EXIF_MAX_SIZE = 1024*64; 15312645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada char* Buffer = malloc(EXIF_MAX_SIZE); 15322645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada 15332645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada if (Buffer != NULL) { 1534482486a3d21c4d4c933f3081ff14122292314bc7Angus Kong create_EXIF_internal(elements, exifTagCount, gpsTagCount, hasDateTimeTag, Buffer); 15352645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada free(Buffer); 15362645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada } else { 15372645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada ErrFatal("Could not allocate memory"); 15382645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada } 15392645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada} 15402645b48159b2928fe388c6c84991b956f01e8f4eTakahiro Okada 154134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 154234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Cler the rotation tag in the exif header to 1. 154334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 154434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectconst char * ClearOrientation(void) 154534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 154634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int a; 154734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (NumOrientations == 0) return NULL; 154834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 154934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (a=0;a<NumOrientations;a++){ 155034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(OrientationNumFormat[a]){ 155134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SBYTE: 155234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_BYTE: 155334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project *(uchar *)(OrientationPtr[a]) = 1; 155434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 155534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 155634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_USHORT: 155734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put16u(OrientationPtr[a], 1); 155834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 155934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 156034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_ULONG: 156134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case FMT_SLONG: 156234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project memset(OrientationPtr, 0, 4); 156334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Can't be bothered to write generic Put32 if I only use it once. 156434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (MotorolaOrder){ 156534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)OrientationPtr[a])[3] = 1; 156634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 156734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ((uchar *)OrientationPtr[a])[0] = 1; 156834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 156934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 157034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 157134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project default: 157234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return NULL; 157334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 157434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 157534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 157634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return OrientTab[ImageInfo.Orientation]; 157734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 157834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 157934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 158034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 158134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 158234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Remove thumbnail out of the exif image. 158334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 158434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectint RemoveThumbnail(unsigned char * ExifSection) 158534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 158634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (!DirWithThumbnailPtrs || 158734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ThumbnailOffset == 0 || 158834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ImageInfo.ThumbnailSize == 0){ 158934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // No thumbnail, or already deleted it. 159034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return 0; 159134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 159234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ThumbnailAtEnd == FALSE){ 159334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Thumbnail is not at end of header, can't chop it off", 0, 0); 159434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return 0; 159534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 159634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 159734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 159834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int de; 159934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int NumDirEntries; 160034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project NumDirEntries = Get16u(DirWithThumbnailPtrs); 160134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 160234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (de=0;de<NumDirEntries;de++){ 160334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int Tag; 160434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project unsigned char * DirEntry; 160534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project DirEntry = DIR_ENTRY_ADDR(DirWithThumbnailPtrs, de); 160634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Tag = Get16u(DirEntry); 160734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Tag == TAG_THUMBNAIL_LENGTH){ 160834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Set length to zero. 160934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (Get16u(DirEntry+2) != FMT_ULONG){ 161034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // non standard format encoding. Can't do it. 161134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project ErrNonfatal("Can't remove thumbnail", 0, 0); 161234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return 0; 161334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 161434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project Put32u(DirEntry+8, 0); 161534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 161634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 161734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 161834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 161934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // This is how far the non thumbnail data went. 162034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return ImageInfo.ThumbnailOffset+8; 162134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 162234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 162334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 162434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 162534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 162634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Convert exif time to Unix time structure 162734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 162834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectint Exif2tm(struct tm * timeptr, char * ExifTime) 162934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 163034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int a; 163134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 163234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project timeptr->tm_wday = -1; 163334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 163434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Check for format: YYYY:MM:DD HH:MM:SS format. 163534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Date and time normally separated by a space, but also seen a ':' there, so 163634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // skip the middle space with '%*c' so it can be any character. 163734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project a = sscanf(ExifTime, "%d%*c%d%*c%d%*c%d:%d:%d", 163834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &timeptr->tm_year, &timeptr->tm_mon, &timeptr->tm_mday, 163934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project &timeptr->tm_hour, &timeptr->tm_min, &timeptr->tm_sec); 164034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 164134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 164234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (a == 6){ 164334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project timeptr->tm_isdst = -1; 164434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project timeptr->tm_mon -= 1; // Adjust for unix zero-based months 164534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project timeptr->tm_year -= 1900; // Adjust for year starting at 1900 164634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return TRUE; // worked. 164734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 164834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 164934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project return FALSE; // Wasn't in Exif date format. 165034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 165134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 165234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 165334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 165434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Show the collected image info, displaying camera F-stop and shutter speed 165534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// in a consistent and legible fashion. 165634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 165734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid ShowImageInfo(int ShowFileInfo) 165834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 165934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ShowFileInfo){ 166034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("File name : %s\n",ImageInfo.FileName); 166134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("File size : %d bytes\n",ImageInfo.FileSize); 166234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 166334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project { 166434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project char Temp[20]; 166534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project FileTimeAsString(Temp); 166634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("File date : %s\n",Temp); 166734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 166834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 166934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 167034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.CameraMake[0]){ 167134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Camera make : %s\n",ImageInfo.CameraMake); 167234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Camera model : %s\n",ImageInfo.CameraModel); 167334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 167434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.DateTime[0]){ 167534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Date/Time : %s\n",ImageInfo.DateTime); 167634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 167734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Resolution : %d x %d\n",ImageInfo.Width, ImageInfo.Height); 167834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 167934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.Orientation > 1){ 168034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Only print orientation if one was supplied, and if its not 1 (normal orientation) 168134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Orientation : %s\n", OrientTab[ImageInfo.Orientation]); 168234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 168334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 168434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.IsColor == 0){ 168534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Color/bw : Black and white\n"); 168634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 168734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 168834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.FlashUsed >= 0){ 168934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.FlashUsed & 1){ 169034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Flash used : Yes"); 169134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch (ImageInfo.FlashUsed){ 169234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x5: printf(" (Strobe light not detected)"); break; 169334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x7: printf(" (Strobe light detected) "); break; 169434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x9: printf(" (manual)"); break; 169534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0xd: printf(" (manual, return light not detected)"); break; 169634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0xf: printf(" (manual, return light detected)"); break; 169734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x19:printf(" (auto)"); break; 169834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x1d:printf(" (auto, return light not detected)"); break; 169934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x1f:printf(" (auto, return light detected)"); break; 170034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x41:printf(" (red eye reduction mode)"); break; 170134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x45:printf(" (red eye reduction mode return light not detected)"); break; 170234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x47:printf(" (red eye reduction mode return light detected)"); break; 170334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x49:printf(" (manual, red eye reduction mode)"); break; 170434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x4d:printf(" (manual, red eye reduction mode, return light not detected)"); break; 170534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x4f:printf(" (red eye reduction mode, return light detected)"); break; 170634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x59:printf(" (auto, red eye reduction mode)"); break; 170734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x5d:printf(" (auto, red eye reduction mode, return light not detected)"); break; 170834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x5f:printf(" (auto, red eye reduction mode, return light detected)"); break; 170934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 171034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 171134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Flash used : No"); 171234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch (ImageInfo.FlashUsed){ 171334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0x18:printf(" (auto)"); break; 171434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 171534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 171634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("\n"); 171734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 171834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 171934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1720574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li if (ImageInfo.FocalLength.num != 0 && ImageInfo.FocalLength.denom != 0) { 1721574d52d26f44b600cdab3d3361eaa5f6dd9d7a4dWu-cheng Li printf("Focal length : %4.1fmm",(double)ImageInfo.FocalLength.num / ImageInfo.FocalLength.denom); 172234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.FocalLength35mmEquiv){ 172334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" (35mm equivalent: %dmm)", ImageInfo.FocalLength35mmEquiv); 172434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 172534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("\n"); 172634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 172734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 172834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.DigitalZoomRatio > 1){ 172934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Digital zoom used. Shame on you! 173034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Digital Zoom : %1.3fx\n", (double)ImageInfo.DigitalZoomRatio); 173134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 173234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 173334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.CCDWidth){ 173434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("CCD width : %4.2fmm\n",(double)ImageInfo.CCDWidth); 173534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 173634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 173734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureTime){ 173834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureTime < 0.010){ 173934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exposure time: %6.4f s ",(double)ImageInfo.ExposureTime); 174034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 174134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exposure time: %5.3f s ",(double)ImageInfo.ExposureTime); 174234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 174334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureTime <= 0.5){ 174434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" (1/%d)",(int)(0.5 + 1/ImageInfo.ExposureTime)); 174534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 174634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("\n"); 174734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 174834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ApertureFNumber){ 174934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Aperture : f/%3.1f\n",(double)ImageInfo.ApertureFNumber); 175034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 175134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.Distance){ 175234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.Distance < 0){ 175334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Focus dist. : Infinite\n"); 175434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 175534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Focus dist. : %4.2fm\n",(double)ImageInfo.Distance); 175634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 175734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 175834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 175934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ISOequivalent){ 176034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("ISO equiv. : %2d\n",(int)ImageInfo.ISOequivalent); 176134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 176234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 176334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureBias){ 176434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If exposure bias was specified, but set to zero, presumably its no bias at all, 176534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // so only show it if its nonzero. 176634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exposure bias: %4.2f\n",(double)ImageInfo.ExposureBias); 176734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 176834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 176934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(ImageInfo.Whitebalance) { 177034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 1: 177134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Whitebalance : Manual\n"); 177234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 177334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0: 177434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Whitebalance : Auto\n"); 177534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 177634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 177734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 177834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project //Quercus: 17-1-2004 Added LightSource, some cams return this, whitebalance or both 177934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(ImageInfo.LightSource) { 178034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 1: 178134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Light Source : Daylight\n"); 178234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 178334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 2: 178434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Light Source : Fluorescent\n"); 178534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 178634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 3: 178734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Light Source : Incandescent\n"); 178834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 178934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 4: 179034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Light Source : Flash\n"); 179134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 179234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 9: 179334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Light Source : Fine weather\n"); 179434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 179534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 11: 179634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Light Source : Shade\n"); 179734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 179834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project default:; //Quercus: 17-1-2004 There are many more modes for this, check Exif2.2 specs 179934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // If it just says 'unknown' or we don't know it, then 180034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // don't bother showing it - it doesn't add any useful information. 180134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 180234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 180334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.MeteringMode){ // 05-jan-2001 vcs 180434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(ImageInfo.MeteringMode) { 180534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 2: 180634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Metering Mode: center weight\n"); 180734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 180834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 3: 180934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Metering Mode: spot\n"); 181034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 181134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 5: 181234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Metering Mode: matrix\n"); 181334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 181434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 181534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 181634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 181734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureProgram){ // 05-jan-2001 vcs 181834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(ImageInfo.ExposureProgram) { 181934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 1: 182034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exposure : Manual\n"); 182134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 182234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 2: 182334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exposure : program (auto)\n"); 182434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 182534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 3: 182634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exposure : aperture priority (semi-auto)\n"); 182734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 182834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 4: 182934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exposure : shutter priority (semi-auto)\n"); 183034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 183134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 5: 183234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exposure : Creative Program (based towards depth of field)\n"); 183334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 183434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 6: 183534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exposure : Action program (based towards fast shutter speed)\n"); 183634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 183734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 7: 183834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exposure : Portrait Mode\n"); 183934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 184034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 8: 184134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Exposure : LandscapeMode \n"); 184234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 184334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project default: 184434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 184534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 184634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 184734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project switch(ImageInfo.ExposureMode){ 184834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 0: // Automatic (not worth cluttering up output for) 184934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 185034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 1: printf("Exposure Mode: Manual\n"); 185134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 185234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project case 2: printf("Exposure Mode: Auto bracketing\n"); 185334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 185434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 185534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 1856d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (ImageInfo.DistanceRange) { 1857d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("Focus range : "); 1858d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang switch(ImageInfo.DistanceRange) { 1859d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case 1: 1860d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("macro"); 1861d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang break; 1862d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case 2: 1863d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("close"); 1864d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang break; 1865d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang case 3: 1866d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("distant"); 1867d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang break; 1868d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang } 1869d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("\n"); 1870d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang } 1871d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 1872d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang 187334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 187434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.Process != M_SOF0){ 187534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // don't show it if its the plain old boring 'baseline' process, but do 187634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // show it if its something else, like 'progressive' (used on web sometimes) 187734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int a; 187834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project for (a=0;;a++){ 187934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (a >= (int)PROCESS_TABLE_SIZE){ 188034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // ran off the end of the table. 188134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Jpeg process : Unknown\n"); 188234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 188334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 188434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ProcessTable[a].Tag == ImageInfo.Process){ 188534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Jpeg process : %s\n",ProcessTable[a].Desc); 188634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project break; 188734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 188834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 188934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 189034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 189134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.GpsInfoPresent){ 189234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("GPS Latitude : %s\n",ImageInfo.GpsLat); 189334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("GPS Longitude: %s\n",ImageInfo.GpsLong); 189434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.GpsAlt[0]) printf("GPS Altitude : %s\n",ImageInfo.GpsAlt); 189534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 189634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 189734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project // Print the comment. Print 'Comment:' for each new line of comment. 189834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.Comments[0]){ 189934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project int a,c; 190034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Comment : "); 1901d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (!ImageInfo.CommentWidchars){ 1902d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang for (a=0;a<MAX_COMMENT_SIZE;a++){ 1903d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang c = ImageInfo.Comments[a]; 1904d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (c == '\0') break; 1905d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (c == '\n'){ 1906d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang // Do not start a new line if the string ends with a carriage return. 1907d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang if (ImageInfo.Comments[a+1] != '\0'){ 1908d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("\nComment : "); 1909d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang }else{ 1910d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("\n"); 1911d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang } 191234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 1913d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang putchar(c); 191434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 191534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 1916d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("\n"); 1917d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang }else{ 1918d6a02c32e6fa83fad5794b0e19b1d28563e5a99bChih-Chung Chang printf("%.*ls\n", ImageInfo.CommentWidchars, (wchar_t *)ImageInfo.Comments); 191934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 192034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 192134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ThumbnailOffset){ 192234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("Map: %05d-%05d: Thumbnail\n",ImageInfo.ThumbnailOffset, ImageInfo.ThumbnailOffset+ImageInfo.ThumbnailSize); 192334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } else { 192434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("NO thumbnail"); 192534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 192634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 192734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 192834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 192934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 193034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project// Summarize highlights of image info on one line (suitable for grep-ing) 193134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project//-------------------------------------------------------------------------- 193234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Projectvoid ShowConciseImageInfo(void) 193334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project{ 193434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("\"%s\"",ImageInfo.FileName); 193534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 193634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" %dx%d",ImageInfo.Width, ImageInfo.Height); 193734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 193834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureTime){ 193934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ExposureTime <= 0.5){ 194034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" (1/%d)",(int)(0.5 + 1/ImageInfo.ExposureTime)); 194134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project }else{ 194234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" (%1.1f)",ImageInfo.ExposureTime); 194334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 194434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 194534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 194634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.ApertureFNumber){ 194734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" f/%3.1f",(double)ImageInfo.ApertureFNumber); 194834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 194934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 195034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.FocalLength35mmEquiv){ 195134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" f(35)=%dmm",ImageInfo.FocalLength35mmEquiv); 195234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 195334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 195434a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.FlashUsed >= 0 && ImageInfo.FlashUsed & 1){ 195534a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" (flash)"); 195634a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 195734a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 195834a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project if (ImageInfo.IsColor == 0){ 195934a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf(" (bw)"); 196034a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project } 196134a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project 196234a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project printf("\n"); 196334a2564d3268a5ca1472c5076675782fbaf724d6The Android Open Source Project} 1964