diff options
Diffstat (limited to 'Build/source/texk/web2c/xetexdir/jpegimage.c')
-rw-r--r-- | Build/source/texk/web2c/xetexdir/jpegimage.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/xetexdir/jpegimage.c b/Build/source/texk/web2c/xetexdir/jpegimage.c index a70c4241c35..fafdb637c10 100644 --- a/Build/source/texk/web2c/xetexdir/jpegimage.c +++ b/Build/source/texk/web2c/xetexdir/jpegimage.c @@ -240,6 +240,134 @@ read_APP14_Adobe (struct JPEG_info *j_info, FILE *fp, unsigned short length) return 7; } +static unsigned long +read_exif_bytes(unsigned char **p, int n, int b) +{ + unsigned long rval = 0; + unsigned char *pp = *p; + if (b) { + switch (n) { + case 4: + rval += *pp++; rval <<= 8; + rval += *pp++; rval <<= 8; + case 2: + rval += *pp++; rval <<= 8; + rval += *pp; + break; + } + } + else { + pp += n; + switch (n) { + case 4: + rval += *--pp; rval <<= 8; + rval += *--pp; rval <<= 8; + case 2: + rval += *--pp; rval <<= 8; + rval += *--pp; + break; + } + } + *p += n; + return rval; +} + +static unsigned short +read_APP1_Exif (struct JPEG_info *j_info, FILE *fp, unsigned short length) +{ + /* this doesn't save the data, just reads the tags we need */ + /* based on info from http://www.exif.org/Exif2-2.PDF */ + unsigned char *buffer = NEW(length, unsigned char); + unsigned char *p, *rp; + unsigned char *tiff_header; + char bigendian; + int i; + double rational_value; + int num_fields, tag, type, count, value, num, den; + double xres = 72.0; + double yres = 72.0; + double res_unit = 1.0; + fread(buffer, length, 1, fp); + p = buffer; + while ((p < buffer + length) && (*p == 0)) + ++p; + tiff_header = p; + if ((*p == 'M') && (*(p+1) == 'M')) + bigendian = 1; + else if ((*p == 'I') && (*(p+1) == 'I')) + bigendian = 0; + else + goto err; + p += 2; + i = read_exif_bytes(&p, 2, bigendian); + if (i != 42) + goto err; + i = read_exif_bytes(&p, 4, bigendian); + p = tiff_header + i; + num_fields = read_exif_bytes(&p, 2, bigendian); + while (num_fields-- > 0) { + tag = read_exif_bytes(&p, 2, bigendian); + type = read_exif_bytes(&p, 2, bigendian); + count = read_exif_bytes(&p, 4, bigendian); + switch (type) { + case 1: /* byte */ + value = *p++; + p += 3; + break; + case 3: /* short */ + value = read_exif_bytes(&p, 2, bigendian); + p += 2; + break; + case 4: /* long */ + case 9: /* slong */ + value = read_exif_bytes(&p, 4, bigendian); + break; + case 5: /* rational */ + case 10: /* srational */ + value = read_exif_bytes(&p, 4, bigendian); + rp = tiff_header + value; + num = read_exif_bytes(&rp, 4, bigendian); + den = read_exif_bytes(&rp, 4, bigendian); + break; + case 7: /* undefined */ + value = *p++; + p += 3; + break; + case 2: /* ascii */ + default: + p += 4; + break; + } + switch (tag) { + case 282: /* x res */ + if (den != 0) + xres = num / den; + break; + case 283: /* y res */ + if (den != 0) + yres = num / den; + break; + case 296: /* res unit */ + switch (value) { + case 2: + res_unit = 1.0; + break; + case 3: + res_unit = 2.54; + break; + } + } + } + + + j_info->xdpi = xres * res_unit; + j_info->ydpi = yres * res_unit; + +err: + RELEASE(buffer); + return length; +} + static unsigned short read_APP0_JFIF (struct JPEG_info *j_info, FILE *fp, unsigned short length) { @@ -364,6 +492,17 @@ JPEG_scan_file (struct JPEG_info *j_info, FILE *fp) } seek_relative(fp, length); break; + case JM_APP1: + if (length > 5) { + if (fread(app_sig, sizeof(char), 5, fp) != 5) + return -1; + length -= 5; + if (!memcmp(app_sig, "Exif\000", 5)) { + length -= read_APP1_Exif(j_info, fp, length); + } + } + seek_relative(fp, length); + break; case JM_APP2: if (length >= 14) { if (fread(app_sig, sizeof(char), 12, fp) != 12) |