From b4c3a0f06e41ef038f4f90c800eba1b625982fe6 Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Mon, 22 Jul 2002 11:36:17 +0000 Subject: [PATCH] added EXIF Version 2.2 Tags --- ext/exif/exif.c | 195 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 155 insertions(+), 40 deletions(-) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 684313aa67..326e4682d1 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -67,7 +67,7 @@ * while extending the module as it shows if you are at the right position. * You are always considered to have a copy of TIFF6.0 and EXIF2.10 standard. */ -#undef EXIF_DEBUG +#endif EXIF_DEBUG #undef EXIF_JPEG2000 @@ -118,7 +118,7 @@ PHP_MINFO_FUNCTION(exif) php_info_print_table_start(); php_info_print_table_row(2, "EXIF Support", "enabled"); php_info_print_table_row(2, "EXIF Version", EXIF_VERSION); - php_info_print_table_row(2, "Supported EXIF Version", "02100"); + php_info_print_table_row(2, "Supported EXIF Version", "02200"); php_info_print_table_row(2, "Supported filetypes", "JPEG,TIFF"); php_info_print_table_end(); } @@ -301,6 +301,37 @@ static char *exif_get_tagformat(int format) #endif /* Describes tag values */ +#define TAG_GPS_VERSION_ID 0x0000 +#define TAG_GPS_LATITUDE_REF 0x0001 +#define TAG_GPS_LATITUDE 0x0002 +#define TAG_GPS_LONGITUDE_REF 0x0003 +#define TAG_GPS_LONGITUDE 0x0004 +#define TAG_GPS_ALTITUDE_REF 0x0005 +#define TAG_GPS_ALTITUDE 0x0006 +#define TAG_GPS_TIME_STAMP 0x0007 +#define TAG_GPS_SATELLITES 0x0008 +#define TAG_GPS_STATUS 0x0009 +#define TAG_GPS_MEASURE_MODE 0x000A +#define TAG_GPS_DOP 0x000B +#define TAG_GPS_SPEED_REF 0x000C +#define TAG_GPS_SPEED 0x000D +#define TAG_GPS_TRACK_REF 0x000E +#define TAG_GPS_TRACK 0x000F +#define TAG_GPS_IMG_DIRECTION_REF 0x0010 +#define TAG_GPS_IMG_DIRECTION 0x0011 +#define TAG_GPS_MAP_DATUM 0x0012 +#define TAG_GPS_DEST_LATITUDE_REF 0x0013 +#define TAG_GPS_DEST_LATITUDE 0x0014 +#define TAG_GPS_DEST_LONGITUDE_REF 0x0015 +#define TAG_GPS_DEST_LONGITUDE 0x0016 +#define TAG_GPS_DEST_BEARING_REF 0x0017 +#define TAG_GPS_DEST_BEARING 0x0018 +#define TAG_GPS_DEST_DISTANCE_REF 0x0019 +#define TAG_GPS_DEST_DISTANCE 0x001A +#define TAG_GPS_PROCESSING_METHOD 0x001B +#define TAG_GPS_AREA_INFORMATION 0x001C +#define TAG_GPS_DATE_STAMP 0x001D +#define TAG_GPS_DIFFERENTIAL 0x001E #define TAG_TIFF_COMMENT 0x00FE /* SHOUDLNT HAPPEN */ #define TAG_NEW_SUBFILE 0x00FE /* New version of subfile tag */ #define TAG_SUBFILE_TYPE 0x00FF /* Old version of subfile tag */ @@ -312,7 +343,6 @@ static char *exif_get_tagformat(int format) #define TAG_TRESHHOLDING 0x0107 #define TAG_CELL_WIDTH 0x0108 #define TAG_CELL_HEIGHT 0x0109 -#define TAG_STRIP_OFFSETS 0x0111 #define TAG_FILL_ORDER 0x010A #define TAG_DOCUMENT_NAME 0x010D #define TAG_IMAGE_DESCRIPTION 0x010E @@ -378,31 +408,67 @@ static char *exif_get_tagformat(int format) #define TAG_EXPOSURETIME 0x829A #define TAG_FNUMBER 0x829D #define TAG_EXIF_IFD_POINTER 0x8769 +#define TAG_EXPOSURE_PROGRAM 0x8822 +#define TAG_SPECTRAL_SENSITY 0x8824 #define TAG_GPS_IFD_POINTER 0x8825 #define TAG_ISOSPEED 0x8827 +#define TAG_OPTOELECTRIC_CONVERSION_F 0x8828 #define TAG_EXIFVERSION 0x9000 +#define TAG_DATE_TIME_ORIGINAL 0x9003 +#define TAG_DATE_TIME_DIGITIZED 0x9004 +#define TAG_COMPONENT_CONFIG 0x9101 +#define TAG_COMPRESSED_BITS_PER_PIXEL 0x9102 #define TAG_SHUTTERSPEED 0x9201 #define TAG_APERTURE 0x9202 -#define TAG_DATETIME_ORIGINAL 0x9003 -#define TAG_MAXAPERTURE 0x9205 +#define TAG_BRIGHTNESS_VALUE 0x9203 +#define TAG_EXPOSURE_BIAS_VALUE 0x9204 +#define TAG_MAX_APERTURE 0x9205 #define TAG_SUBJECT_DISTANCE 0x9206 +#define TAG_METRIC_MODULE 0x9207 #define TAG_LIGHT_SOURCE 0x9208 #define TAG_FLASH 0x9209 -#define TAG_FOCALLENGTH 0x920A +#define TAG_FOCAL_LENGTH 0x920A +#define TAG_SUBJECT_AREA 0x9214 #define TAG_MARKER_NOTE 0x927C #define TAG_USERCOMMENT 0x9286 -#define TAG_XP_TITLE 0x9c9b -#define TAG_XP_COMMENTS 0x9c9c -#define TAG_XP_AUTHOR 0x9c9d -#define TAG_XP_KEYWORDS 0x9c9e -#define TAG_XP_SUBJECT 0x9c9f +#define TAG_SUB_SEC_TIME 0x9290 +#define TAG_SUB_SEC_TIME_ORIGINAL 0x9291 +#define TAG_SUB_SEC_TIME_DIGITIZED 0x9292 +#define TAG_XP_TITLE 0x9C9B +#define TAG_XP_COMMENTS 0x9C9C +#define TAG_XP_AUTHOR 0x9C9D +#define TAG_XP_KEYWORDS 0x9C9E +#define TAG_XP_SUBJECT 0x9C9F #define TAG_FLASH_PIX_VERSION 0xA000 #define TAG_COLOR_SPACE 0xA001 -#define TAG_COMP_IMAGEWIDTH 0xA002 /* compressed images only */ -#define TAG_COMP_IMAGEHEIGHT 0xA003 +#define TAG_COMP_IMAGE_WIDTH 0xA002 /* compressed images only */ +#define TAG_COMP_IMAGE_HEIGHT 0xA003 +#define TAG_RELATED_SOUND_FILE 0xA004 #define TAG_INTEROP_IFD_POINTER 0xA005 /* IFD pointer */ -#define TAG_FOCALPLANEXRES 0xA20E -#define TAG_FOCALPLANEUNITS 0xA210 +#define TAG_FLASH_ENERGY 0xA20B +#define TAG_SPATIAL_FREQUENCY_RESPONSE 0xA20C +#define TAG_FOCALPLANE_X_RES 0xA20E +#define TAG_FOCALPLANE_Y_RES 0xA20F +#define TAG_FOCALPLANE_RESOLUTION_UNIT 0xA210 +#define TAG_SUBJECT_LOCATION 0xA214 +#define TAG_EXPOSURE_INDEX 0xA215 +#define TAG_SENSING_METHOD 0xA217 +#define TAG_FILE_SOURCE 0xA300 +#define TAG_SCENE_TYPE 0xA301 +#define TAG_CFA_PATTERN 0xA302 +#define TAG_CUSTOM_RENDERED 0xA401 +#define TAG_EXPOSURE_MODE 0xA402 +#define TAG_WHITE_BALANCE 0xA403 +#define TAG_DIGITAL_ZOOM_RATIO 0xA404 +#define TAG_FOCAL_LENGTH_IN_35_MM_FILM 0xA405 +#define TAG_SCENE_CAPTURE_TYPE 0xA406 +#define TAG_GAIN_CONTROL 0xA407 +#define TAG_CONTRAST 0xA408 +#define TAG_SATURATION 0xA409 +#define TAG_SHARPNESS 0xA40A +#define TAG_DEVICE_SETTING_DESCRIPTION 0xA40B +#define TAG_SUBJECT_DISTANCE_RANGE 0xA40C +#define TAG_IMAGE_UNIQUE_ID 0xA420 /* Olympus specific tags */ #define TAG_OLYMPUS_SPECIALMODE 0x0200 @@ -417,6 +483,7 @@ static char *exif_get_tagformat(int format) /* Internal */ #define TAG_NONE -1 /* note that -1 <> 0xFFFF */ #define TAG_COMPUTED_VALUE -2 +#define TAG_END_OF_LIST 0xFFFD /* Values for TAG_PHOTOMETRIC_INTERPRETATION */ #define PMI_BLACK_IS_ZERO 0 @@ -432,11 +499,41 @@ static char *exif_get_tagformat(int format) /* {{{ TabTable[] */ - static const struct { unsigned short Tag; char *Desc; } TagTable[] = { + { 0x0000, "GPSVersion"}, + { 0x0001, "GPSLatitudeRef"}, + { 0x0002, "GPSLatitude"}, + { 0x0003, "GPSLongitude"}, + { 0x0004, "GPSLongitudeRef"}, + { 0x0005, "GPSAltitudeRef"}, + { 0x0006, "GPSAltitude"}, + { 0x0007, "GPSTimeStamp"}, + { 0x0008, "GPSSatellites"}, + { 0x0009, "GPSStatus"}, + { 0x000A, "GPSMeasureMode"}, + { 0x000B, "GPSDOP"}, + { 0x000C, "GPSSpeedRef"}, + { 0x000D, "GPSSpeed"}, + { 0x000E, "GPSTrackRef"}, + { 0x000F, "GPSTrack"}, + { 0x0010, "GPSImgDirectionRef"}, + { 0x0011, "GPSImgDirection"}, + { 0x0012, "GPSMapDatum"}, + { 0x0013, "GPSDestLatitudeRef"}, + { 0x0014, "GPSDestLatitude"}, + { 0x0015, "GPSDestLongitudeRef"}, + { 0x0016, "GPSDestLongitude"}, + { 0x0017, "GPSDestBearingRef"}, + { 0x0018, "GPSDestBearing"}, + { 0x0019, "GPSDestDistanceRef"}, + { 0x001A, "GPSDestDistance"}, + { 0x001B, "GPSProcessingMode"}, + { 0x001C, "GPSAreaInformation"}, + { 0x001D, "GPSDateStamp"}, + { 0x001E, "GPSDifferential"}, { 0x00FE, "NewSubFile"}, { 0x00FF, "SubFile"}, { 0x0100, "ImageWidth"}, @@ -508,6 +605,9 @@ static const struct { { 0x0213, "YCbCrPositioning"}, { 0x0214, "ReferenceBlackWhite"}, { 0x1000, "RelatedImageFileFormat"}, + { 0x8822, "ExposureProgram"}, + { 0x8824, "SpectralSensity"}, + { 0x8828, "OECF"}, { 0x828D, "CFARepeatPatternDim"}, { 0x828E, "CFAPattern"}, { 0x828F, "BatteryLevel"}, @@ -559,6 +659,7 @@ static const struct { { 0xA001, "ColorSpace"}, { 0xA002, "ExifImageWidth"}, { 0xA003, "ExifImageLength"}, + { 0xA004, "RelatedSoundFile"}, { 0xA005, "InteroperabilityOffset"}, { 0xA20B, "FlashEnergy"}, /* 0x920B in TIFF/EP */ { 0xA20C, "SpatialFrequencyResponse"}, /* 0x920C - - */ @@ -570,26 +671,40 @@ static const struct { { 0xA217, "SensingMethod"}, /* 0x9217 - - */ { 0xA300, "FileSource"}, { 0xA301, "SceneType"}, + { 0xA302, "CFAPattern"}, + { 0xA401, "CustomRendered"}, + { 0xA402, "ExposureMode"}, + { 0xA403, "WhiteBalance"}, + { 0xA404, "DigitalZoomRatio"}, + { 0xA405, "FocalLengthIn35mmFilm"}, + { 0xA406, "SceneCaptureType"}, + { 0xA407, "GainControl"}, + { 0xA408, "Contrast"}, + { 0xA409, "Saturation"}, + { 0xA40A, "Sharpness"}, + { 0xA40B, "DeviceSettingDescription"}, + { 0xA40C, "SubjectDistanceRange"}, + { 0xA420, "ImageUniqueID"}, {TAG_NONE, "no tag value"}, {TAG_COMPUTED_VALUE, "computed value"}, - { 0, ""} /* Important for exif_get_tagname() IF value != "" functionresult is != false */ + {TAG_END_OF_LIST, ""} /* Important for exif_get_tagname() IF value != "" functionresult is != false */ } ; /* }}} */ /* {{{ exif_get_tagname Get headername for tag_num or NULL if not defined */ -static char * exif_get_tagname(int tag_num, char *ret, int len) +static char * exif_get_tagname(int tag_num, char *ret, int len TSRMLS_DC) { int i, t; char tmp[32]; for (i=0;;i++) { - if ((t=TagTable[i].Tag) == tag_num || !t) { + if ((t=TagTable[i].Tag) == tag_num || t==TAG_END_OF_LIST) { + if (t==TAG_END_OF_LIST) { + break; + } if (ret && len) { - if (!t) { - break; - } strncpy(ret, TagTable[i].Desc, abs(len)); if (len<0) { len = -len; @@ -603,7 +718,7 @@ static char * exif_get_tagname(int tag_num, char *ret, int len) } } if (ret && len) { - sprintf(tmp, "UndefinedTag:0x%04X", tag_num); + snprintf(tmp, sizeof(tmp), "UndefinedTag:0x%04X", tag_num); strncpy(ret, tmp, abs(len)); if (len<0) { len = -len; @@ -1842,7 +1957,7 @@ PHP_FUNCTION(exif_tagname) convert_to_long_ex(p_num); tag = Z_LVAL_PP(p_num); - szTemp = exif_get_tagname(tag, NULL, 0); + szTemp = exif_get_tagname(tag, NULL, 0 TSRMLS_CC); if (tag<0 || !szTemp || !szTemp[0]) { RETURN_BOOL(FALSE); } else { @@ -1995,7 +2110,7 @@ static void exif_thumbnail_build(image_info_type *ImageInfo TSRMLS_DC) { info_data = &info_list->list[i]; byte_count = php_tiff_bytes_per_format[info_data->format] * info_data->length; #ifdef EXIF_DEBUG - php_error(E_NOTICE, "%s(): thumbnail: process tag(x%04X=%s): %s%s (%d bytes)", get_active_function_name(TSRMLS_C), info_data->tag, exif_get_tagname(info_data->tag, tagname, -12), (info_data->length>1)&&info_data->format!=TAG_FMT_UNDEFINED&&info_data->format!=TAG_FMT_STRING?"ARRAY OF ":"", exif_get_tagformat(info_data->format), byte_count); + php_error(E_NOTICE, "%s(): thumbnail: process tag(x%04X=%s): %s%s (%d bytes)", get_active_function_name(TSRMLS_C), info_data->tag, exif_get_tagname(info_data->tag, tagname, -12 TSRMLS_CC), (info_data->length>1)&&info_data->format!=TAG_FMT_UNDEFINED&&info_data->format!=TAG_FMT_STRING?"ARRAY OF ":"", exif_get_tagformat(info_data->format), byte_count); #endif if (info_data->tag==TAG_STRIP_OFFSETS || info_data->tag==TAG_JPEG_INTERCHANGE_FORMAT) { php_ifd_set16u(new_data + 0, info_data->tag, ImageInfo->motorola_intel); @@ -2235,7 +2350,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha if (!format || format >= NUM_FORMATS) { /* (-1) catches illegal zero case as unsigned underflows to positive large. */ - php_error(E_WARNING, "%s(): Illegal format code in IFD: 0x%04X", get_active_function_name(TSRMLS_C), format); + php_error(E_WARNING, "%s(): Illegal format code in IFD_TAG: 0x%04X", get_active_function_name(TSRMLS_C), format); return TRUE; } @@ -2255,11 +2370,11 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha if (value_ptr < dir_entry) { /* we can read this if offset_val > 0 */ /* some files have their values in other parts of the file */ - php_error(E_WARNING, "%s(): process tag(x%04X=%s): Illegal pointer offset(x%04X < x%04X)", get_active_function_name(TSRMLS_C), tag, exif_get_tagname(tag, tagname, -12), offset_val, dir_entry); + php_error(E_WARNING, "%s(): process tag(x%04X=%s): Illegal pointer offset(x%04X < x%04X)", get_active_function_name(TSRMLS_C), tag, exif_get_tagname(tag, tagname, -12 TSRMLS_CC), offset_val, dir_entry); } else { /* this is for sure not allowed */ /* exception are IFD pointers */ - php_error(E_WARNING, "%s(): process tag(x%04X=%s): Illegal pointer offset(x%04X + x%04X = x%04X > x%04X)", get_active_function_name(TSRMLS_C), tag, exif_get_tagname(tag, tagname, -12), offset_val, byte_count, offset_val+byte_count, IFDlength); + php_error(E_WARNING, "%s(): process tag(x%04X=%s): Illegal pointer offset(x%04X + x%04X = x%04X > x%04X)", get_active_function_name(TSRMLS_C), tag, exif_get_tagname(tag, tagname, -12 TSRMLS_CC), offset_val, byte_count, offset_val+byte_count, IFDlength); } return TRUE; } @@ -2306,17 +2421,17 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha ImageInfo->sections_found |= FOUND_ANY_TAG; #ifdef EXIF_DEBUG - php_error(E_NOTICE, "%s(): process tag(x%04X=%s,@x%04X + x%04X(=%d)): %s%s", get_active_function_name(TSRMLS_C), tag, exif_get_tagname(tag, tagname, -12), offset_val, byte_count, byte_count, (components>1)&&format!=TAG_FMT_UNDEFINED&&format!=TAG_FMT_STRING?"ARRAY OF ":"", format==TAG_FMT_STRING?(value_ptr?value_ptr:""):exif_get_tagformat(format)); + php_error(E_NOTICE, "%s(): process tag(x%04X=%s,@x%04X + x%04X(=%d)): %s%s", get_active_function_name(TSRMLS_C), tag, exif_get_tagname(tag, tagname, -12 TSRMLS_CC), offset_val, byte_count, byte_count, (components>1)&&format!=TAG_FMT_UNDEFINED&&format!=TAG_FMT_STRING?"ARRAY OF ":"", format==TAG_FMT_STRING?(value_ptr?value_ptr:""):exif_get_tagformat(format)); #endif if (section_index==SECTION_THUMBNAIL) { switch(tag) { case TAG_IMAGEWIDTH: - case TAG_COMP_IMAGEWIDTH: + case TAG_COMP_IMAGE_WIDTH: ImageInfo->Thumbnail.width = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC); break; case TAG_IMAGEHEIGHT: - case TAG_COMP_IMAGEHEIGHT: + case TAG_COMP_IMAGE_HEIGHT: ImageInfo->Thumbnail.height = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC); break; @@ -2395,7 +2510,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha break; case TAG_APERTURE: - case TAG_MAXAPERTURE: + case TAG_MAX_APERTURE: /* More relevant info always comes earlier, so only use this field if we don't have appropriate aperture information yet. */ if (ImageInfo->ApertureFNumber == 0) { @@ -2418,11 +2533,11 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha ImageInfo->ExposureTime = -1; break; - case TAG_COMP_IMAGEWIDTH: + case TAG_COMP_IMAGE_WIDTH: ImageInfo->ExifImageWidth = exif_convert_any_to_int(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC); break; - case TAG_FOCALPLANEXRES: + case TAG_FOCALPLANE_X_RES: ImageInfo->FocalplaneXRes = exif_convert_any_format(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC); break; @@ -2432,7 +2547,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha ImageInfo->Distance = (float)exif_convert_any_format(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC); break; - case TAG_FOCALPLANEUNITS: + case TAG_FOCALPLANE_RESOLUTION_UNIT: switch((int)exif_convert_any_format(value_ptr, format, ImageInfo->motorola_intel TSRMLS_CC)) { case 1: ImageInfo->FocalplaneUnits = 25.4; break; /* inch */ case 2: @@ -2489,7 +2604,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha } } } - exif_iif_add_tag(ImageInfo, section_index, exif_get_tagname(tag, tagname, sizeof(tagname)), tag, format, components, value_ptr TSRMLS_CC); + exif_iif_add_tag(ImageInfo, section_index, exif_get_tagname(tag, tagname, sizeof(tagname) TSRMLS_CC), tag, format, components, value_ptr TSRMLS_CC); EFREE_IF(outside); return TRUE; } @@ -2920,7 +3035,7 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offse entry_tag = php_ifd_get16u(dir_entry+0, ImageInfo->motorola_intel); entry_type = php_ifd_get16u(dir_entry+2, ImageInfo->motorola_intel); if (entry_type > NUM_FORMATS) { - php_error(E_WARNING, "%s(): Error in TIFF: Illegal format, suppose bytes", get_active_function_name(TSRMLS_C)); + php_error(E_WARNING, "%s(): Illegal format code in TIFF 0x%04d, suppose bytes", get_active_function_name(TSRMLS_C), entry_type); entry_type = TAG_FMT_BYTE; } entry_length = php_ifd_get32u(dir_entry+4, ImageInfo->motorola_intel) * php_tiff_bytes_per_format[entry_type]; @@ -2941,11 +3056,11 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offse } switch(entry_tag) { case TAG_IMAGEWIDTH: - case TAG_COMP_IMAGEWIDTH: + case TAG_COMP_IMAGE_WIDTH: ImageInfo->Width = entry_value; break; case TAG_IMAGEHEIGHT: - case TAG_COMP_IMAGEHEIGHT: + case TAG_COMP_IMAGE_HEIGHT: ImageInfo->Height = entry_value; break; case TAG_PHOTOMETRIC_INTERPRETATION: @@ -3373,7 +3488,7 @@ PHP_FUNCTION(exif_read_data) exif_iif_add_str(&ImageInfo, SECTION_COMPUTED, "Copyright.Editor", ImageInfo.CopyrightEditor TSRMLS_CC); for (i=0; i