summaryrefslogtreecommitdiff
path: root/ext/exif/exif.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/exif/exif.c')
-rw-r--r--ext/exif/exif.c76
1 files changed, 75 insertions, 1 deletions
diff --git a/ext/exif/exif.c b/ext/exif/exif.c
index 9f314d95d6..a34ad7fa0b 100644
--- a/ext/exif/exif.c
+++ b/ext/exif/exif.c
@@ -401,6 +401,11 @@ static char *exif_get_tagformat(int format)
#define TAG_FOCALLENGTH 0x920A
#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_FLASH_PIX_VERSION 0xA000
#define TAG_COLOR_SPACE 0xA001
#define TAG_COMP_IMAGEWIDTH 0xA002 /* compressed images only */
@@ -555,6 +560,11 @@ static const struct {
{ 0x9290, "SubSecTime"},
{ 0x9291, "SubSecTimeOriginal"},
{ 0x9292, "SubSecTimeDigitized"},
+ { 0x9c9b, "Title" }, /* Win XP specific, Unicode */
+ { 0x9c9c, "Comments" }, /* Win XP specific, Unicode */
+ { 0x9c9d, "Author" }, /* Win XP specific, Unicode */
+ { 0x9c9e, "Keywords" }, /* Win XP specific, Unicode */
+ { 0x9c9f, "Subject" }, /* Win XP specific, Unicode, not to be confused with SubjectDistance and SubjectLocation */
{ 0xA000, "FlashPixVersion"},
{ 0xA001, "ColorSpace"},
{ 0xA002, "ExifImageWidth"},
@@ -883,7 +893,8 @@ typedef struct {
#define SECTION_GPS 9
#define SECTION_INTEROP 10
#define SECTION_APP12 11
-#define SECTION_COUNT 12
+#define SECTION_WINXP 12
+#define SECTION_COUNT 13
#define FOUND_FILE (1<<SECTION_FILE)
#define FOUND_COMPUTED (1<<SECTION_COMPUTED)
@@ -897,6 +908,7 @@ typedef struct {
#define FOUND_GPS (1<<SECTION_GPS)
#define FOUND_INTEROP (1<<SECTION_INTEROP)
#define FOUND_APP12 (1<<SECTION_APP12)
+#define FOUND_WINXP (1<<SECTION_WINXP)
static char *exif_get_sectionname(int section)
{
@@ -913,6 +925,7 @@ static char *exif_get_sectionname(int section)
case SECTION_GPS: return "GPS";
case SECTION_INTEROP: return "INTEROP";
case SECTION_APP12: return "APP12";
+ case SECTION_WINXP: return "WINXP";
}
return "";
}
@@ -973,6 +986,17 @@ typedef struct {
char *data;
} thumbnail_data;
+typedef struct {
+ char *value;
+ size_t size;
+ int tag;
+} xp_field_type;
+
+typedef struct {
+ int count;
+ xp_field_type *list;
+} xp_field_list;
+
/* EXIF standard defines Copyright as "<Photographer> [ '\0' <Editor> ] ['\0']" */
/* This structure is used to store a section of a Jpeg file. */
typedef struct {
@@ -1008,6 +1032,8 @@ typedef struct {
char *CopyrightPhotographer;
char *CopyrightEditor;
+ xp_field_list xp_fields;
+
thumbnail_data Thumbnail;
/* other */
int sections_found; /* FOUND_<marker> */
@@ -2177,6 +2203,29 @@ static int exif_process_user_comment(image_info_type *ImageInfo, char **pszInfoP
}
/* }}} */
+/* {{{ exif_process_unicode
+ * Process unicode field in IFD. */
+static int exif_process_unicode(image_info_type *ImageInfo, xp_field_type *xp_field, int tag, char *szValuePtr, int ByteCount TSRMLS_DC)
+{
+ xp_field->tag = tag;
+
+ /* Copy the comment */
+#ifdef HAVE_MBSTRING
+/* What if MS supports big-endian with XP? */
+/* if (ImageInfo->motorola_intel) {
+ xp_field->value = php_mb_convert_encoding(szValuePtr, ByteCount, ImageInfo->encode_unicode, ImageInfo->decode_unicode_be, &xp_field->size TSRMLS_CC);
+ } else {
+ xp_field->value = php_mb_convert_encoding(szValuePtr, ByteCount, ImageInfo->encode_unicode, ImageInfo->decode_unicode_le, &xp_field->size TSRMLS_CC);
+ }*/
+ xp_field->value = php_mb_convert_encoding(szValuePtr, ByteCount, ImageInfo->encode_unicode, ImageInfo->decode_unicode_le, &xp_field->size TSRMLS_CC);
+ return xp_field->size;
+#else
+ xp_field->size = exif_process_string_raw(&xp_field->value, szValuePtr, ByteCount);
+ return xp_field->size;
+#endif
+}
+/* }}} */
+
/* {{{ exif_process_IFD_TAG
* Process one of the nested IFDs directories. */
static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, char *offset_base, size_t IFDlength, int section_index, int ReadNextIFD TSRMLS_DC)
@@ -2185,6 +2234,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
int tag, format, components;
char *value_ptr, tagname[64], cbuf[32], *outside=NULL;
size_t byte_count, offset_val, fpos, fgot;
+ xp_field_type *tmp_xp;
tag = php_ifd_get16u(dir_entry, ImageInfo->motorola_intel);
format = php_ifd_get16u(dir_entry+2, ImageInfo->motorola_intel);
@@ -2325,6 +2375,22 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
ImageInfo->UserCommentLength = exif_process_user_comment(ImageInfo, &(ImageInfo->UserComment), &(ImageInfo->UserCommentEncoding), value_ptr, byte_count TSRMLS_CC);
break;
+ case TAG_XP_TITLE:
+ case TAG_XP_COMMENTS:
+ case TAG_XP_AUTHOR:
+ case TAG_XP_KEYWORDS:
+ case TAG_XP_SUBJECT:
+ tmp_xp = (xp_field_type*)erealloc(ImageInfo->xp_fields.list, sizeof(xp_field_type)*(ImageInfo->xp_fields.count+1));
+ if (!tmp_xp) {
+ EXIF_ERRLOG_EALLOC
+ } else {
+ ImageInfo->sections_found |= FOUND_WINXP;
+ ImageInfo->xp_fields.list = tmp_xp;
+ ImageInfo->xp_fields.count++;
+ exif_process_unicode(ImageInfo, &(ImageInfo->xp_fields.list[ImageInfo->xp_fields.count-1]), tag, value_ptr, byte_count TSRMLS_CC);
+ }
+ break;
+
case TAG_FNUMBER:
/* Simplest way of expressing aperture, so I trust it the most.
(overwrite previously computd value if there is one) */
@@ -3099,6 +3165,10 @@ static int exif_discard_imageinfo(image_info_type *ImageInfo)
EFREE_IF(ImageInfo->encode_jis);
EFREE_IF(ImageInfo->decode_jis_be);
EFREE_IF(ImageInfo->decode_jis_le);
+ for (i=0; i<ImageInfo->xp_fields.count; i++) {
+ EFREE_IF(ImageInfo->xp_fields.list[i].value);
+ }
+ EFREE_IF(ImageInfo->xp_fields.list);
for (i=0; i<SECTION_COUNT; i++) {
exif_iif_free(ImageInfo, i);
}
@@ -3304,6 +3374,9 @@ PHP_FUNCTION(exif_read_data)
exif_iif_add_str(&ImageInfo, SECTION_COMPUTED, "Copyright.Photographer", ImageInfo.CopyrightPhotographer);
exif_iif_add_str(&ImageInfo, SECTION_COMPUTED, "Copyright.Editor", ImageInfo.CopyrightEditor);
+ for (i=0; i<ImageInfo.xp_fields.count; i++) {
+ exif_iif_add_str(&ImageInfo, SECTION_WINXP, exif_get_tagname(ImageInfo.xp_fields.list[i].tag, NULL, 0), ImageInfo.xp_fields.list[i].value);
+ }
if (ImageInfo.Thumbnail.size) {
if (read_thumbnail) {
/* not exif_iif_add_str : this is a buffer */
@@ -3335,6 +3408,7 @@ PHP_FUNCTION(exif_read_data)
add_assoc_image_info(return_value, sub_arrays, &ImageInfo, SECTION_INTEROP);
add_assoc_image_info(return_value, sub_arrays, &ImageInfo, SECTION_FPIX);
add_assoc_image_info(return_value, sub_arrays, &ImageInfo, SECTION_APP12);
+ add_assoc_image_info(return_value, sub_arrays, &ImageInfo, SECTION_WINXP);
#ifdef EXIF_DEBUG
php_error(E_NOTICE, "Discarding info");