| /* -*- C++ -*- |
| * Copyright 2019-2025 LibRaw LLC (info@libraw.org) |
| * |
| LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder, |
| dcraw.c is copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net. |
| LibRaw do not use RESTRICTED code from dcraw.c |
| |
| LibRaw is free software; you can redistribute it and/or modify |
| it under the terms of the one of two licenses as you choose: |
| |
| 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 |
| (See file LICENSE.LGPL provided in LibRaw distribution archive for details). |
| |
| 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 |
| (See file LICENSE.CDDL provided in LibRaw distribution archive for details). |
| |
| */ |
| |
| #include "third_party/libraw/internal/dcraw_defs.h" |
| #include "third_party/libraw/internal/libraw_cameraids.h" |
| |
| int LibRaw::parse_tiff_ifd(INT64 base) |
| { |
| unsigned entries, tag, type, len, plen = 16, utmp; |
| INT64 save; |
| int ifd, use_cm = 0, cfa, i, j, c, ima_len = 0; |
| char *cbuf, *cp; |
| uchar cfa_pat[16], cfa_pc[] = {0, 1, 2, 3}, tab[256]; |
| double fm[3][4], cc[4][4], cm[4][3], cam_xyz[4][3], num; |
| double ab[] = {1, 1, 1, 1}, asn[] = {0, 0, 0, 0}, xyz[] = {1, 1, 1}; |
| unsigned sony_curve[] = {0, 0, 0, 0, 0, 4095}; |
| unsigned *buf, sony_offset = 0, sony_length = 0, sony_key = 0; |
| struct jhead jh; |
| |
| ushort *rafdata; |
| |
| if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0]) |
| return 1; |
| ifd = tiff_nifds++; |
| for (j = 0; j < 4; j++) |
| for (i = 0; i < 4; i++) |
| cc[j][i] = i == j; |
| |
| if (libraw_internal_data.unpacker_data.ifd0_offset == -1LL) |
| libraw_internal_data.unpacker_data.ifd0_offset = base; |
| |
| entries = get2(); |
| if (entries > 512) |
| return 1; |
| |
| INT64 fsize = ifp->size(); |
| |
| while (entries--) |
| { |
| tiff_get(base, &tag, &type, &len, &save); |
| INT64 savepos = ftell(ifp); |
| if (len > 8 && savepos + len > 2 * fsize) |
| { |
| fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! |
| continue; |
| } |
| if (callbacks.exif_cb) |
| { |
| callbacks.exif_cb(callbacks.exifparser_data, |
| tag | (is_pana_raw ? 0x30000 : ((ifd + 1) << 20)), type, |
| len, order, ifp, base); |
| fseek(ifp, savepos, SEEK_SET); |
| } |
| if (!is_pana_raw) |
| { /* processing of EXIF tags that collide w/ PanasonicRaw tags */ |
| switch (tag) |
| { |
| case 0x0001: |
| if (len == 4) |
| is_pana_raw = get4(); |
| break; |
| case 0x000b: /* 11, Std. EXIF Software tag */ |
| fgets(software, 64, ifp); |
| if (!strncmp(software, "Adobe", 5) || !strncmp(software, "dcraw", 5) || |
| !strncmp(software, "UFRaw", 5) || !strncmp(software, "Bibble", 6) || |
| !strcmp(software, "Digital Photo Professional")) |
| is_raw = 0; |
| break; |
| case 0x001c: /* 28, safeguard, probably not needed */ |
| case 0x001d: /* 29, safeguard, probably not needed */ |
| case 0x001e: /* 30, safeguard, probably not needed */ |
| cblack[tag - 0x001c] = get2(); |
| cblack[3] = cblack[1]; |
| break; |
| |
| case 0x0111: /* 273, StripOffset */ |
| if (len > 1 && len < 16384) |
| { |
| INT64 sav = ftell(ifp); |
| tiff_ifd[ifd].strip_offsets = (INT64 *)calloc(len, sizeof(INT64)); |
| tiff_ifd[ifd].strip_offsets_count = len; |
| for (int ii = 0; ii < (int)len; ii++) |
| tiff_ifd[ifd].strip_offsets[ii] = get4() + base; |
| fseek(ifp, sav, SEEK_SET); // restore position |
| } |
| /* fallback */ |
| case 0x0201: /* 513, JpegIFOffset */ |
| case 0xf007: // 61447 |
| tiff_ifd[ifd].offset = get4() + base; |
| if (!tiff_ifd[ifd].bps && tiff_ifd[ifd].offset > 0) |
| { |
| fseek(ifp, tiff_ifd[ifd].offset, SEEK_SET); |
| if (ljpeg_start(&jh, 1)) |
| { |
| if (!dng_version && !strcasecmp(make, "SONY") && tiff_ifd[ifd].phint == 32803 && |
| tiff_ifd[ifd].comp == 7) // Sony/lossless compressed IFD |
| { |
| tiff_ifd[ifd].comp = 6; |
| tiff_ifd[ifd].bps = jh.bits; |
| tiff_ifd[ifd].samples = 1; |
| } |
| else if (!dng_version && !strcasecmp(make, "SONY") && tiff_ifd[ifd].phint == 6 && |
| tiff_ifd[ifd].comp == 7 && tiff_ifd[ifd].samples == 3) // Sony/lossless YCbCr |
| { |
| tiff_ifd[ifd].comp = 6; |
| tiff_ifd[ifd].bps = jh.bits; |
| // tiff_ifd[ifd].samples = 3; // no change |
| } |
| else |
| { |
| tiff_ifd[ifd].comp = 6; |
| tiff_ifd[ifd].bps = jh.bits; |
| tiff_ifd[ifd].t_width = jh.wide; |
| tiff_ifd[ifd].t_height = jh.high; |
| tiff_ifd[ifd].samples = jh.clrs; |
| if (!(jh.sraw || (jh.clrs & 1))) |
| tiff_ifd[ifd].t_width *= jh.clrs; |
| if ((tiff_ifd[ifd].t_width > 4 * tiff_ifd[ifd].t_height) & ~jh.clrs) |
| { |
| tiff_ifd[ifd].t_width /= 2; |
| tiff_ifd[ifd].t_height *= 2; |
| } |
| i = order; |
| parse_tiff(tiff_ifd[ifd].offset + 12); |
| order = i; |
| } |
| } |
| } |
| break; |
| } |
| } |
| else |
| { /* processing Panasonic-specific "PanasonicRaw" tags */ |
| switch (tag) |
| { |
| case 0x0004: /* 4, SensorTopBorder */ |
| imgdata.sizes.raw_inset_crops[0].ctop = get2(); |
| break; |
| case 0x000a: /* 10, BitsPerSample */ |
| pana_bpp = get2(); |
| pana_bpp = LIM(pana_bpp, 8, 16); |
| break; |
| case 0x000b: /* 11, Compression */ |
| imPana.Compression = get2(); |
| break; |
| case 0x000e: /* 14, LinearityLimitRed */ |
| case 0x000f: /* 15, LinearityLimitGreen */ |
| case 0x0010: /* 16, LinearityLimitBlue */ |
| imgdata.color.linear_max[tag - 14] = get2(); |
| if (imgdata.color.linear_max[tag - 14] == 16383) |
| imgdata.color.linear_max[tag - 14] -= 64; |
| if (imgdata.color.linear_max[tag - 14] == 4095) |
| imgdata.color.linear_max[tag - 14] -= 16; |
| if (tag == 0x000f) // 15, LinearityLimitGreen |
| imgdata.color.linear_max[3] = imgdata.color.linear_max[1]; |
| break; |
| case 0x0013: /* 19, WBInfo */ |
| if ((i = get2()) > 0x100) |
| break; |
| for (c = 0; c < i; c++) |
| { |
| if ((j = get2()) < 0x100) |
| { |
| if (j >= 0) { |
| icWBC[j][0] = get2(); |
| icWBC[j][2] = get2(); |
| icWBC[j][1] = icWBC[j][3] = |
| 0x100; |
| } |
| } |
| else // light source out of EXIF numbers range |
| get4(); |
| } |
| break; |
| case 0x0018: /* 24, HighISOMultiplierRed */ |
| case 0x0019: /* 25, HighISOMultiplierGreen */ |
| case 0x001a: /* 26, HighISOMultiplierBlue */ |
| imPana.HighISOMultiplier[tag - 0x0018] = get2(); |
| break; |
| case 0x001c: /* 28, BlackLevelRed */ |
| case 0x001d: /* 29, BlackLevelGreen */ |
| case 0x001e: /* 30, BlackLevelBlue */ |
| pana_black[tag - 0x001c] = get2(); |
| break; |
| case 0x002d: /* 45, RawFormat */ |
| /* pana_encoding: tag 0x002d (45dec) not used - DMC-LX1/FZ30/FZ50/L1/LX1/LX2 |
| 2 - RAW DMC-FZ8/FZ18 |
| 3 - RAW DMC-L10 |
| 4 - RW2 for most other models, including G9 in "pixel shift off" mode and YUNEEC CGO4 |
| (must add 15 to black levels for RawFormat == 4) |
| 5 - RW2 DC-GH5s; G9 in "pixel shift on" mode |
| 6 - RW2 DC-S1, DC-S1R in "pixel shift off" mode |
| 7 - RW2 DC-S1R (probably DC-S1 too) in "pixel shift on" mode |
| 8 - RW2 DC-GH6, DC-S5M2 |
| */ |
| pana_encoding = get2(); |
| break; |
| case 0x002f: /* 47, CropTop */ |
| imgdata.sizes.raw_inset_crops[0].ctop = get2(); |
| break; |
| case 0x0030: /* 48, CropLeft */ |
| imgdata.sizes.raw_inset_crops[0].cleft = get2(); |
| break; |
| case 0x0031: /* 49, CropBottom */ |
| imgdata.sizes.raw_inset_crops[0].cheight = |
| get2() - imgdata.sizes.raw_inset_crops[0].ctop; |
| break; |
| case 0x0032: /* 50, CropRight */ |
| imgdata.sizes.raw_inset_crops[0].cwidth = |
| get2() - imgdata.sizes.raw_inset_crops[0].cleft; |
| break; |
| case 0x0037: /* 55, ISO if ISO in 0x8827 & ISO in 0x0017 == 65535 */ |
| if (iso_speed == 65535) |
| iso_speed = float(get4()); |
| break; |
| case 0x0039: |
| if (type == LIBRAW_EXIFTAG_TYPE_UNDEFINED && len == 26) |
| { |
| ushort cnt = get2(); |
| if (cnt > 6) |
| cnt = 6; |
| for (i = 0; i < cnt; i++) |
| pana8.tag39[i] = get4(); |
| } |
| break; |
| case 0x003A: |
| if (type == LIBRAW_EXIFTAG_TYPE_UNDEFINED && len == 26) |
| { |
| ushort cnt = get2(); |
| if (cnt > 6) |
| cnt = 6; |
| for (i = 0; i < cnt; i++) |
| { |
| get2(); |
| pana8.tag3A[i] = get2(); |
| } |
| } |
| break; |
| case 0x003B: |
| if (type == LIBRAW_EXIFTAG_TYPE_SHORT && len == 1) |
| pana8.tag3B = get2(); |
| break; |
| case 0x003C: |
| case 0x003D: |
| case 0x003E: |
| case 0x003F: |
| if (type == LIBRAW_EXIFTAG_TYPE_SHORT && len == 1) |
| pana8.initial[tag - 0x3c] = get2(); |
| break; |
| case 0x0040: |
| if (type == LIBRAW_EXIFTAG_TYPE_UNDEFINED && len == 70) |
| { |
| ushort count = get2(); |
| if (count > 17) count = 17; |
| for (i = 0; i < count; i++) |
| { |
| ushort v1 = get2(); |
| if (v1 > 16u) v1 = 16u; |
| pana8.tag40a[i] = v1; |
| ushort v2 = get2(); |
| if (v2 > 0xfffu) |
| v2 = 0xfffu; |
| pana8.tag40b[i] = v2; |
| } |
| } |
| break; |
| case 0x0041: |
| if (type == LIBRAW_EXIFTAG_TYPE_UNDEFINED && len == 36) |
| { |
| ushort count = get2(); |
| if (count > 17) |
| count = 17; |
| for (i = 0; i < count; i++) |
| { |
| ushort v1 = get2(); |
| if (v1 > 0x40u) v1 = 64; |
| pana8.tag41[i] = v1; |
| } |
| } |
| break; |
| case 0x0042: |
| if (type == LIBRAW_EXIFTAG_TYPE_SHORT && len == 1) |
| { |
| ushort val = get2(); |
| if (val > 5) |
| val = 5; |
| pana8.stripe_count = val; |
| } |
| break; |
| case 0x0043: |
| if (type == LIBRAW_EXIFTAG_TYPE_SHORT && len == 1) |
| { |
| ushort val = get2(); |
| if (val > 5) |
| val = 5; |
| pana8.tag43 = val; |
| } |
| break; |
| case 0x0044: |
| if (type == LIBRAW_EXIFTAG_TYPE_UNDEFINED && len == 50) |
| { |
| ushort count = get2(); |
| if (count > 5) |
| count = 5; |
| for (i = 0; i < count; i++) |
| pana8.stripe_offsets[i] = get4(); |
| } |
| break; |
| case 0x0045: |
| if (type == LIBRAW_EXIFTAG_TYPE_UNDEFINED && len == 50) |
| { |
| ushort count = get2(); |
| if (count > 5) |
| count = 5; |
| for (i = 0; i < count; i++) |
| pana8.stripe_left[i] = get4(); |
| } |
| break; |
| case 0x0046: |
| if (type == LIBRAW_EXIFTAG_TYPE_UNDEFINED && len == 50) |
| { |
| ushort count = get2(); |
| if (count > 5) |
| count = 5; |
| for (i = 0; i < count; i++) |
| pana8.stripe_compressed_size[i] = get4(); |
| } |
| break; |
| case 0x0047: |
| if (type == LIBRAW_EXIFTAG_TYPE_UNDEFINED && len == 26) |
| { |
| ushort count = get2(); |
| if (count > 5) |
| count = 5; |
| for (i = 0; i < count; i++) |
| pana8.stripe_width[i] = get2(); |
| } |
| break; |
| case 0x0048: |
| if (type == LIBRAW_EXIFTAG_TYPE_UNDEFINED && len == 26) |
| { |
| ushort count = get2(); |
| if (count > 5) |
| count = 5; |
| for (i = 0; i < count; i++) |
| pana8.stripe_height[i] = get2(); |
| } |
| break; |
| case 0x011c: /* 284, Gamma */ |
| { |
| int n = get2(); |
| if (n >= 1024) |
| imPana.gamma = (float)n / 1024.0f; |
| else if (n >= 256) |
| imPana.gamma = (float)n / 256.0f; |
| else |
| imPana.gamma = (float)n / 100.0f; |
| } |
| break; |
| case 0x0120: /* 288, CameraIFD, contains tags 0x1xxx, 0x2xxx, 0x3xxx */ |
| { |
| unsigned sorder = order; |
| INT64 sbase = base; |
| base = ftell(ifp); |
| order = get2(); |
| fseek(ifp, 2, SEEK_CUR); |
| fseek(ifp, INT64(get4()) - 8LL, SEEK_CUR); |
| parse_tiff_ifd(base); |
| base = sbase; |
| order = sorder; |
| } |
| break; |
| case 0x0121: /* 289, Multishot, 0 is Off, 65536 is Pixel Shift */ |
| imPana.Multishot = get4(); |
| break; |
| case 0x1001: |
| if (imPana.Multishot == 0) { |
| imPana.Multishot = get4(); |
| if (imPana.Multishot) |
| imPana.Multishot += 65535; |
| } |
| break; |
| case 0x1100: |
| imPana.FocusStepNear = get2(); |
| break; |
| case 0x1101: |
| imPana.FocusStepCount = get2(); |
| break; |
| case 0x1105: |
| imPana.ZoomPosition = get4(); |
| break; |
| case 0x1201: |
| if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT)) { |
| imPana.LensManufacturer = fgetc(ifp); |
| } else if (type == 258) { |
| imPana.LensManufacturer = get4(); |
| if (imPana.LensManufacturer >= 257) { |
| ilm.LensMount = LIBRAW_MOUNT_LPS_L; |
| ilm.LensFormat = LIBRAW_FORMAT_FF; |
| } |
| } |
| break; |
| case 0x1202: |
| if (ilm.LensMount == LIBRAW_MOUNT_LPS_L) { |
| if ((utmp = get2())) ilm.LensID = utmp; |
| } else if ((imPana.LensManufacturer != 0xff) && |
| (imPana.LensManufacturer != 0xffffffff)) { |
| if ((utmp = (fgetc(ifp) << 8) | fgetc(ifp))) |
| ilm.LensID = (imPana.LensManufacturer << 16) + utmp; |
| } |
| break; |
| case 0x1203: /* 4611, FocalLengthIn35mmFormat, contained in 0x0120 |
| CameraIFD */ |
| if (imgdata.lens.FocalLengthIn35mmFormat < 0.65f) |
| imgdata.lens.FocalLengthIn35mmFormat = get2(); |
| break; |
| case 0x2009: /* 8201, contained in 0x0120 CameraIFD */ |
| if ((pana_encoding == 4) || (pana_encoding == 5)) |
| { |
| i = MIN(8, len); |
| int permut[8] = {3, 2, 1, 0, 3 + 4, 2 + 4, 1 + 4, 0 + 4}; |
| imPana.BlackLevelDim = len; |
| for (j = 0; j < i; j++) |
| { |
| imPana.BlackLevel[permut[j]] = |
| (float)(get2()) / (float)(powf(2.f, 14.f - pana_bpp)); |
| } |
| } |
| break; |
| case 0x3420: /* 13344, WB_RedLevelAuto, contained in 0x0120 CameraIFD */ |
| icWBC[LIBRAW_WBI_Auto][0] = get2(); |
| icWBC[LIBRAW_WBI_Auto][1] = icWBC[LIBRAW_WBI_Auto][3] = 1024; |
| break; |
| case 0x3421: /* 13345, WB_BlueLevelAuto, contained in 0x0120 CameraIFD */ |
| icWBC[LIBRAW_WBI_Auto][2] = get2(); |
| break; |
| case 0x0002: /* 2, ImageWidth */ |
| tiff_ifd[ifd].t_width = getint(type); |
| break; |
| case 0x0003: /* 3, ImageHeight */ |
| tiff_ifd[ifd].t_height = getint(type); |
| break; |
| case 0x0005: /* 5, SensorLeftBorder */ |
| width = get2(); |
| imgdata.sizes.raw_inset_crops[0].cleft = width; |
| break; |
| case 0x0006: /* 6, SensorBottomBorder */ |
| height = get2(); |
| imgdata.sizes.raw_inset_crops[0].cheight = |
| height - imgdata.sizes.raw_inset_crops[0].ctop; |
| break; |
| case 0x0007: /* 7, SensorRightBorder */ |
| i = get2(); |
| width += i; |
| imgdata.sizes.raw_inset_crops[0].cwidth = |
| i - imgdata.sizes.raw_inset_crops[0].cleft; |
| break; |
| case 0x0009: /* 9, CFAPattern */ |
| if ((i = get2())) |
| filters = i; |
| break; |
| case 0x0011: /* 17, RedBalance */ |
| case 0x0012: /* 18, BlueBalance */ |
| if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT) && len == 1) |
| cam_mul[(tag - 0x0011) * 2] = get2() / 256.f; |
| break; |
| case 0x0017: /* 23, ISO */ |
| if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT)) |
| iso_speed = get2(); |
| break; |
| case 0x0024: /* 36, WBRedLevel */ |
| case 0x0025: /* 37, WBGreenLevel */ |
| case 0x0026: /* 38, WBBlueLevel */ |
| cam_mul[tag - 0x0024] = get2(); |
| break; |
| case 0x0027: /* 39, WBInfo2 */ |
| if ((i = get2()) > 0x100) |
| break; |
| for (c = 0; c < i; c++) |
| { |
| if ((j = get2()) < 0x100) |
| { |
| if (j >= 0) { |
| icWBC[j][0] = get2(); |
| icWBC[j][1] = icWBC[j][3] = get2(); |
| icWBC[j][2] = get2(); |
| if (c == 1 && i > 6 && cam_mul[0] <= 0.001f) |
| for (int q = 0; q < 4; q++) |
| cam_mul[q] = float(icWBC[j][q]); |
| } |
| } |
| else |
| fseek(ifp, 6, SEEK_CUR); |
| } |
| break; |
| case 0x002e: /* 46, JpgFromRaw */ |
| if ((type != LIBRAW_EXIFTAG_TYPE_UNDEFINED) || (fgetc(ifp) != 0xff) || (fgetc(ifp) != 0xd8)) |
| break; |
| thumb_offset = ftell(ifp) - 2; |
| thumb_length = len; |
| break; |
| |
| case 0x0118: /* 280, Panasonic RW2 offset */ |
| if (type != LIBRAW_EXIFTAG_TYPE_LONG) |
| break; |
| load_raw = &LibRaw::panasonic_load_raw; |
| load_flags = 0x2008; |
| case 0x0111: /* 273, StripOffset */ |
| if (len > 1 && len < 16384) |
| { |
| INT64 sav = ftell(ifp); |
| tiff_ifd[ifd].strip_offsets = (INT64 *)calloc(len, sizeof(INT64)); |
| tiff_ifd[ifd].strip_offsets_count = len; |
| for (int ii = 0; ii < (int)len; ii++) |
| tiff_ifd[ifd].strip_offsets[ii] = get4() + base; |
| fseek(ifp, sav, SEEK_SET); // restore position |
| } |
| /* fallthrough */ |
| tiff_ifd[ifd].offset = get4() + base; |
| if (!tiff_ifd[ifd].bps && tiff_ifd[ifd].offset > 0) |
| { |
| fseek(ifp, tiff_ifd[ifd].offset, SEEK_SET); |
| if (ljpeg_start(&jh, 1)) |
| { |
| tiff_ifd[ifd].comp = 6; |
| tiff_ifd[ifd].t_width = jh.wide; |
| tiff_ifd[ifd].t_height = jh.high; |
| tiff_ifd[ifd].bps = jh.bits; |
| tiff_ifd[ifd].samples = jh.clrs; |
| if (!(jh.sraw || (jh.clrs & 1))) |
| tiff_ifd[ifd].t_width *= jh.clrs; |
| if ((tiff_ifd[ifd].t_width > 4 * tiff_ifd[ifd].t_height) & ~jh.clrs) |
| { |
| tiff_ifd[ifd].t_width /= 2; |
| tiff_ifd[ifd].t_height *= 2; |
| } |
| i = order; |
| parse_tiff(tiff_ifd[ifd].offset + 12); |
| order = i; |
| } |
| } |
| break; |
| } |
| |
| } /* processing of Panasonic-specific tags finished */ |
| |
| switch (tag) |
| { /* processing of general EXIF tags */ |
| case 0xf000: /* 61440, Fuji HS10 table */ |
| fseek(ifp, get4() + base, SEEK_SET); |
| parse_tiff_ifd(base); |
| break; |
| case 0x00fe: /* NewSubfileType */ |
| tiff_ifd[ifd].newsubfiletype = int(getreal(type)); |
| break; |
| case 0x0100: /* 256, ImageWidth */ |
| case 0xf001: /* 61441, Fuji RAF RawImageFullWidth */ |
| tiff_ifd[ifd].t_width = getint(type); |
| break; |
| case 0x0101: /* 257, ImageHeight */ |
| case 0xf002: /* 61442, Fuji RAF RawImageFullHeight */ |
| tiff_ifd[ifd].t_height = getint(type); |
| break; |
| case 0x0102: /* 258, BitsPerSample */ |
| case 0xf003: /* 61443, Fuji RAF 0xf003 */ |
| if(!tiff_ifd[ifd].samples || tag != 0x0102) // ??? already set by tag 0x115 |
| tiff_ifd[ifd].samples = len & 7; |
| tiff_ifd[ifd].bps = getint(type); |
| if (tiff_bps < (unsigned)tiff_ifd[ifd].bps) |
| tiff_bps = tiff_ifd[ifd].bps; |
| break; |
| case 0xf006: /* 61446, Fuji RAF 0xf006 */ |
| raw_height = 0; |
| if (tiff_ifd[ifd].bps > 12) |
| break; |
| load_raw = &LibRaw::packed_load_raw; |
| load_flags = get4() ? 24 : 80; |
| break; |
| case 0x0103: /* 259, Compression */ |
| /* |
| 262 = Kodak 262 |
| 32767 = Sony ARW Compressed |
| 32769 = Packed RAW |
| 32770 = Samsung SRW Compressed |
| 32772 = Samsung SRW Compressed 2 |
| 32867 = Kodak KDC Compressed |
| 34713 = Nikon NEF Compressed |
| 65000 = Kodak DCR Compressed |
| 65535 = Pentax PEF Compressed |
| */ |
| tiff_ifd[ifd].comp = getint(type); |
| break; |
| case 0x0106: /* 262, PhotometricInterpretation */ |
| tiff_ifd[ifd].phint = get2(); |
| break; |
| case 0x010e: /* 270, ImageDescription */ |
| fread(desc, 512, 1, ifp); |
| desc[511] = 0; |
| break; |
| case 0x010f: /* 271, Make */ |
| fgets(make, 64, ifp); |
| break; |
| case 0x0110: /* 272, Model */ |
| if (!strncmp(make, "Hasselblad", 10) && model[0] && |
| (imHassy.format != LIBRAW_HF_Imacon)) |
| break; |
| fgets(model, 64, ifp); |
| break; |
| case 0x0116: // 278 |
| tiff_ifd[ifd].rows_per_strip = getint(type); |
| break; |
| case 0x0112: /* 274, Orientation */ |
| tiff_ifd[ifd].t_flip = "50132467"[get2() & 7] - '0'; |
| break; |
| case 0x0115: /* 277, SamplesPerPixel */ |
| tiff_ifd[ifd].samples = getint(type) & 7; |
| break; |
| case 0x0152: /* Extrasamples */ |
| tiff_ifd[ifd].extrasamples = (getint(type) & 0xff) + 1024; |
| break; |
| case 0x0117: /* 279, StripByteCounts */ |
| if (len > 1 && len < 16384) |
| { |
| INT64 sav = ftell(ifp); |
| tiff_ifd[ifd].strip_byte_counts = (INT64 *)calloc(len, sizeof(INT64)); |
| tiff_ifd[ifd].strip_byte_counts_count = len; |
| for (int ii = 0; ii < (int)len; ii++) |
| tiff_ifd[ifd].strip_byte_counts[ii] = get4(); |
| fseek(ifp, sav, SEEK_SET); // restore position |
| } |
| /* fallback */ |
| case 0x0202: // 514 |
| case 0xf008: // 61448 |
| tiff_ifd[ifd].bytes = get4(); |
| break; |
| case 0xf00e: // 61454, FujiFilm "As Shot" |
| FORC3 cam_mul[GRBG_2_RGBG(c)] = float(getint(type)); |
| break; |
| case 0x0131: /* 305, Software */ |
| fgets(software, 64, ifp); |
| if (!strncmp(software, "Adobe", 5) || !strncmp(software, "dcraw", 5) || |
| !strncmp(software, "UFRaw", 5) || !strncmp(software, "Bibble", 6) || |
| !strcmp(software, "Digital Photo Professional")) |
| is_raw = 0; |
| break; |
| case 0x0132: /* 306, DateTime */ |
| get_timestamp(0); |
| break; |
| case 0x013b: /* 315, Artist */ |
| fread(artist, 64, 1, ifp); |
| artist[63] = 0; |
| break; |
| case 0x013d: // 317 |
| tiff_ifd[ifd].predictor = getint(type); |
| break; |
| case 0x0142: /* 322, TileWidth */ |
| tiff_ifd[ifd].t_tile_width = getint(type); |
| break; |
| case 0x0143: /* 323, TileLength */ |
| tiff_ifd[ifd].t_tile_length = getint(type); |
| break; |
| case 0x0144: /* 324, TileOffsets */ |
| tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4(); // FIXME: get8 for BigTIFF |
| if (len == 1) |
| tiff_ifd[ifd].t_tile_width = tiff_ifd[ifd].t_tile_length = 0; |
| if (len == 4) |
| { |
| load_raw = &LibRaw::sinar_4shot_load_raw; |
| is_raw = 5; |
| } |
| break; |
| case 0x0145: // 325 |
| tiff_ifd[ifd].bytes = len > 1 ? ftell(ifp) : get4(); // FIXME: get8 for BigTIFF |
| break; |
| case 0x014a: /* 330, SubIFDs */ |
| if (!strcmp(model, "DSLR-A100") && tiff_ifd[ifd].t_width == 3872) |
| { |
| load_raw = &LibRaw::sony_arw_load_raw; |
| data_offset = get4() + base; |
| ifd++; |
| if (ifd >= int(sizeof tiff_ifd / sizeof tiff_ifd[0])) |
| throw LIBRAW_EXCEPTION_IO_CORRUPT; |
| break; |
| } |
| if (!strncmp(make, "Hasselblad", 10) && |
| libraw_internal_data.unpacker_data.hasselblad_parser_flag) |
| { |
| fseek(ifp, ftell(ifp) + 4, SEEK_SET); |
| fseek(ifp, get4() + base, SEEK_SET); |
| parse_tiff_ifd(base); |
| break; |
| } |
| if (len > 1000) |
| len = 1000; /* 1000 SubIFDs is enough */ |
| while (len--) |
| { |
| INT64 ii = ftell(ifp); |
| fseek(ifp, get4() + base, SEEK_SET); |
| if (parse_tiff_ifd(base)) |
| break; |
| fseek(ifp, ii + 4LL, SEEK_SET); |
| } |
| break; |
| case 0x0153: // 339 |
| tiff_ifd[ifd].sample_format = getint(type); |
| break; |
| case 0x0190: // 400 |
| strcpy(make, "Sarnoff"); |
| maximum = 0xfff; |
| break; |
| case 0x02bc: // 700 |
| if ((tagtypeIs(LIBRAW_EXIFTAG_TYPE_BYTE) || |
| tagtypeIs(LIBRAW_EXIFTAG_TYPE_ASCII) || |
| tagtypeIs(LIBRAW_EXIFTAG_TYPE_SBYTE) || |
| tagtypeIs(LIBRAW_EXIFTOOLTAGTYPE_binary)) && |
| (len > 1) && (len < 5100000)) |
| { |
| xmpdata = (char *)calloc(xmplen = len + 1,1); |
| unsigned br = fread(xmpdata,1, len, ifp); |
| xmpdata[br] = 0; |
| } |
| break; |
| case 0x7000: |
| imSony.SonyRawFileType = get2(); |
| break; |
| case 0x7010: // 28688 |
| FORC4 sony_curve[c + 1] = get2() >> 2 & 0xfff; |
| for (i = 0; i < 5; i++) |
| for (j = sony_curve[i] + 1; j <= (int)sony_curve[i + 1]; j++) |
| curve[j] = curve[j - 1] + (1 << i); |
| break; |
| case 0x7200: // 29184, Sony SR2Private |
| sony_offset = get4(); |
| break; |
| case 0x7201: // 29185, Sony SR2Private |
| sony_length = get4(); |
| break; |
| case 0x7221: // 29217, Sony SR2Private |
| sony_key = get4(); |
| break; |
| case 0x7250: // 29264, Sony SR2Private |
| parse_minolta(ftell(ifp)); |
| raw_width = 0; |
| break; |
| case 0x7303: // 29443, Sony SR2SubIFD |
| FORC4 cam_mul[GRBG_2_RGBG(c)] = get2(); |
| break; |
| case 0x7313: // 29459, Sony SR2SubIFD |
| FORC4 cam_mul[RGGB_2_RGBG(c)] = get2(); |
| break; |
| case 0x7310: // 29456, Sony SR2SubIFD |
| FORC4 cblack[RGGB_2_RGBG(c)] = get2(); |
| i = cblack[3]; |
| FORC3 if (i > (int)cblack[c]) i = cblack[c]; |
| FORC4 cblack[c] -= i; |
| black = i; |
| break; |
| case 0x827d: /* 33405, Model2 */ |
| /* |
| for Kodak ProBack 645 PB645x-yyyy 'x' is: |
| 'M' for Mamiya 645 |
| 'C' for Contax 645 |
| 'H' for Hasselblad H-series |
| */ |
| fgets(model2, 64, ifp); |
| break; |
| case 0x828d: /* 33421, CFARepeatPatternDim */ |
| if (get2() == 6 && get2() == 6) |
| tiff_ifd[ifd].t_filters = filters = 9; |
| break; |
| case 0x828e: /* 33422, CFAPattern */ |
| if (filters == 9) |
| { |
| FORC(36)((char *)xtrans)[c] = fgetc(ifp) & 3; |
| break; |
| } |
| case 0xfd09: /* 64777, Kodak P-series */ |
| if (len == 36) |
| { |
| tiff_ifd[ifd].t_filters = filters = 9; |
| colors = 3; |
| FORC(36)((char *)xtrans)[c] = fgetc(ifp) & 3; |
| } |
| else if (len > 0) |
| { |
| if ((plen = len) > 16) |
| plen = 16; |
| fread(cfa_pat, 1, plen, ifp); |
| for (colors = cfa = i = 0; i < (int)plen && colors < 4; i++) |
| { |
| if (cfa_pat[i] > 31) |
| continue; // Skip wrong data |
| colors += !(cfa & (1 << cfa_pat[i])); |
| cfa |= 1 << cfa_pat[i]; |
| } |
| if (cfa == 070) |
| memcpy(cfa_pc, "\003\004\005", 3); /* CMY */ |
| if (cfa == 072) |
| memcpy(cfa_pc, "\005\003\004\001", 4); /* GMCY */ |
| goto guess_cfa_pc; |
| } |
| break; |
| case 0x8290: // 33424 |
| case 0xfe00: // 65024 |
| fseek(ifp, get4() + base, SEEK_SET); |
| parse_kodak_ifd(base); |
| break; |
| case 0x829a: /* 33434, ExposureTime */ |
| tiff_ifd[ifd].t_shutter = shutter = getrealf(type); |
| break; |
| case 0x829d: /* 33437, FNumber */ |
| aperture = getrealf(type); |
| break; |
| case 0x9400: |
| imCommon.exifAmbientTemperature = getrealf(type); |
| if ((imCommon.CameraTemperature > -273.15f) && |
| ((OlyID == OlyID_TG_5) || |
| (OlyID == OlyID_TG_6) || |
| (OlyID == OlyID_TG_7))) |
| imCommon.CameraTemperature += |
| imCommon.exifAmbientTemperature; |
| break; |
| case 0x9401: |
| imCommon.exifHumidity = getrealf(type); |
| break; |
| case 0x9402: |
| imCommon.exifPressure = getrealf(type); |
| break; |
| case 0x9403: |
| imCommon.exifWaterDepth = getrealf(type); |
| break; |
| case 0x9404: |
| imCommon.exifAcceleration = getrealf(type); |
| break; |
| case 0x9405: |
| imCommon.exifCameraElevationAngle = getrealf(type); |
| break; |
| case 0xa405: // FocalLengthIn35mmFormat |
| imgdata.lens.FocalLengthIn35mmFormat = get2(); |
| break; |
| case 0xa431: // BodySerialNumber |
| case 0xc62f: |
| stmread(imgdata.shootinginfo.BodySerial, len, ifp); |
| break; |
| case 0xa432: // LensInfo, 42034dec, Lens Specification per EXIF standard |
| imgdata.lens.MinFocal = getrealf(type); |
| imgdata.lens.MaxFocal = getrealf(type); |
| imgdata.lens.MaxAp4MinFocal = getrealf(type); |
| imgdata.lens.MaxAp4MaxFocal = getrealf(type); |
| break; |
| case 0xa435: // LensSerialNumber |
| stmread(imgdata.lens.LensSerial, len, ifp); |
| break; |
| case 0xc630: // DNG LensInfo, Lens Specification per EXIF standard |
| imgdata.lens.MinFocal = getrealf(type); |
| imgdata.lens.MaxFocal = getrealf(type); |
| imgdata.lens.MaxAp4MinFocal = getrealf(type); |
| imgdata.lens.MaxAp4MaxFocal = getrealf(type); |
| break; |
| case 0xa420: /* 42016, ImageUniqueID */ |
| stmread(imgdata.color.ImageUniqueID, len, ifp); |
| break; |
| case 0xc65d: /* 50781, RawDataUniqueID */ |
| imgdata.color.RawDataUniqueID[16] = 0; |
| fread(imgdata.color.RawDataUniqueID, 1, 16, ifp); |
| break; |
| case 0xa433: // LensMake |
| stmread(imgdata.lens.LensMake, len, ifp); |
| break; |
| case 0xa434: // LensModel |
| stmread(imgdata.lens.Lens, len, ifp); |
| if (!strncmp(imgdata.lens.Lens, "----", 4)) |
| imgdata.lens.Lens[0] = 0; |
| break; |
| case 0x9205: |
| imgdata.lens.EXIF_MaxAp = libraw_powf64l(2.0f, (getrealf(type) / 2.0f)); |
| break; |
| case 0x8602: /* 34306, Leaf white balance */ |
| FORC4 |
| { |
| int q = get2(); |
| if (q) |
| cam_mul[GRGB_2_RGBG(c)] = 4096.f / q; |
| } |
| break; |
| case 0x8603: /* 34307, Leaf CatchLight color matrix */ |
| fread(software, 1, 7, ifp); |
| if (strncmp(software, "MATRIX", 6)) |
| break; |
| colors = 4; |
| for (raw_color = i = 0; i < 3; i++) |
| { |
| FORC4 fscanf(ifp, "%f", &rgb_cam[i][GRGB_2_RGBG(c)]); |
| if (!use_camera_wb) |
| continue; |
| num = 0; |
| FORC4 num += rgb_cam[i][c]; |
| FORC4 rgb_cam[i][c] /= float(MAX(1, num)); |
| } |
| break; |
| case 0x8606: /* 34310, Leaf metadata */ |
| parse_mos(ftell(ifp)); |
| case 0x85ff: // 34303 |
| strcpy(make, "Leaf"); |
| break; |
| case 0x8769: /* 34665, EXIF tag */ |
| fseek(ifp, get4() + base, SEEK_SET); |
| parse_exif(base); |
| break; |
| case 0x8825: /* 34853, GPSInfo tag */ |
| { |
| INT64 pos; |
| fseek(ifp, pos = (get4() + base), SEEK_SET); |
| parse_gps(base); |
| fseek(ifp, pos, SEEK_SET); |
| parse_gps_libraw(base); |
| } |
| break; |
| case 0x8773: /* 34675, InterColorProfile */ |
| case 0xc68f: /* 50831, AsShotICCProfile */ |
| profile_offset = ftell(ifp); |
| profile_length = len; |
| break; |
| case 0x9102: /* 37122, CompressedBitsPerPixel */ |
| kodak_cbpp = get4(); |
| break; |
| case 0x920a: /* 37386, FocalLength */ |
| focal_len = getrealf(type); |
| break; |
| case 0x9211: /* 37393, ImageNumber */ |
| shot_order = getint(type); |
| break; |
| case 0x9215: /* 37397, ExposureIndex */ |
| imCommon.exifExposureIndex = getrealf(type); |
| break; |
| case 0x9218: /* 37400, old Kodak KDC tag */ |
| for (raw_color = i = 0; i < 3; i++) |
| { |
| getreal(type); |
| FORC3 rgb_cam[i][c] = getrealf(type); |
| } |
| break; |
| case 0xa010: // 40976 |
| strip_offset = get4(); |
| switch (tiff_ifd[ifd].comp) |
| { |
| case 0x8002: // 32770 |
| load_raw = &LibRaw::samsung_load_raw; |
| break; |
| case 0x8004: // 32772 |
| load_raw = &LibRaw::samsung2_load_raw; |
| break; |
| case 0x8005: // 32773 |
| load_raw = &LibRaw::samsung3_load_raw; |
| break; |
| } |
| break; |
| case 0xb4c3: /* 46275, Imacon tags */ |
| imHassy.format = LIBRAW_HF_Imacon; |
| strcpy(make, "Imacon"); |
| data_offset = ftell(ifp); |
| ima_len = len; |
| break; |
| case 0xb4c7: // 46279 |
| if (!ima_len) |
| break; |
| fseek(ifp, 38, SEEK_CUR); |
| case 0xb4c2: // 46274 |
| fseek(ifp, 40, SEEK_CUR); |
| raw_width = get4(); |
| raw_height = get4(); |
| left_margin = get4() & 7; |
| width = raw_width - left_margin - (get4() & 7); |
| top_margin = get4() & 7; |
| height = raw_height - top_margin - (get4() & 7); |
| if (raw_width == 7262 && ima_len == 234317952) |
| { |
| height = 5412; |
| width = 7216; |
| left_margin = 7; |
| filters = 0; |
| } |
| else if (raw_width == 7262) |
| { |
| height = 5444; |
| width = 7244; |
| left_margin = 7; |
| } |
| fseek(ifp, 52, SEEK_CUR); |
| FORC3 cam_mul[c] = getrealf(LIBRAW_EXIFTAG_TYPE_FLOAT); |
| fseek(ifp, 114, SEEK_CUR); |
| flip = (get2() >> 7) * 90; |
| if (width * (height * 6l) == ima_len) |
| { |
| if (flip % 180 == 90) |
| SWAP(width, height); |
| raw_width = width; |
| raw_height = height; |
| left_margin = top_margin = filters = flip = 0; |
| } |
| c = unsigned(height) * unsigned(width) / 1000000; |
| if (c == 32) |
| c--; |
| sprintf(model, "Ixpress %d-Mp", c); |
| load_raw = &LibRaw::imacon_full_load_raw; |
| if (filters) |
| { |
| if (left_margin & 1) |
| filters = 0x61616161; |
| load_raw = &LibRaw::unpacked_load_raw; |
| } |
| maximum = 0xffff; |
| break; |
| case 0xc516: /* 50454, Sinar tag */ |
| case 0xc517: // 50455 |
| if (len < 1 || len > 2560000 || !(cbuf = (char *)malloc(len))) |
| break; |
| if (fread(cbuf, 1, len, ifp) != (int)len) |
| throw LIBRAW_EXCEPTION_IO_CORRUPT; // cbuf to be free'ed in recycle |
| cbuf[len - 1] = 0; |
| for (cp = cbuf - 1; cp && cp < cbuf + len; cp = strchr(cp, '\n')) |
| if (!strncmp(++cp, "Neutral ", 8)) |
| sscanf(cp + 8, "%f %f %f", cam_mul, cam_mul + 1, cam_mul + 2); |
| free(cbuf); |
| break; |
| case 0xc51a: // 50458 |
| if (!make[0]) |
| strcpy(make, "Hasselblad"); |
| break; |
| case 0xc51b: /* 50459, Hasselblad tag */ |
| if (!libraw_internal_data.unpacker_data.hasselblad_parser_flag) |
| { |
| libraw_internal_data.unpacker_data.hasselblad_parser_flag = 1; |
| i = order; |
| INT64 jj = ftell(ifp); |
| c = tiff_nifds; |
| order = get2(); |
| get2(); |
| fseek(ifp, jj + get4(), SEEK_SET); |
| parse_tiff_ifd(jj); |
| maximum = 0xffff; |
| tiff_nifds = c; |
| order = i; |
| break; |
| } |
| case 0xc612: /* 50706, DNGVersion */ |
| FORC4 dng_version = (dng_version << 8) + fgetc(ifp); |
| if (!make[0]) |
| strcpy(make, "DNG"); |
| is_raw = 1; |
| break; |
| case 0xc614: /* 50708, UniqueCameraModel */ |
| stmread(imgdata.color.UniqueCameraModel, len, ifp); |
| if (model[0]) |
| break; |
| strncpy(make, imgdata.color.UniqueCameraModel, |
| MIN(len, sizeof(imgdata.color.UniqueCameraModel))); |
| if ((cp = strchr(make, ' '))) |
| { |
| strcpy(model, cp + 1); |
| *cp = 0; |
| } |
| break; |
| case 0xc616: /* 50710, CFAPlaneColor */ |
| if (filters == 9) |
| break; |
| if (len > 4) |
| len = 4; |
| colors = len; |
| fread(cfa_pc, 1, colors, ifp); |
| guess_cfa_pc: |
| FORCC tab[cfa_pc[c]] = c; |
| cdesc[c] = 0; |
| for (i = 16; i--;) |
| filters = filters << 2 | tab[cfa_pat[i % plen]]; |
| filters -= !filters; |
| tiff_ifd[ifd].t_filters = filters; |
| break; |
| case 0xc617: /* 50711, CFALayout */ |
| if (get2() == 2) |
| tiff_ifd[ifd].t_fuji_width = fuji_width = 1; |
| break; |
| case 0x0123: // 291 |
| case 0xc618: /* 50712, LinearizationTable */ |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_LINTABLE; |
| tiff_ifd[ifd].lineartable_offset = ftell(ifp); |
| tiff_ifd[ifd].lineartable_len = len; |
| linear_table(len); |
| break; |
| case 0xc619: /* 50713, BlackLevelRepeatDim */ |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK; |
| |
| tiff_ifd[ifd].dng_levels.dng_cblack[4] = cblack[4] = get2(); |
| tiff_ifd[ifd].dng_levels.dng_fcblack[4] = float(cblack[4]); |
| |
| |
| tiff_ifd[ifd].dng_levels.dng_cblack[5] = cblack[5] = get2(); |
| tiff_ifd[ifd].dng_levels.dng_fcblack[5] = float(cblack[5]); |
| |
| if (cblack[4] * cblack[5] > |
| (LIBRAW_CBLACK_SIZE - |
| 7)) // Use last cblack item as DNG black level count |
| { |
| tiff_ifd[ifd].dng_levels.dng_fcblack[4] = |
| tiff_ifd[ifd].dng_levels.dng_fcblack[5] = 1.f; |
| tiff_ifd[ifd].dng_levels.dng_cblack[4] = tiff_ifd[ifd].dng_levels.dng_cblack[5] = |
| cblack[4] = cblack[5] = 1; |
| } |
| break; |
| |
| case 0xf00c: |
| if (imFuji.RAFDataGeneration != 4096) |
| { |
| unsigned fwb[4]; |
| FORC4 fwb[c] = get4(); |
| if (fwb[3] < 0x100) |
| { |
| FORC3 icWBC[fwb[3]][GRBG_2_RGBG(c)] = fwb[c]; |
| icWBC[fwb[3]][3] = icWBC[fwb[3]][1]; |
| if ((fwb[3] == 17) && // Tungsten WB |
| (libraw_internal_data.unpacker_data.lenRAFData > 3) && |
| (libraw_internal_data.unpacker_data.lenRAFData < 10240000)) |
| { |
| INT64 f_save = ftell(ifp); |
| rafdata = (ushort *)calloc( |
| sizeof(ushort) * libraw_internal_data.unpacker_data.lenRAFData+1,1); |
| fseek(ifp, libraw_internal_data.unpacker_data.posRAFData, SEEK_SET); |
| fread(rafdata, sizeof(ushort), |
| libraw_internal_data.unpacker_data.lenRAFData, ifp); |
| fseek(ifp, f_save, SEEK_SET); |
| |
| uchar *PrivateMknBuf = (uchar *)rafdata; |
| int PrivateMknLength = libraw_internal_data.unpacker_data.lenRAFData |
| << 1; |
| for (int pos = 0; pos < PrivateMknLength - 16; pos++) |
| { |
| if (!memcmp(PrivateMknBuf + pos, "TSNERDTS", 8)) // STDRENST |
| { |
| imFuji.isTSNERDTS = 1; |
| break; |
| } |
| } |
| int fj; // 31? (fj<<1)-0x3c : 34? (fj<<1)-0x4e : undef |
| int is34 = 0; |
| if ((imFuji.RAFDataVersion == 0x0260) || // X-Pro3, GFX 100S |
| (imFuji.RAFDataVersion == 0x0261) || // X100V, GFX 50S II |
| (imFuji.RAFDataVersion == 0x0262) || // X-T4 |
| (imFuji.RAFDataVersion == 0x0263) || // X-H2S |
| (imFuji.RAFDataVersion == 0x0264) || // X-S10, X-H2 |
| (imFuji.RAFDataVersion == 0x0265) || // X-E4, X-T5 |
| (imFuji.RAFDataVersion == 0x0266) || // X-T30 II, X-S20 |
| (imFuji.RAFDataVersion == 0x0267) || // GFX 100 II |
| (imFuji.RAFDataVersion == 0x0368) || // GFX 100S II |
| (imFuji.RAFDataVersion == 0x0369) || // X100VI |
| (imFuji.RAFDataVersion == 0x036a) || // X-T50 |
| (imFuji.RAFDataVersion == 0x036b) || // X-M5 |
| !strcmp(model, "X-Pro3") || |
| !strcmp(model, "GFX100S II") || !strcmp(model, "GFX 100S II") || |
| !strcmp(model, "GFX100S") || !strcmp(model, "GFX 100S") || |
| !strcmp(model, "GFX100 II") || !strcmp(model, "GFX 100 II") || |
| !strcmp(model, "GFX50S II") || !strcmp(model, "GFX 50S II") || |
| !strcmp(model, "X100VI") || |
| !strcmp(model, "X100V") || |
| !strcmp(model, "X-T4") || |
| !strcmp(model, "X-H2S") || |
| !strcmp(model, "X-H2") || |
| !strcmp(model, "X-E4") || |
| !strcmp(model, "X-T50") || |
| !strcmp(model, "X-T5") || |
| !strcmp(model, "X-M5") || |
| !strcmp(model, "X-T30 II") || |
| !strcmp(model, "X-S10") || |
| !strcmp(model, "X-S20")) |
| // is34 cameras have 34 CCT values instead of 31, manual still claims 2500 to 10000 K |
| // aligned 3000 K to Incandescent, as it is usual w/ other Fujifilm cameras |
| is34 = 1; |
| |
| for (int fi = 0; |
| fi < int(libraw_internal_data.unpacker_data.lenRAFData - 3); fi++) // looking for Tungsten WB |
| { |
| if ((fwb[0] == rafdata[fi]) && (fwb[1] == rafdata[fi + 1]) && |
| (fwb[2] == rafdata[fi + 2])) // found Tungsten WB |
| { |
| if (fi > 14 && rafdata[fi - 15] != |
| fwb[0]) // 15 is offset of Tungsten WB from the first |
| // preset, Fine Weather WB |
| continue; |
| if (fi >= 15) |
| { |
| for (int wb_ind = 0, ofst = fi - 15; wb_ind < (int)Fuji_wb_list1.size(); |
| wb_ind++, ofst += 3) |
| { |
| icWBC[Fuji_wb_list1[wb_ind]][1] = |
| icWBC[Fuji_wb_list1[wb_ind]][3] = rafdata[ofst]; |
| icWBC[Fuji_wb_list1[wb_ind]][0] = rafdata[ofst + 1]; |
| icWBC[Fuji_wb_list1[wb_ind]][2] = rafdata[ofst + 2]; |
| } |
| } |
| |
| if (is34) |
| fi += 24; |
| fi += 96; |
| for (fj = fi; fj < (fi + 15); fj += 3) // looking for the end of the WB table |
| { |
| if (fj > libraw_internal_data.unpacker_data.lenRAFData - 3) |
| break; |
| if (rafdata[fj] != rafdata[fi]) |
| { |
| fj -= 93; |
| if (is34) |
| fj -= 9; |
| //printf ("wb start in DNG: 0x%04x\n", fj*2-0x4e); |
| for (int iCCT = 0, ofst = fj; iCCT < 31 |
| && ofst < libraw_internal_data.unpacker_data.lenRAFData - 3; |
| iCCT++, ofst += 3) |
| { |
| icWBCCTC[iCCT][0] = float(FujiCCT_K[iCCT]); |
| icWBCCTC[iCCT][1] = rafdata[ofst + 1]; |
| icWBCCTC[iCCT][2] = icWBCCTC[iCCT][4] = rafdata[ofst]; |
| icWBCCTC[iCCT][3] = rafdata[ofst + 2]; |
| } |
| break; |
| } |
| } |
| free(rafdata); |
| break; |
| } |
| } |
| } |
| } |
| FORC4 fwb[c] = get4(); |
| if (fwb[3] < 0x100) { |
| FORC3 icWBC[fwb[3]][GRBG_2_RGBG(c)] = fwb[c]; |
| icWBC[fwb[3]][3] = icWBC[fwb[3]][1]; |
| } |
| } |
| break; |
| case 0xf00d: |
| if (imFuji.RAFDataGeneration != 4096) |
| { |
| FORC3 icWBC[LIBRAW_WBI_Auto][GRBG_2_RGBG(c)] = getint(type); |
| icWBC[LIBRAW_WBI_Auto][3] = icWBC[LIBRAW_WBI_Auto][1]; |
| } |
| break; |
| case 0xc615: /* 50709, LocalizedCameraModel */ |
| stmread(imgdata.color.LocalizedCameraModel, len, ifp); |
| break; |
| case 0xf00a: // 61450 |
| cblack[4] = cblack[5] = int(MIN(sqrtf((float)len), 64.f)); |
| case 0xc61a: /* 50714, BlackLevel */ |
| if (tiff_ifd[ifd].samples > 1 && |
| tiff_ifd[ifd].samples == (int)len) // LinearDNG, per-channel black |
| { |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK; |
| for (i = 0; i < 4 && i < (int)len; i++) |
| { |
| tiff_ifd[ifd].dng_levels.dng_fcblack[i] = getrealf(type); |
| tiff_ifd[ifd].dng_levels.dng_cblack[i] = cblack[i] = |
| unsigned(tiff_ifd[ifd].dng_levels.dng_fcblack[i] + 0.5f); |
| } |
| // Record len in last cblack field |
| tiff_ifd[ifd].dng_levels.dng_cblack[LIBRAW_CBLACK_SIZE - 1] = len; |
| |
| tiff_ifd[ifd].dng_levels.dng_fblack = 0.f; |
| tiff_ifd[ifd].dng_levels.dng_black = black = 0; |
| } |
| else if (tiff_ifd[ifd].samples > 1 // Linear DNG w repeat dim |
| && (tiff_ifd[ifd].samples * cblack[4] * cblack[5] == len)) |
| { |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK; |
| tiff_ifd[ifd].dng_levels.dng_cblack[LIBRAW_CBLACK_SIZE - 1] = |
| cblack[LIBRAW_CBLACK_SIZE - 1] = len; |
| for (i = 0; i < (int)len && i < LIBRAW_CBLACK_SIZE - 7; i++) |
| { |
| tiff_ifd[ifd].dng_levels.dng_fcblack[i + 6] = getrealf(type); |
| tiff_ifd[ifd].dng_levels.dng_cblack[i + 6] = cblack[i + 6] = |
| unsigned(tiff_ifd[ifd].dng_levels.dng_fcblack[i + 6] + 0.5f); |
| } |
| } |
| else if ((cblack[4] * cblack[5] < 2) && len == 1) |
| { |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK; |
| tiff_ifd[ifd].dng_levels.dng_fblack = getrealf(type); |
| black = tiff_ifd[ifd].dng_levels.dng_black = |
| unsigned(tiff_ifd[ifd].dng_levels.dng_fblack); |
| } |
| else if (cblack[4] * cblack[5] <= len) |
| { |
| FORC(int(cblack[4] * cblack[5])) |
| { |
| tiff_ifd[ifd].dng_levels.dng_fcblack[6 + c] = getrealf(type); |
| cblack[6 + c] = unsigned(tiff_ifd[ifd].dng_levels.dng_fcblack[6 + c]); |
| } |
| black = 0; |
| FORC4 |
| cblack[c] = 0; |
| |
| if (tag == 0xc61a) |
| { |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK; |
| FORC(int(cblack[4] * cblack[5])) |
| tiff_ifd[ifd].dng_levels.dng_cblack[6 + c] = cblack[6 + c]; |
| tiff_ifd[ifd].dng_levels.dng_fblack = 0; |
| tiff_ifd[ifd].dng_levels.dng_black = 0; |
| FORC4 |
| { |
| tiff_ifd[ifd].dng_levels.dng_fcblack[c] = 0.f; |
| tiff_ifd[ifd].dng_levels.dng_cblack[c] = 0; |
| } |
| } |
| } |
| break; |
| case 0xc61b: /* 50715, BlackLevelDeltaH */ |
| case 0xc61c: /* 50716, BlackLevelDeltaV */ |
| for (num = i = 0; i < (int)len && i < 65536; i++) |
| num += getreal(type); |
| if (len > 0) |
| { |
| black += unsigned(num / len + 0.5); |
| tiff_ifd[ifd].dng_levels.dng_fblack += float(num / len); |
| tiff_ifd[ifd].dng_levels.dng_black += unsigned(num / len + 0.5); |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK; |
| } |
| break; |
| case 0xc61d: /* 50717, WhiteLevel */ |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_WHITE; |
| tiff_ifd[ifd].dng_levels.dng_whitelevel[0] = maximum = getint(type); |
| if (tiff_ifd[ifd].samples > 1) // Linear DNG case |
| for (i = 1; i < 4 && i < (int)len; i++) |
| tiff_ifd[ifd].dng_levels.dng_whitelevel[i] = getint(type); |
| break; |
| case 0xc61e: /* DefaultScale */ |
| { |
| float q1 = getrealf(type); |
| float q2 = getrealf(type); |
| if (q1 > 0.00001f && q2 > 0.00001f) |
| { |
| pixel_aspect = q1 / q2; |
| if (pixel_aspect > 0.995 && pixel_aspect < 1.005) |
| pixel_aspect = 1.0; |
| } |
| } |
| break; |
| case 0xc61f: /* 50719, DefaultCropOrigin */ |
| if (len == 2) |
| { |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_CROPORIGIN; |
| tiff_ifd[ifd].dng_levels.default_crop[0] = ushort(getreal(type)); |
| tiff_ifd[ifd].dng_levels.default_crop[1] = ushort(getreal(type)); |
| if (!strncasecmp(make, "SONY", 4)) |
| { |
| imgdata.sizes.raw_inset_crops[0].cleft = |
| tiff_ifd[ifd].dng_levels.default_crop[0]; |
| imgdata.sizes.raw_inset_crops[0].ctop = |
| tiff_ifd[ifd].dng_levels.default_crop[1]; |
| } |
| } |
| break; |
| |
| case 0xc620: /* 50720, DefaultCropSize */ |
| if (len == 2) |
| { |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_CROPSIZE; |
| tiff_ifd[ifd].dng_levels.default_crop[2] = ushort(getreal(type)); |
| tiff_ifd[ifd].dng_levels.default_crop[3] = ushort(getreal(type)); |
| if (!strncasecmp(make, "SONY", 4)) |
| { |
| imgdata.sizes.raw_inset_crops[0].cwidth = |
| tiff_ifd[ifd].dng_levels.default_crop[2]; |
| imgdata.sizes.raw_inset_crops[0].cheight = |
| tiff_ifd[ifd].dng_levels.default_crop[3]; |
| } |
| } |
| break; |
| |
| case 0xc7b5: /* 51125 DefaultUserCrop */ |
| if (len == 4) |
| { |
| int cnt = 0; |
| FORC4 |
| { |
| float v = getrealf(type); |
| if (v >= 0.f && v <= 1.f) |
| { |
| tiff_ifd[ifd].dng_levels.user_crop[c] = v; |
| cnt++; |
| } |
| } |
| if(cnt == 4 // valid values |
| && tiff_ifd[ifd].dng_levels.user_crop[0] < tiff_ifd[ifd].dng_levels.user_crop[2] // top < bottom |
| && tiff_ifd[ifd].dng_levels.user_crop[1] < tiff_ifd[ifd].dng_levels.user_crop[3] // left < right |
| ) |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_USERCROP; |
| } |
| break; |
| case 0x74c7: |
| if ((len == 2) && !strncasecmp(make, "SONY", 4)) |
| { |
| imgdata.sizes.raw_inset_crops[0].cleft = get4(); |
| imgdata.sizes.raw_inset_crops[0].ctop = get4(); |
| } |
| break; |
| |
| case 0x74c8: |
| if ((len == 2) && !strncasecmp(make, "SONY", 4)) |
| { |
| imgdata.sizes.raw_inset_crops[0].cwidth = get4(); |
| imgdata.sizes.raw_inset_crops[0].cheight = get4(); |
| } |
| break; |
| |
| case 0xc65a: // 50778 |
| tiff_ifd[ifd].dng_color[0].illuminant = get2(); |
| tiff_ifd[ifd].dng_color[0].parsedfields |= LIBRAW_DNGFM_ILLUMINANT; |
| break; |
| case 0xc65b: // 50779 |
| tiff_ifd[ifd].dng_color[1].illuminant = get2(); |
| tiff_ifd[ifd].dng_color[1].parsedfields |= LIBRAW_DNGFM_ILLUMINANT; |
| break; |
| |
| case 0xc621: /* 50721, ColorMatrix1 */ |
| case 0xc622: /* 50722, ColorMatrix2 */ |
| { |
| int chan = (len == 9) ? 3 : (len == 12 ? 4 : 0); |
| i = tag == 0xc621 ? 0 : 1; |
| if (chan) |
| { |
| tiff_ifd[ifd].dng_color[i].parsedfields |= LIBRAW_DNGFM_COLORMATRIX; |
| imHassy.nIFD_CM[i] = ifd; |
| } |
| FORC(chan) for (j = 0; j < 3; j++) |
| { |
| cm[c][j] = getreal(type); |
| tiff_ifd[ifd].dng_color[i].colormatrix[c][j] = float(cm[c][j]); |
| } |
| use_cm = 1; |
| } |
| break; |
| |
| case 0xc714: /* ForwardMatrix1 */ |
| case 0xc715: /* ForwardMatrix2 */ |
| { |
| int chan = (len == 9) ? 3 : (len == 12 ? 4 : 0); |
| i = tag == 0xc714 ? 0 : 1; |
| if (chan) |
| tiff_ifd[ifd].dng_color[i].parsedfields |= LIBRAW_DNGFM_FORWARDMATRIX; |
| for (j = 0; j < 3; j++) |
| FORC(chan) |
| { |
| fm[j][c] = getreal(type); |
| tiff_ifd[ifd].dng_color[i].forwardmatrix[j][c] = float(fm[j][c]); |
| } |
| } |
| break; |
| |
| case 0xc623: /* 50723, CameraCalibration1 */ |
| case 0xc624: /* 50724, CameraCalibration2 */ |
| { |
| int chan = (len == 9) ? 3 : (len == 16 ? 4 : 0); |
| j = tag == 0xc623 ? 0 : 1; |
| if (chan) |
| tiff_ifd[ifd].dng_color[j].parsedfields |= LIBRAW_DNGFM_CALIBRATION; |
| for (i = 0; i < chan; i++) |
| FORC(chan) |
| { |
| cc[i][c] = getreal(type); |
| tiff_ifd[ifd].dng_color[j].calibration[i][c] = float(cc[i][c]); |
| } |
| } |
| break; |
| case 0xc627: /* 50727, AnalogBalance */ |
| if (len >= 3) |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_ANALOGBALANCE; |
| for (c = 0; c < (int)len && c < 4; c++) |
| { |
| ab[c] = getreal(type); |
| tiff_ifd[ifd].dng_levels.analogbalance[c] = float(ab[c]); |
| } |
| break; |
| case 0xc628: /* 50728, AsShotNeutral */ |
| if (len >= 3) |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_ASSHOTNEUTRAL; |
| for (c = 0; c < (int)len && c < 4; c++) |
| { |
| asn[c] = getreal(type); |
| tiff_ifd[ifd].dng_levels.asshotneutral[c] = float(asn[c]); |
| } |
| break; |
| case 0xc629: /* 50729, AsShotWhiteXY */ |
| xyz[0] = getreal(type); |
| xyz[1] = getreal(type); |
| xyz[2] = 1 - xyz[0] - xyz[1]; |
| FORC3 xyz[c] /= LibRaw_constants::d65_white[c]; |
| break; |
| case 0xc62a: /* DNG: 50730 BaselineExposure */ |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BASELINEEXPOSURE; |
| tiff_ifd[ifd].dng_levels.baseline_exposure = getrealf(type); |
| break; |
| case 0xc62e: /* DNG: 50734 LinearResponseLimit */ |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_LINEARRESPONSELIMIT; |
| tiff_ifd[ifd].dng_levels.LinearResponseLimit = getrealf(type); |
| break; |
| |
| case 0xc634: /* 50740 : DNG Adobe, DNG Pentax, Sony SR2, DNG Private */ |
| { |
| char mbuf[64]; |
| INT64 curr_pos, start_pos = ftell(ifp); |
| unsigned MakN_order, m_sorder = order; |
| unsigned MakN_length; |
| unsigned pos_in_original_raw; |
| fread(mbuf, 1, 6, ifp); |
| |
| if (!strcmp(mbuf, "Adobe")) |
| { |
| order = 0x4d4d; // Adobe header is always in "MM" / big endian |
| curr_pos = start_pos + 6; |
| while (curr_pos + 8 - start_pos <= len) |
| { |
| fread(mbuf, 1, 4, ifp); |
| curr_pos += 8; |
| |
| if (!strncmp(mbuf, "Pano", 4)) |
| { // PanasonicRaw, yes, they use "Pano" as signature |
| parseAdobePanoMakernote(); |
| } |
| |
| if (!strncmp(mbuf, "MakN", 4)) |
| { |
| MakN_length = get4(); |
| MakN_order = get2(); |
| pos_in_original_raw = get4(); |
| order = MakN_order; |
| |
| INT64 save_pos = ifp->tell(); |
| parse_makernote_0xc634(curr_pos + 6 - pos_in_original_raw, 0, |
| AdobeDNG); |
| |
| curr_pos = save_pos + MakN_length - 6; |
| fseek(ifp, curr_pos, SEEK_SET); |
| |
| fread(mbuf, 1, 4, ifp); |
| curr_pos += 8; |
| |
| if (!strncmp(mbuf, "Pano ", 4)) |
| { |
| parseAdobePanoMakernote(); |
| } |
| |
| if (!strncmp(mbuf, "RAF ", 4)) |
| { // Fujifilm Raw, AdobeRAF |
| try { |
| parseAdobeRAFMakernote(); // May raise exception for out-of buffer reads |
| } |
| catch (...) |
| { |
| // just ignore it |
| } |
| } |
| |
| if (!strncmp(mbuf, "SR2 ", 4)) |
| { |
| order = 0x4d4d; |
| MakN_length = get4(); |
| MakN_order = get2(); |
| pos_in_original_raw = get4(); |
| order = MakN_order; |
| |
| unsigned *buf_SR2; |
| unsigned SR2SubIFDOffset = 0; |
| unsigned SR2SubIFDLength = 0; |
| unsigned SR2SubIFDKey = 0; |
| { |
| INT64 _base = curr_pos + 6 - pos_in_original_raw; |
| unsigned _entries, _tag, _type, _len; |
| INT64 _save; |
| _entries = get2(); |
| while (_entries--) |
| { |
| tiff_get(_base, &_tag, &_type, &_len, &_save); |
| if (callbacks.exif_cb) |
| { |
| INT64 _savepos = ftell(ifp); |
| callbacks.exif_cb(callbacks.exifparser_data, tag | 0x60000, |
| _type, _len, order, ifp, base); |
| fseek(ifp, _savepos, SEEK_SET); |
| } |
| |
| if (_tag == 0x7200) |
| { |
| SR2SubIFDOffset = get4(); |
| } |
| else if (_tag == 0x7201) |
| { |
| SR2SubIFDLength = get4(); |
| } |
| else if (_tag == 0x7221) |
| { |
| SR2SubIFDKey = get4(); |
| } |
| fseek(ifp, _save, SEEK_SET); |
| } |
| } |
| |
| if (SR2SubIFDLength && (SR2SubIFDLength < 10240000) && |
| (buf_SR2 = (unsigned *)calloc(SR2SubIFDLength + 1024,1))) |
| { // 1024b for safety |
| fseek(ifp, SR2SubIFDOffset + base, SEEK_SET); |
| int items = fread(buf_SR2, 1, SR2SubIFDLength, ifp); |
| if (items == SR2SubIFDLength) |
| { |
| sony_decrypt(buf_SR2, SR2SubIFDLength / 4, 1, SR2SubIFDKey); |
| parseSonySR2((uchar *)buf_SR2, SR2SubIFDOffset, |
| SR2SubIFDLength, AdobeDNG); |
| } |
| free(buf_SR2); |
| } |
| |
| } /* SR2 processed */ |
| break; |
| } |
| } |
| } |
| else |
| { |
| fread(mbuf + 6, 1, 2, ifp); |
| if (!strcmp(mbuf, "RICOH") && ((sget2((uchar *)mbuf + 6) == 0x4949) || |
| (sget2((uchar *)mbuf + 6) == 0x4d4d))) |
| { |
| is_PentaxRicohMakernotes = 1; |
| } |
| if (!strcmp(mbuf, "PENTAX ") || !strcmp(mbuf, "SAMSUNG") || |
| is_PentaxRicohMakernotes) |
| { |
| fseek(ifp, start_pos, SEEK_SET); |
| parse_makernote_0xc634(base, 0, CameraDNG); |
| } |
| } |
| fseek(ifp, start_pos, SEEK_SET); |
| order = m_sorder; |
| } |
| if (dng_version) |
| { |
| break; |
| } |
| |
| { |
| INT64 jj = get4() + base; |
| parse_minolta(jj); |
| fseek(ifp, jj, SEEK_SET); |
| } |
| parse_tiff_ifd(base); |
| break; |
| case 0xc640: // 50752 |
| read_shorts(cr2_slice, 3); |
| break; |
| case 0xc68b: /* 50827, OriginalRawFileName */ |
| stmread(imgdata.color.OriginalRawFileName, len, ifp); |
| break; |
| case 0xc68d: /* 50829 ActiveArea */ |
| tiff_ifd[ifd].t_tm = top_margin = getint(type); |
| tiff_ifd[ifd].t_lm = left_margin = getint(type); |
| tiff_ifd[ifd].t_vheight = height = getint(type) - top_margin; |
| tiff_ifd[ifd].t_vwidth = width = getint(type) - left_margin; |
| break; |
| case 0xc68e: /* 50830 MaskedAreas */ |
| for (i = 0; i < (int)len && i < 32; i++) |
| ((int *)mask)[i] = getint(type); |
| black = 0; |
| break; |
| case 0xc71a: /* 50970, PreviewColorSpace */ |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_PREVIEWCS; |
| tiff_ifd[ifd].dng_levels.preview_colorspace = getint(type); |
| break; |
| case 0xc740: /* 51008, OpcodeList1 */ |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_OPCODE1; |
| if (len < 4 * 1024 * 1024) // 4M per opcode list limit |
| { |
| tiff_ifd[ifd].dng_levels.rawopcodes[0].len = len; |
| tiff_ifd[ifd].dng_levels.rawopcodes[0].data = calloc(len,1); |
| fread(tiff_ifd[ifd].dng_levels.rawopcodes[0].data, 1, len, ifp); |
| } |
| break; |
| case 0xc741: /* 51009, OpcodeList2 */ |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_OPCODE2; |
| tiff_ifd[ifd].opcode2_offset = meta_offset = ftell(ifp); |
| if (len < 4 * 1024 * 1024) // 4M per opcode list limit |
| { |
| tiff_ifd[ifd].dng_levels.rawopcodes[1].len = len; |
| tiff_ifd[ifd].dng_levels.rawopcodes[1].data = calloc(len,1); |
| fread(tiff_ifd[ifd].dng_levels.rawopcodes[1].data, 1, len, ifp); |
| } |
| break; |
| case 0xc74e: /* 51022, OpcodeList3 */ |
| tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_OPCODE3; |
| if (len < 4 * 1024 * 1024) // 4M per opcode list limit |
| { |
| tiff_ifd[ifd].dng_levels.rawopcodes[2].len = len; |
| tiff_ifd[ifd].dng_levels.rawopcodes[2].data = calloc(len,1); |
| fread(tiff_ifd[ifd].dng_levels.rawopcodes[2].data, 1, len, ifp); |
| } |
| break; |
| case 0xfd04: /* 64772, Kodak P-series */ |
| if (len < 13) |
| break; |
| fseek(ifp, 16, SEEK_CUR); |
| data_offset = get4(); |
| fseek(ifp, 28, SEEK_CUR); |
| data_offset += get4(); |
| load_raw = &LibRaw::packed_load_raw; |
| break; |
| case 0xfe02: // 65026 |
| if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_ASCII)) |
| fgets(model2, 64, ifp); |
| } |
| fseek(ifp, save, SEEK_SET); |
| } |
| if (sony_length && sony_length < 10240000 && |
| (buf = (unsigned *)calloc(sony_length, 1))) |
| { |
| fseek(ifp, sony_offset, SEEK_SET); |
| int items = fread(buf, 1, sony_length, ifp); |
| if (items == sony_length) |
| { |
| sony_decrypt(buf, sony_length / 4, 1, sony_key); |
| parseSonySR2((uchar *)buf, sony_offset, sony_length, nonDNG); |
| } |
| free(buf); |
| } |
| for (i = 0; i < colors && i < 4; i++) |
| FORCC cc[i][c] *= ab[i]; |
| if (use_cm) |
| { |
| FORCC for (i = 0; i < 3; i++) for (cam_xyz[c][i] = j = 0; j < colors; j++) |
| cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i]; |
| cam_xyz_coeff(cmatrix, cam_xyz); |
| } |
| if (asn[0]) |
| { |
| cam_mul[3] = 0; |
| FORCC |
| if (fabs(asn[c]) > 0.0001) |
| cam_mul[c] = float(1. / asn[c]); |
| } |
| if (!use_cm) |
| FORCC if (fabs(cc[c][c]) > 0.0001) pre_mul[c] /= float(cc[c][c]); |
| return 0; |
| } |
| |
| int LibRaw::parse_tiff(INT64 _base) |
| { |
| INT64 base = _base; |
| int doff; |
| fseek(ifp, base, SEEK_SET); |
| order = get2(); |
| if (order != 0x4949 && order != 0x4d4d) |
| return 0; |
| get2(); |
| while ((doff = get4())) |
| { |
| INT64 doff64 = doff; |
| if (doff64 + base > ifp->size()) break; |
| fseek(ifp, doff64 + base, SEEK_SET); |
| if (parse_tiff_ifd(_base)) |
| break; |
| } |
| return 1; |
| } |
| |
| struct ifd_size_t |
| { |
| int ifdi; |
| INT64 databits; |
| }; |
| |
| int ifd_size_t_cmp(const void *a, const void *b) |
| { |
| if (!a || !b) |
| return 0; |
| const ifd_size_t *ai = (ifd_size_t *)a; |
| const ifd_size_t *bi = (ifd_size_t *)b; |
| return bi->databits > ai->databits ? 1 |
| : (bi->databits < ai->databits ? -1 : 0); |
| } |
| |
| static LibRaw_internal_thumbnail_formats tiff2thumbformat(int _comp, int _phint, int _bps, const char *_make, bool isDNG); |
| |
| void LibRaw::apply_tiff() |
| { |
| int max_samp = 0, ties = 0, raw = -1, thm = -1, i; |
| unsigned long long ns, os; |
| struct jhead jh; |
| |
| thumb_misc = 16; |
| if (thumb_offset) |
| { |
| fseek(ifp, thumb_offset, SEEK_SET); |
| if (ljpeg_start(&jh, 1)) |
| { |
| if ((unsigned)jh.bits < 17 && (unsigned)jh.wide < 0x10000 && |
| (unsigned)jh.high < 0x10000) |
| { |
| thumb_misc = jh.bits; |
| thumb_width = jh.wide; |
| thumb_height = jh.high; |
| } |
| } |
| } |
| for (i = tiff_nifds; i--;) |
| { |
| if (tiff_ifd[i].t_shutter) |
| shutter = tiff_ifd[i].t_shutter; |
| tiff_ifd[i].t_shutter = shutter; |
| } |
| |
| if (dng_version) |
| { |
| int ifdc = 0; |
| for (i = 0; i < (int)tiff_nifds; i++) |
| { |
| if (tiff_ifd[i].t_width < 1 || tiff_ifd[i].t_width > 65535 || |
| tiff_ifd[i].t_height < 1 || tiff_ifd[i].t_height > 65535) |
| continue; /* wrong image dimensions */ |
| |
| int samp = tiff_ifd[i].samples; |
| if (samp == 2) |
| samp = 1; // Fuji 2-frame |
| max_samp = LIM(MAX(max_samp, samp), 1, |
| 3); // max_samp is needed for thumbnail selection below |
| |
| if ( // Check phint only for RAW subfiletype |
| (tiff_ifd[i].newsubfiletype == 16 |
| || tiff_ifd[i].newsubfiletype == 0 |
| || (tiff_ifd[i].newsubfiletype & 0xffff) == 1) |
| && |
| (tiff_ifd[i].phint != 32803 && tiff_ifd[i].phint != 34892) |
| ) |
| continue; |
| |
| if ((tiff_ifd[i].newsubfiletype == 0) // main image |
| // Enhanced demosaiced: |
| || (tiff_ifd[i].newsubfiletype == 16 && |
| (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_ADD_ENHANCED)) |
| // Preview: 0x1 or 0x10001 |
| || ((tiff_ifd[i].newsubfiletype & 0xffff) == 1 && |
| (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_ADD_PREVIEWS)) |
| // Transparency mask: 0x4 |
| || ((tiff_ifd[i].newsubfiletype & 0xffff) == 4 && |
| (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_ADD_MASKS))) |
| { |
| // Add this IFD to dng_frames |
| libraw_internal_data.unpacker_data.dng_frames[ifdc] = |
| ((tiff_ifd[i].newsubfiletype & 0xffff) << 16) | ((i << 8) & 0xff00); |
| ifdc++; |
| // Fuji SuperCCD: second frame: |
| if ((tiff_ifd[i].newsubfiletype == 0) && tiff_ifd[i].samples == 2) |
| { |
| libraw_internal_data.unpacker_data.dng_frames[ifdc] = |
| ((tiff_ifd[i].newsubfiletype & 0xffff) << 16) | |
| ((i << 8) & 0xff00) | 1; |
| ifdc++; |
| } |
| } |
| } |
| if (ifdc) |
| { |
| if (ifdc > 1 && (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_PREFER_LARGEST_IMAGE)) |
| { |
| ifd_size_t arr[LIBRAW_IFD_MAXCOUNT * 2]; |
| memset(arr, 0, sizeof(arr)); |
| for (int q = 0; q < ifdc && q < LIBRAW_IFD_MAXCOUNT * 2; q++) |
| { |
| int ifdidx = |
| (libraw_internal_data.unpacker_data.dng_frames[q] >> 8) & 0xff; |
| arr[q].ifdi = libraw_internal_data.unpacker_data.dng_frames[q]; |
| arr[q].databits = |
| INT64(tiff_ifd[ifdidx].t_width) * INT64(tiff_ifd[ifdidx].t_height) * |
| INT64(tiff_ifd[ifdidx].samples) * INT64(tiff_ifd[ifdidx].bps) + |
| INT64(0x100 - |
| (arr[q].ifdi & 0xff)); // add inverted frame # to ensure same |
| // sort order for similar sized frames. |
| if (tiff_ifd[ifdidx].phint == 4) |
| arr[q].databits /= 4; // Force lower bit count for Transp. mask images |
| } |
| qsort(arr, MIN(ifdc, LIBRAW_IFD_MAXCOUNT * 2), sizeof(arr[0]), |
| ifd_size_t_cmp); |
| for (int q = 0; q < ifdc && q < LIBRAW_IFD_MAXCOUNT * 2; q++) |
| libraw_internal_data.unpacker_data.dng_frames[q] = arr[q].ifdi; |
| } |
| |
| int idx = LIM((int)shot_select, 0, ifdc - 1); |
| i = (libraw_internal_data.unpacker_data.dng_frames[idx] >> 8) & |
| 0xff; // extract frame# back |
| |
| raw_width = tiff_ifd[i].t_width; |
| raw_height = tiff_ifd[i].t_height; |
| tiff_bps = tiff_ifd[i].bps; |
| tiff_compress = tiff_ifd[i].comp; |
| tiff_sampleformat = tiff_ifd[i].sample_format; |
| data_offset = tiff_ifd[i].offset; |
| data_size = tiff_ifd[i].bytes; |
| tiff_flip = tiff_ifd[i].t_flip; |
| tiff_samples = tiff_ifd[i].samples; |
| tile_width = tiff_ifd[i].t_tile_width; |
| tile_length = tiff_ifd[i].t_tile_length; |
| fuji_width = tiff_ifd[i].t_fuji_width; |
| if (tiff_samples != 2) /* special case: Fuji SuperCCD */ |
| { |
| if (tiff_ifd[i].phint == 34892) |
| filters = 0; |
| else if (i > 0 && tiff_ifd[i].phint == 32803 && |
| tiff_ifd[0].phint == 32803 && !tiff_ifd[i].t_filters && |
| tiff_ifd[0].t_filters) |
| filters = tiff_ifd[0].t_filters; |
| else |
| filters = tiff_ifd[i].t_filters; |
| width = tiff_ifd[i].t_vwidth; |
| height = tiff_ifd[i].t_vheight; |
| top_margin = tiff_ifd[i].t_tm; |
| left_margin = tiff_ifd[i].t_lm; |
| shutter = tiff_ifd[i].t_shutter; |
| if (tiff_ifd[i].dng_levels.dng_whitelevel[0]) |
| maximum = tiff_ifd[i].dng_levels.dng_whitelevel[0]; |
| else if (tiff_ifd[i].sample_format <= 2 && tiff_bps > 0 && |
| tiff_bps < 32) // SampleFormat: 0-default(1), 1 - Uint, 2 - Int |
| maximum = (1 << tiff_bps) - 1; |
| else if (tiff_ifd[i].sample_format == 3) |
| maximum = 1; // Defaults for FP |
| } |
| raw = i; |
| is_raw = ifdc; |
| } |
| else |
| is_raw = 0; |
| } |
| else |
| { |
| // Fix for broken Sony bps tag |
| if (!strncasecmp(make, "Sony", 4)) |
| { |
| for (i = 0; i < (int)tiff_nifds; i++) |
| { |
| if (tiff_ifd[i].bps > 33 && tiff_ifd[i].samples == 1) |
| { |
| int bps = 14; // default |
| if (tiff_ifd[i].dng_levels.dng_whitelevel[0] > 0) |
| { |
| for(int c = 0,j=1; c < 16; c++, j<<=1) |
| if (j > (int)tiff_ifd[i].dng_levels.dng_whitelevel[0]) |
| { |
| bps = c; break; |
| } |
| } |
| tiff_ifd[i].bps = bps; |
| } |
| } |
| } |
| |
| for (i = 0; i < (int)tiff_nifds; i++) |
| { |
| if (tiff_ifd[i].t_width < 1 || tiff_ifd[i].t_width > 65535 || |
| tiff_ifd[i].t_height < 1 || tiff_ifd[i].t_height > 65535) |
| continue; /* wrong image dimensions */ |
| if (max_samp < tiff_ifd[i].samples) |
| max_samp = tiff_ifd[i].samples; |
| if (max_samp > 3) |
| max_samp = 3; |
| |
| os = unsigned(raw_width) * unsigned(raw_height); |
| ns = unsigned(tiff_ifd[i].t_width) * unsigned(tiff_ifd[i].t_height); |
| if (tiff_bps) |
| { |
| os *= tiff_bps; |
| ns *= tiff_ifd[i].bps; |
| } |
| /* too complex if below, so separate if to skip RGB+Alpha TIFFs*/ |
| if (tiff_ifd[i].phint == 2 && tiff_ifd[i].extrasamples > 0 && tiff_ifd[i].samples > 3) |
| continue; // SKIP RGB+Alpha IFDs |
| |
| if (!strncasecmp(make, "Sony", 4) && tiff_ifd[i].bps == 8 && tiff_ifd[i].phint == 6 && tiff_ifd[i].comp == 7 && |
| tiff_ifd[i].samples == 3 && tiff_ifd[i].newsubfiletype == 1) |
| continue; // Sony RGB preview |
| |
| if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3 || |
| (tiff_ifd[i].comp == 6 && tiff_ifd[i].samples == 3 && !strncasecmp(make, "Sony", 4) && tiff_ifd[i].bps >=12) |
| ) && |
| unsigned(tiff_ifd[i].t_width | tiff_ifd[i].t_height) < 0x10000 && |
| (unsigned)tiff_ifd[i].bps < 33 && |
| (unsigned)tiff_ifd[i].samples < 13 && ns && |
| ((ns > os && (ties = 1)) || (ns == os && (int)shot_select == ties++))) |
| { |
| raw_width = tiff_ifd[i].t_width; |
| raw_height = tiff_ifd[i].t_height; |
| tiff_bps = tiff_ifd[i].bps; |
| tiff_compress = tiff_ifd[i].comp; |
| tiff_sampleformat = tiff_ifd[i].sample_format; |
| data_offset = tiff_ifd[i].offset; |
| data_size = tiff_ifd[i].bytes; |
| tiff_flip = tiff_ifd[i].t_flip; |
| tiff_samples = tiff_ifd[i].samples; |
| tile_width = tiff_ifd[i].t_tile_width; |
| tile_length = tiff_ifd[i].t_tile_length; |
| shutter = tiff_ifd[i].t_shutter; |
| raw = i; |
| } |
| } |
| if (is_raw == 1 && ties) |
| is_raw = ties; |
| } |
| if (is_NikonTransfer && raw >= 0) |
| { |
| if (tiff_ifd[raw].bps == 16) |
| { |
| if (tiff_compress == 1) |
| { |
| if ((INT64(raw_width) * INT64(raw_height) * 3LL) == (tiff_ifd[raw].bytes << 1)) |
| { |
| tiff_bps = tiff_ifd[raw].bps = 12; |
| } |
| else |
| { |
| tiff_bps = tiff_ifd[raw].bps = 14; |
| } |
| } |
| } |
| else if (tiff_ifd[raw].bps == 8) |
| { |
| if (tiff_compress == 1) |
| { |
| is_NikonTransfer = 2; // 8-bit debayered TIFF, like CoolScan NEFs |
| imgdata.rawparams.coolscan_nef_gamma = 2.2f; |
| } |
| } |
| } |
| |
| if (!tile_width) |
| tile_width = INT_MAX; |
| if (!tile_length) |
| tile_length = INT_MAX; |
| for (i = tiff_nifds; i--;) |
| if (tiff_ifd[i].t_flip) |
| tiff_flip = tiff_ifd[i].t_flip; |
| |
| #if 0 |
| if (raw < 0 && is_raw) |
| is_raw = 0; |
| #endif |
| |
| if (raw >= 0 && !load_raw) |
| switch (tiff_compress) |
| { |
| case 32767: |
| if (!dng_version && |
| tiff_ifd[raw].bytes == INT64(raw_width) * INT64(raw_height)) |
| { |
| tiff_bps = 14; |
| load_raw = &LibRaw::sony_arw2_load_raw; |
| break; |
| } |
| if (!dng_version && !strncasecmp(make, "Sony", 4) && |
| tiff_ifd[raw].bytes == INT64(raw_width) * INT64(raw_height) * 2LL) |
| { |
| tiff_bps = 14; |
| load_raw = &LibRaw::unpacked_load_raw; |
| break; |
| } |
| if (tiff_ifd[raw].bytes * 8LL != |
| INT64(raw_width) * INT64(raw_height) * INT64(tiff_bps)) |
| { |
| raw_height += 8; |
| load_raw = &LibRaw::sony_arw_load_raw; |
| break; |
| } |
| load_flags = 79; |
| case 32769: |
| load_flags++; |
| case 32770: |
| case 32773: |
| goto slr; |
| case 0: |
| case 1: |
| if (dng_version && tiff_sampleformat == 3 && |
| (tiff_bps > 8 && (tiff_bps % 8 == 0) && (tiff_bps <= 32))) // only 16,24, and 32 are allowed |
| { |
| load_raw = &LibRaw::uncompressed_fp_dng_load_raw; |
| break; |
| } |
| // Sony 14-bit uncompressed |
| if (!dng_version && !strncasecmp(make, "Sony", 4) && |
| tiff_ifd[raw].bytes == INT64(raw_width) * INT64(raw_height) * 2LL) |
| { |
| tiff_bps = 14; |
| load_raw = &LibRaw::unpacked_load_raw; |
| break; |
| } |
| if (!dng_version && !strncasecmp(make, "Sony", 4) && tiff_ifd[raw].samples == 4 && |
| tiff_ifd[raw].bytes == INT64(raw_width) * INT64(raw_height) * 8LL) // Sony ARQ |
| { |
| // maybe to detect ARQ with the following: |
| // if (tiff_ifd[raw].phint == 32892) |
| tiff_bps = 14; |
| tiff_samples = 4; |
| load_raw = &LibRaw::sony_arq_load_raw; |
| filters = 0; |
| strcpy(cdesc, "RGBG"); |
| break; |
| } |
| if (!strncasecmp(make, "Nikon", 5) && |
| (!strncmp(software, "Nikon Scan", 10) || (is_NikonTransfer == 2) || |
| strcasestr(model, "COOLSCAN"))) |
| { |
| load_raw = &LibRaw::nikon_coolscan_load_raw; |
| raw_color = 1; |
| colors = (tiff_samples == 3) ? 3 : 1; |
| filters = 0; |
| break; |
| } |
| if ((!strncmp(make, "OLYMPUS", 7) || !strncmp(make, "OM Digi", 7) || |
| (!strncasecmp(make, "CLAUSS", 6) && !strncasecmp(model, "piX 5oo", 7))) && // 0x5330303539 works here |
| (tiff_ifd[raw].bytes * 2LL == INT64(raw_width) * INT64(raw_height) * 3LL)) |
| load_flags = 24; |
| if (!dng_version && tiff_ifd[raw].bytes * 5LL == INT64(raw_width) * INT64(raw_height) * 8LL) |
| { |
| load_flags = 81; |
| tiff_bps = 12; |
| } |
| slr: |
| switch (tiff_bps) |
| { |
| case 8: |
| load_raw = &LibRaw::eight_bit_load_raw; |
| break; |
| case 12: |
| if (tiff_ifd[raw].phint == 2) |
| load_flags = 6; |
| if (!strncasecmp(make, "NIKON", 5) && |
| !strncasecmp(model, "COOLPIX A1000", 13) && |
| data_size == raw_width * raw_height * 2u) |
| load_raw = &LibRaw::unpacked_load_raw; |
| else |
| load_raw = &LibRaw::packed_load_raw; |
| break; |
| case 14: |
| load_flags = 0; |
| case 16: |
| load_raw = &LibRaw::unpacked_load_raw; |
| if ((!strncmp(make, "OLYMPUS", 7) || !strncmp(make, "OM Digi", 7) || |
| (!strncasecmp(make, "CLAUSS", 6) && !strncasecmp(model, "piX 5oo", 7))) && // 0x5330303539 works here |
| (tiff_ifd[raw].bytes * 7LL > INT64(raw_width) * INT64(raw_height))) |
| { |
| load_raw = &LibRaw::olympus_load_raw; |
| } |
| } |
| break; |
| case 6: |
| case 7: |
| case 99: |
| if (!dng_version && tiff_compress == 6 && !strcasecmp(make, "SONY")) |
| { |
| if (tiff_ifd[raw].phint == 6 && tiff_ifd[raw].bps >= 12 && tiff_ifd[raw].samples == 3) |
| { |
| load_raw = &LibRaw::sony_ycbcr_load_raw; |
| filters = 0; |
| colors = 3; |
| } |
| else |
| load_raw = &LibRaw::sony_ljpeg_load_raw; |
| } |
| // Allow A1/Compression=7 |
| else if(!dng_version && tiff_compress == 7 && !strcasecmp(make, "SONY") && |
| (!strcasecmp(model,"ILCE-1") || !strncasecmp(model, "ILCE-7",6) |
| || !strncasecmp(model, "ILCE-9", 6) // Most likely ILCE-9 will use tiff_compr=7 this w/ updated FW |
| ) && |
| tiff_bps == 14 && tiff_samples == 1) |
| load_raw = &LibRaw::sony_ljpeg_load_raw; |
| else |
| load_raw = &LibRaw::lossless_jpeg_load_raw; |
| break; |
| case 262: |
| load_raw = &LibRaw::kodak_262_load_raw; |
| break; |
| case 34713: |
| if ((INT64(raw_width) + 9LL) / 10LL * 16LL * INT64(raw_height) == tiff_ifd[raw].bytes) |
| { |
| load_raw = &LibRaw::packed_load_raw; |
| load_flags = 1; |
| } |
| else if (INT64(raw_width) * INT64(raw_height) * 3LL == tiff_ifd[raw].bytes * 2LL) |
| { |
| load_raw = &LibRaw::packed_load_raw; |
| if (model[0] == 'N') |
| load_flags = 80; |
| } |
| else if (INT64(raw_width) * INT64(raw_height) * 3LL == tiff_ifd[raw].bytes) |
| { |
| load_raw = &LibRaw::nikon_yuv_load_raw; |
| gamma_curve(1 / 2.4, 12.92, 1, 4095); |
| memset(cblack, 0, sizeof cblack); |
| filters = 0; |
| } |
| else if (INT64(raw_width) * INT64(raw_height) * 2LL == tiff_ifd[raw].bytes) |
| { |
| load_raw = &LibRaw::unpacked_load_raw; |
| load_flags = 4; |
| order = 0x4d4d; |
| } |
| #if 0 /* Never used because of same condition above, but need to recheck */ |
| else if (INT64(raw_width) * INT64(raw_height) * 3LL == |
| INT64(tiff_ifd[raw].bytes) * 2LL) |
| { |
| load_raw = &LibRaw::packed_load_raw; |
| load_flags = 80; |
| } |
| #endif |
| else if (tiff_ifd[raw].rows_per_strip && |
| tiff_ifd[raw].strip_offsets_count && |
| tiff_ifd[raw].strip_offsets_count == |
| tiff_ifd[raw].strip_byte_counts_count) |
| { |
| int fit = 1; |
| for (int q = 0; q < tiff_ifd[raw].strip_byte_counts_count - 1; |
| q++) // all but last |
| if (INT64(tiff_ifd[raw].strip_byte_counts[q]) * 2LL != |
| INT64(tiff_ifd[raw].rows_per_strip) * INT64(raw_width) * 3LL) |
| { |
| fit = 0; |
| break; |
| } |
| if (fit) |
| load_raw = &LibRaw::nikon_load_striped_packed_raw; |
| else |
| load_raw = &LibRaw::nikon_load_raw; // fallback |
| } |
| else if ((((INT64(raw_width) * 3LL / 2LL) + 15LL) / 16LL) * 16LL * INT64(raw_height) == tiff_ifd[raw].bytes) |
| { |
| load_raw = &LibRaw::nikon_load_padded_packed_raw; |
| } |
| else if ((!strncmp(model, "NIKON Z 9", 9) || !strncmp(model, "NIKON Z 8", 9) || !strcmp(model, "NIKON Z f") |
| || !strcmp(model, "NIKON Z6_3")) && |
| tiff_ifd[raw].offset) |
| { |
| INT64 pos = ftell(ifp); |
| unsigned char cmp[] = {0xff, 0x10, 0xff, 0x50 }; // JpegXS SOC + Cap |
| unsigned char buf[4]; |
| fseek(ifp, INT64(tiff_ifd[raw].offset), SEEK_SET); |
| fread(buf, 1, 4, ifp); |
| fseek(ifp, pos, SEEK_SET); |
| if(!memcmp(buf,cmp,4)) |
| load_raw = &LibRaw::nikon_he_load_raw; |
| else |
| load_raw = &LibRaw::nikon_load_raw; |
| } |
| else |
| load_raw = &LibRaw::nikon_load_raw; |
| break; |
| case 65535: |
| load_raw = &LibRaw::pentax_load_raw; |
| break; |
| case 65000: |
| switch (tiff_ifd[raw].phint) |
| { |
| case 2: |
| load_raw = &LibRaw::kodak_rgb_load_raw; |
| filters = 0; |
| break; |
| case 6: |
| load_raw = &LibRaw::kodak_ycbcr_load_raw; |
| filters = 0; |
| break; |
| case 32803: |
| load_raw = &LibRaw::kodak_65000_load_raw; |
| } |
| case 32867: |
| case 34892: |
| break; |
| case 8: |
| break; |
| case 52546: |
| if (dng_version) /* DNG 1.7 JPEG XL: if not compiled w/ DNG SDK decoder will return NOT SUPPORTED*/ |
| break; |
| // else: fallthrough |
| case 9: |
| if (dng_version) |
| break; /* Compression=9 supported for dng if we compiled with GPR SDK; if NO SDK: decoder will return NOT Supported */ |
| // else: fallthrough |
| default: |
| is_raw = 0; |
| } |
| if (!dng_version) |
| { |
| if (((tiff_samples == 3 && tiff_ifd[raw].bytes && |
| !(tiff_bps == 16 && |
| !strncmp(make, "Leaf", 4)) && // Allow Leaf/16bit/3color files |
| !(tiff_ifd[raw].comp == 6 && tiff_ifd[raw].phint == 6 && tiff_bps >= 12 && !strncasecmp(make,"Sony",4)) && // Sony YCbCr |
| tiff_bps != 14 && |
| (tiff_compress & -16) != 32768) || |
| (tiff_bps == 8 && strncmp(make, "Phase", 5) && |
| strncmp(make, "Leaf", 4) && !strcasestr(make, "Kodak") && |
| !strstr(model2, "DEBUG RAW"))) && |
| !strcasestr(model, "COOLSCAN") && strncmp(software, "Nikon Scan", 10) && |
| is_NikonTransfer != 2) |
| is_raw = 0; |
| |
| if (is_raw && raw >= 0 && tiff_ifd[raw].phint == 2 && tiff_ifd[raw].extrasamples > 0 && tiff_ifd[raw].samples > 3) |
| is_raw = 0; // SKIP RGB+Alpha IFDs |
| } |
| |
| INT64 fsizecheck = 0ULL; |
| |
| if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CHECK_THUMBNAILS_ALL_VENDORS) |
| fsizecheck = ifp->size(); |
| else if ((imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CHECK_THUMBNAILS_KNOWN_VENDORS) && |
| (!strncasecmp(make, "Ricoh", 5) || (dng_version && !strncasecmp(make, "Samsung", 7)))) |
| fsizecheck = ifp->size(); |
| |
| for (i = 0; i < (int)tiff_nifds; i++) |
| if (i != raw && |
| (tiff_ifd[i].samples == max_samp || |
| (tiff_ifd[i].comp == 7 && |
| tiff_ifd[i].samples == 1)) /* Allow 1-bps JPEGs */ |
| && tiff_ifd[i].bps > 0 && tiff_ifd[i].bps < 33 && |
| tiff_ifd[i].phint != 32803 && tiff_ifd[i].phint != 34892 && |
| (tiff_ifd[i].comp != 52546 || (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_ALLOW_JPEGXL_PREVIEWS)) && |
| unsigned(tiff_ifd[i].t_width | tiff_ifd[i].t_height) < 0x10000 && |
| tiff_ifd[i].comp != 34892) |
| { |
| if (fsizecheck > 0LL) |
| { |
| bool ok = true; |
| if (tiff_ifd[i].strip_byte_counts_count && tiff_ifd[i].strip_offsets_count) |
| for (int s = 0; s < MIN(tiff_ifd[i].strip_byte_counts_count, tiff_ifd[i].strip_offsets_count); s++) |
| { |
| if (tiff_ifd[i].strip_offsets[s] + tiff_ifd[i].strip_byte_counts[s] > fsizecheck) |
| { |
| ok = false; |
| break; |
| } |
| } |
| else if (tiff_ifd[i].bytes > 0) |
| if (tiff_ifd[i].offset + tiff_ifd[i].bytes > fsizecheck) |
| ok = false; |
| |
| if(!ok) |
| continue; |
| } |
| if ( (INT64(tiff_ifd[i].t_width) * INT64(tiff_ifd[i].t_height) / INT64(SQR(tiff_ifd[i].bps) + 1)) > |
| (INT64(thumb_width) * INT64(thumb_height) / INT64(SQR(thumb_misc) + 1)) ) |
| { |
| |
| thumb_width = tiff_ifd[i].t_width; |
| thumb_height = tiff_ifd[i].t_height; |
| thumb_offset = tiff_ifd[i].offset; |
| thumb_length = unsigned(tiff_ifd[i].bytes); // do we expect >4GB thumbnail? |
| thumb_misc = tiff_ifd[i].bps; |
| thm = i; |
| } |
| if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT && tiff_ifd[i].bytes > 0) |
| { |
| bool already = false; |
| for(int idx = 0; idx < imgdata.thumbs_list.thumbcount ; idx++) |
| if (imgdata.thumbs_list.thumblist[idx].toffset == tiff_ifd[i].offset) |
| { |
| already = true; |
| break; |
| } |
| if (!already) |
| { |
| int idx = imgdata.thumbs_list.thumbcount; |
| imgdata.thumbs_list.thumblist[idx].tformat = tiff2thumbformat(tiff_ifd[i].comp, tiff_ifd[i].phint, |
| tiff_ifd[i].bps, make, dng_version); |
| imgdata.thumbs_list.thumblist[idx].twidth = tiff_ifd[i].t_width; |
| imgdata.thumbs_list.thumblist[idx].theight = tiff_ifd[i].t_height; |
| imgdata.thumbs_list.thumblist[idx].tflip = tiff_ifd[i].t_flip; |
| imgdata.thumbs_list.thumblist[idx].tlength = unsigned(tiff_ifd[i].bytes); |
| imgdata.thumbs_list.thumblist[idx].tmisc = tiff_ifd[i].bps | (tiff_ifd[i].samples << 5); |
| imgdata.thumbs_list.thumblist[idx].toffset = tiff_ifd[i].offset; |
| imgdata.thumbs_list.thumbcount++; |
| } |
| } |
| } |
| if (thm >= 0) |
| { |
| thumb_misc |= tiff_ifd[thm].samples << 5; |
| thumb_format = tiff2thumbformat(tiff_ifd[thm].comp, tiff_ifd[thm].phint, tiff_ifd[thm].bps, make, dng_version); |
| } |
| } |
| |
| static LibRaw_internal_thumbnail_formats tiff2thumbformat(int _comp, int _phint, int _bps, const char *_make, bool isDNG) |
| { |
| switch (_comp) |
| { |
| case 0: |
| return LIBRAW_INTERNAL_THUMBNAIL_LAYER; |
| case 1: |
| if (_bps <= 8) |
| return LIBRAW_INTERNAL_THUMBNAIL_PPM; |
| else if (!strncmp(_make, "Imacon", 6)) |
| return LIBRAW_INTERNAL_THUMBNAIL_PPM16; |
| else if (isDNG && _phint == 6 && _bps == 12) |
| return LIBRAW_INTERNAL_THUMBNAIL_DNG_YCBCR; |
| else |
| return LIBRAW_INTERNAL_THUMBNAIL_KODAK_THUMB; |
| case 52546: |
| return LIBRAW_INTERNAL_THUMBNAIL_JPEGXL; |
| case 65000: |
| return _phint == 6 ? LIBRAW_INTERNAL_THUMBNAIL_KODAK_YCBCR : LIBRAW_INTERNAL_THUMBNAIL_KODAK_RGB; |
| } |
| return LIBRAW_INTERNAL_THUMBNAIL_JPEG; // default |
| } |