diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 30750326a..c41842f56 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -1738,11 +1738,17 @@ void CLASS parse_hasselblad_gain() information, but it makes no difference if set to zero. See hasselblad_correct() how the flatfield is applied. - Applied in FFF conversion is flatfield correction, levels, and the bad columns(?) + Applied in FFF conversion is levels, flatfield correction, and the bad columns(?) data. A/D curves are surprisingly not applied, maybe pre-applied in hardware and - only available as information? + only available as information? Levels are applied before flatfield, further + ordering has not been investigated. Not all combinations/models have been tested so there may be gaps. + + Most clipped pixels in a 3FR is at 65535, but there's also some at 65534. Both + are set to 65535 when calibrated, while 65533 is treated as a normal value. In + the calibration process smaller values can be scaled to 65534 (which should + not be seen as clipped). */ ushort raw_h, count, ch_count, u16; @@ -1789,6 +1795,37 @@ void CLASS hasselblad_correct() */ + if (hbd.levels) { + int i; + fseek(ifp, hbd.levels, SEEK_SET); + /* skip the first set (not used as we don't apply on first/last row), we look at it though to see if + the levels format is one that we support (there are other formats on some models which is not + supported here) */ + short test[10]; + for (i = 0; i < 10; i++) test[i] = (short)get2(); + if (test[5] == 0 && test[6] == 0 && test[7] == 0 && test[8] == 0 && test[9] == 0) { + int corr[4]; + ushort *row_above = (ushort *)malloc(sizeof(ushort) * raw_width); // we need to cache row above as we write new values as we go + for (col = 0; col < raw_width; col++) row_above[col] = RAW(0,col); + for (row = 1; row < raw_height-1; row++) { + for (i = 0; i < 4; i++) corr[i] = (short)get2(); + fseek(ifp, 6 * 2, SEEK_CUR); + for (col = 0; col < raw_width; col++) { + unsigned v = RAW(row,col); + if (v >= 65534) { + v = 65535; + } else { + if (corr[((col & 1)<<1)+0] && row_above[col] > black) v += 2 * ((corr[((col & 1)<<1)+0] * (row_above[col]-(int)black)) / 32767) - 2; + if (corr[((col & 1)<<1)+1] && RAW(row+1,col) > black) v += 2 * ((corr[((col & 1)<<1)+1] * (RAW(row+1,col)-(int)black)) / 32767) - 2; + } + row_above[col] = RAW(row,col); + RAW(row,col) = CLIP(v); + } + } + free(row_above); + } + } + if (hbd.flatfield) { int bw, bh, ffrows, ffcols, i, c; ushort ref[4], ref_max; @@ -1936,7 +1973,7 @@ void CLASS hasselblad_correct() if (ffc == ffs + 4 * ffcols) next_ffc += raw_width; // last col in map, avoid stepping further } unsigned v = RAW(row,col); - if (v > black) { + if (v > black && v < 65535) { c = FC(row,col); unsigned x = col < cur_ffc ? 0 : col - cur_ffc; unsigned y = row < cur_ffr ? 0 : row - cur_ffr; @@ -1967,33 +2004,6 @@ void CLASS hasselblad_correct() free(ffmap); free(corners_weight); } - - if (hbd.levels) { - int i; - fseek(ifp, hbd.levels, SEEK_SET); - /* skip the first set (not used as we don't apply on first/last row), we look at it though to see if - the levels format is one that we support (there are other formats on some models which is not - supported here) */ - short test[10]; - for (i = 0; i < 10; i++) test[i] = (short)get2(); - if (test[5] == 0 && test[6] == 0 && test[7] == 0 && test[8] == 0 && test[9] == 0) { - int corr[4]; - ushort *row_above = (ushort *)malloc(sizeof(ushort) * raw_width); // we need to cache row above as we write new values as we go - for (col = 0; col < raw_width; col++) row_above[col] = RAW(0,col); - for (row = 1; row < raw_height-1; row++) { - for (i = 0; i < 4; i++) corr[i] = (short)get2(); - fseek(ifp, 6 * 2, SEEK_CUR); - for (col = 0; col < raw_width; col++) { - unsigned v = RAW(row,col); - if (corr[((col & 1)<<1)+0] && row_above[col] > black) v += 2 * ((corr[((col & 1)<<1)+0] * (row_above[col]-(int)black)) / 32767) - 2; - if (corr[((col & 1)<<1)+1] && RAW(row+1,col) > black) v += 2 * ((corr[((col & 1)<<1)+1] * (RAW(row+1,col)-(int)black)) / 32767) - 2; - row_above[col] = RAW(row,col); - RAW(row,col) = CLIP(v); - } - } - free(row_above); - } - } } void CLASS hasselblad_load_raw() diff --git a/rtengine/dcraw.patch b/rtengine/dcraw.patch index 67e679847..bfc7e6236 100755 --- a/rtengine/dcraw.patch +++ b/rtengine/dcraw.patch @@ -1,5 +1,5 @@ --- dcraw.c 2014-07-24 16:15:36.700261700 +0200 -+++ dcraw.cc 2014-12-29 20:24:33.459795490 +0100 ++++ dcraw.cc 2015-01-04 18:44:56.900751624 +0100 @@ -1,3 +1,15 @@ +/*RT*/#include +/*RT*/#include @@ -245,7 +245,7 @@ unsigned c; if (nbits == -1) -@@ -1712,6 +1676,326 @@ +@@ -1712,6 +1676,336 @@ maximum = 0xfffc - ph1.black; } @@ -311,11 +311,17 @@ + information, but it makes no difference if set to zero. See + hasselblad_correct() how the flatfield is applied. + -+ Applied in FFF conversion is flatfield correction, levels, and the bad columns(?) ++ Applied in FFF conversion is levels, flatfield correction, and the bad columns(?) + data. A/D curves are surprisingly not applied, maybe pre-applied in hardware and -+ only available as information? ++ only available as information? Levels are applied before flatfield, further ++ ordering has not been investigated. + + Not all combinations/models have been tested so there may be gaps. ++ ++ Most clipped pixels in a 3FR is at 65535, but there's also some at 65534. Both ++ are set to 65535 when calibrated, while 65533 is treated as a normal value. In ++ the calibration process smaller values can be scaled to 65534 (which should ++ not be seen as clipped). + */ + + ushort raw_h, count, ch_count, u16; @@ -362,6 +368,37 @@ + + */ + ++ if (hbd.levels) { ++ int i; ++ fseek(ifp, hbd.levels, SEEK_SET); ++ /* skip the first set (not used as we don't apply on first/last row), we look at it though to see if ++ the levels format is one that we support (there are other formats on some models which is not ++ supported here) */ ++ short test[10]; ++ for (i = 0; i < 10; i++) test[i] = (short)get2(); ++ if (test[5] == 0 && test[6] == 0 && test[7] == 0 && test[8] == 0 && test[9] == 0) { ++ int corr[4]; ++ ushort *row_above = (ushort *)malloc(sizeof(ushort) * raw_width); // we need to cache row above as we write new values as we go ++ for (col = 0; col < raw_width; col++) row_above[col] = RAW(0,col); ++ for (row = 1; row < raw_height-1; row++) { ++ for (i = 0; i < 4; i++) corr[i] = (short)get2(); ++ fseek(ifp, 6 * 2, SEEK_CUR); ++ for (col = 0; col < raw_width; col++) { ++ unsigned v = RAW(row,col); ++ if (v >= 65534) { ++ v = 65535; ++ } else { ++ if (corr[((col & 1)<<1)+0] && row_above[col] > black) v += 2 * ((corr[((col & 1)<<1)+0] * (row_above[col]-(int)black)) / 32767) - 2; ++ if (corr[((col & 1)<<1)+1] && RAW(row+1,col) > black) v += 2 * ((corr[((col & 1)<<1)+1] * (RAW(row+1,col)-(int)black)) / 32767) - 2; ++ } ++ row_above[col] = RAW(row,col); ++ RAW(row,col) = CLIP(v); ++ } ++ } ++ free(row_above); ++ } ++ } ++ + if (hbd.flatfield) { + int bw, bh, ffrows, ffcols, i, c; + ushort ref[4], ref_max; @@ -509,7 +546,7 @@ + if (ffc == ffs + 4 * ffcols) next_ffc += raw_width; // last col in map, avoid stepping further + } + unsigned v = RAW(row,col); -+ if (v > black) { ++ if (v > black && v < 65535) { + c = FC(row,col); + unsigned x = col < cur_ffc ? 0 : col - cur_ffc; + unsigned y = row < cur_ffr ? 0 : row - cur_ffr; @@ -540,39 +577,12 @@ + free(ffmap); + free(corners_weight); + } -+ -+ if (hbd.levels) { -+ int i; -+ fseek(ifp, hbd.levels, SEEK_SET); -+ /* skip the first set (not used as we don't apply on first/last row), we look at it though to see if -+ the levels format is one that we support (there are other formats on some models which is not -+ supported here) */ -+ short test[10]; -+ for (i = 0; i < 10; i++) test[i] = (short)get2(); -+ if (test[5] == 0 && test[6] == 0 && test[7] == 0 && test[8] == 0 && test[9] == 0) { -+ int corr[4]; -+ ushort *row_above = (ushort *)malloc(sizeof(ushort) * raw_width); // we need to cache row above as we write new values as we go -+ for (col = 0; col < raw_width; col++) row_above[col] = RAW(0,col); -+ for (row = 1; row < raw_height-1; row++) { -+ for (i = 0; i < 4; i++) corr[i] = (short)get2(); -+ fseek(ifp, 6 * 2, SEEK_CUR); -+ for (col = 0; col < raw_width; col++) { -+ unsigned v = RAW(row,col); -+ if (corr[((col & 1)<<1)+0] && row_above[col] > black) v += 2 * ((corr[((col & 1)<<1)+0] * (row_above[col]-(int)black)) / 32767) - 2; -+ if (corr[((col & 1)<<1)+1] && RAW(row+1,col) > black) v += 2 * ((corr[((col & 1)<<1)+1] * (RAW(row+1,col)-(int)black)) / 32767) - 2; -+ row_above[col] = RAW(row,col); -+ RAW(row,col) = CLIP(v); -+ } -+ } -+ free(row_above); -+ } -+ } +} + void CLASS hasselblad_load_raw() { struct jhead jh; -@@ -1903,10 +2187,10 @@ +@@ -1903,10 +2197,10 @@ maximum = curve[0x3ff]; } @@ -586,7 +596,7 @@ int byte; if (!nbits) return vbits=0; -@@ -2195,11 +2479,11 @@ +@@ -2195,11 +2489,11 @@ METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo) { @@ -600,7 +610,7 @@ cinfo->src->next_input_byte = jpeg_buffer; cinfo->src->bytes_in_buffer = nbytes; return TRUE; -@@ -2524,10 +2808,9 @@ +@@ -2524,10 +2818,9 @@ maximum = (1 << (thumb_misc & 31)) - 1; } @@ -613,7 +623,7 @@ if (start) { for (p=0; p < 4; p++) pad[p] = key = key * 48828125 + 1; -@@ -2612,11 +2895,13 @@ +@@ -2612,11 +2905,13 @@ bit += 7; } for (i=0; i < 16; i++, col+=2) @@ -628,7 +638,7 @@ } void CLASS samsung_load_raw() -@@ -2863,7 +3148,7 @@ +@@ -2863,7 +3158,7 @@ void CLASS foveon_decoder (unsigned size, unsigned code) { @@ -637,7 +647,7 @@ struct decode *cur; int i, len; -@@ -3571,6 +3856,8 @@ +@@ -3571,6 +3866,8 @@ if (load_raw == &CLASS phase_one_load_raw || load_raw == &CLASS phase_one_load_raw_c) phase_one_correct(); @@ -646,7 +656,7 @@ if (fuji_width) { for (row=0; row < raw_height-top_margin*2; row++) { for (col=0; col < fuji_width << !fuji_layout; col++) { -@@ -3586,10 +3873,13 @@ +@@ -3586,10 +3883,13 @@ } } } else { @@ -662,7 +672,7 @@ if (mask[0][3] > 0) goto mask_set; if (load_raw == &CLASS canon_load_raw || load_raw == &CLASS lossless_jpeg_load_raw) { -@@ -4191,239 +4481,8 @@ +@@ -4191,239 +4491,8 @@ } } @@ -903,7 +913,7 @@ void CLASS cielab (ushort rgb[3], short lab[3]) { -@@ -4684,112 +4743,7 @@ +@@ -4684,112 +4753,7 @@ } #undef fcol @@ -1016,7 +1026,7 @@ #undef TS void CLASS median_filter() -@@ -4959,7 +4913,7 @@ +@@ -4959,7 +4923,7 @@ } } @@ -1025,7 +1035,7 @@ void CLASS parse_makernote (int base, int uptag) { -@@ -5116,12 +5070,16 @@ +@@ -5116,12 +5080,16 @@ cam_mul[2] = get4() << 2; } } @@ -1043,7 +1053,7 @@ if (tag == 0x1d) while ((c = fgetc(ifp)) && c != EOF) serial = serial*10 + (isdigit(c) ? c - '0' : c % 10); -@@ -5367,7 +5325,7 @@ +@@ -5367,7 +5335,7 @@ { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22", "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65", "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7", @@ -1052,7 +1062,7 @@ "","","","","Aptus-II 10R","Aptus-II 8","","Aptus-II 12","","AFi-II 12" }; float romm_cam[3][3]; -@@ -5456,6 +5414,8 @@ +@@ -5456,6 +5424,8 @@ wbi = -2; } if (tag == 2118) wbtemp = getint(type); @@ -1061,7 +1071,7 @@ if (tag == 2130 + wbi) FORC3 mul[c] = getreal(type); if (tag == 2140 + wbi && wbi >= 0) -@@ -5475,8 +5435,8 @@ +@@ -5475,8 +5445,8 @@ } } @@ -1072,7 +1082,7 @@ int CLASS parse_tiff_ifd (int base) { -@@ -5489,7 +5449,7 @@ +@@ -5489,7 +5459,7 @@ unsigned sony_curve[] = { 0,0,0,0,0,4095 }; unsigned *buf, sony_offset=0, sony_length=0, sony_key=0; struct jhead jh; @@ -1081,7 +1091,7 @@ if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0]) return 1; -@@ -5564,7 +5524,8 @@ +@@ -5564,7 +5534,8 @@ fgets (make, 64, ifp); break; case 272: /* Model */ @@ -1091,7 +1101,7 @@ break; case 280: /* Panasonic RW2 offset */ if (type != 4) break; -@@ -5620,6 +5581,9 @@ +@@ -5620,6 +5591,9 @@ case 315: /* Artist */ fread (artist, 64, 1, ifp); break; @@ -1101,7 +1111,7 @@ case 322: /* TileWidth */ tiff_ifd[ifd].tile_width = getint(type); break; -@@ -5635,6 +5599,9 @@ +@@ -5635,6 +5609,9 @@ is_raw = 5; } break; @@ -1111,7 +1121,7 @@ case 330: /* SubIFDs */ if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].width == 3872) { load_raw = &CLASS sony_arw_load_raw; -@@ -5648,6 +5615,9 @@ +@@ -5648,6 +5625,9 @@ fseek (ifp, i+4, SEEK_SET); } break; @@ -1121,7 +1131,7 @@ case 400: strcpy (make, "Sarnoff"); maximum = 0xfff; -@@ -5828,6 +5798,9 @@ +@@ -5828,6 +5808,9 @@ if (!make[0]) strcpy (make, "DNG"); is_raw = 1; break; @@ -1131,7 +1141,7 @@ case 50710: /* CFAPlaneColor */ if (filters == 9) break; if (len > 4) len = 4; -@@ -5859,10 +5832,21 @@ +@@ -5859,10 +5842,21 @@ case 61450: cblack[4] = cblack[5] = MIN(sqrt(len),64); case 50714: /* BlackLevel */ @@ -1157,7 +1167,7 @@ case 50715: /* BlackLevelDeltaH */ case 50716: /* BlackLevelDeltaV */ for (num=i=0; i < len; i++) -@@ -5940,12 +5924,15 @@ +@@ -5940,12 +5934,15 @@ fread (buf, sony_length, 1, ifp); sony_decrypt (buf, sony_length/4, 1, sony_key); sfp = ifp; @@ -1179,7 +1189,7 @@ ifp = sfp; free (buf); } -@@ -5969,6 +5956,7 @@ +@@ -5969,6 +5966,7 @@ int CLASS parse_tiff (int base) { int doff; @@ -1187,7 +1197,7 @@ fseek (ifp, base, SEEK_SET); order = get2(); -@@ -6046,7 +6034,7 @@ +@@ -6046,7 +6044,7 @@ case 8: load_raw = &CLASS eight_bit_load_raw; break; case 12: if (tiff_ifd[raw].phint == 2) load_flags = 6; @@ -1196,7 +1206,7 @@ case 14: load_flags = 0; case 16: load_raw = &CLASS unpacked_load_raw; if (!strncmp(make,"OLYMPUS",7) && -@@ -6079,6 +6067,7 @@ +@@ -6079,6 +6077,7 @@ case 32803: load_raw = &CLASS kodak_65000_load_raw; } case 32867: case 34892: break; @@ -1204,7 +1214,7 @@ default: is_raw = 0; } if (!dng_version) -@@ -6164,7 +6153,7 @@ +@@ -6164,7 +6163,7 @@ { const char *file, *ext; char *jname, *jfile, *jext; @@ -1213,7 +1223,7 @@ ext = strrchr (ifname, '.'); file = strrchr (ifname, '/'); -@@ -6186,13 +6175,14 @@ +@@ -6186,13 +6185,14 @@ } else while (isdigit(*--jext)) { if (*jext != '9') { @@ -1230,7 +1240,7 @@ if (verbose) fprintf (stderr,_("Reading metadata from %s ...\n"), jname); parse_tiff (12); -@@ -6537,7 +6527,11 @@ +@@ -6537,7 +6537,11 @@ order = get2(); hlen = get4(); if (get4() == 0x48454150) /* "HEAP" */ @@ -1242,7 +1252,7 @@ if (parse_tiff (save+6)) apply_tiff(); fseek (ifp, save+len, SEEK_SET); } -@@ -6789,7 +6783,8 @@ +@@ -6789,7 +6793,8 @@ { static const struct { const char *prefix; @@ -1252,7 +1262,7 @@ } table[] = { { "AgfaPhoto DC-833m", 0, 0, /* DJC */ { 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } }, -@@ -7690,6 +7685,27 @@ +@@ -7690,6 +7695,27 @@ } break; } @@ -1280,7 +1290,7 @@ } void CLASS simple_coeff (int index) -@@ -7967,7 +7983,7 @@ +@@ -7967,7 +7993,7 @@ tiff_flip = flip = filters = UINT_MAX; /* unknown */ raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0; maximum = height = width = top_margin = left_margin = 0; @@ -1289,7 +1299,7 @@ iso_speed = shutter = aperture = focal_len = unique_id = 0; tiff_nifds = 0; memset (tiff_ifd, 0, sizeof tiff_ifd); -@@ -7999,13 +8015,20 @@ +@@ -7999,13 +8025,20 @@ fread (head, 1, 32, ifp); fseek (ifp, 0, SEEK_END); flen = fsize = ftell(ifp); @@ -1312,7 +1322,7 @@ parse_ciff (hlen, flen-hlen, 0); load_raw = &CLASS canon_load_raw; } else if (parse_tiff(0)) apply_tiff(); -@@ -8051,6 +8074,7 @@ +@@ -8051,6 +8084,7 @@ fseek (ifp, 100+28*(shot_select > 0), SEEK_SET); parse_tiff (data_offset = get4()); parse_tiff (thumb_offset+12); @@ -1320,7 +1330,7 @@ apply_tiff(); } else if (!memcmp (head,"RIFF",4)) { fseek (ifp, 0, SEEK_SET); -@@ -8160,15 +8184,18 @@ +@@ -8160,15 +8194,18 @@ if (make[0] == 0) parse_smal (0, flen); if (make[0] == 0) { parse_jpeg(0); @@ -1348,7 +1358,7 @@ } for (i=0; i < sizeof corp / sizeof *corp; i++) -@@ -8201,7 +8228,7 @@ +@@ -8201,7 +8238,7 @@ if (height == 3136 && width == 4864) /* Pentax K20D and Samsung GX20 */ { height = 3124; width = 4688; filters = 0x16161616; } if (width == 4352 && (!strcmp(model,"K-r") || !strcmp(model,"K-x"))) @@ -1357,7 +1367,7 @@ if (width >= 4960 && !strncmp(model,"K-5",3)) { left_margin = 10; width = 4950; filters = 0x16161616; } if (width == 4736 && !strcmp(model,"K-7")) -@@ -8220,6 +8247,7 @@ +@@ -8220,6 +8257,7 @@ switch (tiff_compress) { case 1: load_raw = &CLASS packed_dng_load_raw; break; case 7: load_raw = &CLASS lossless_dng_load_raw; break; @@ -1365,7 +1375,7 @@ case 34892: load_raw = &CLASS lossy_dng_load_raw; break; default: load_raw = 0; } -@@ -8347,7 +8375,7 @@ +@@ -8347,7 +8385,7 @@ width -= 44; } else if (!strcmp(model,"D3200") || !strcmp(model,"D600") || @@ -1374,7 +1384,7 @@ width -= 46; } else if (!strcmp(model,"D4") || !strcmp(model,"Df")) { -@@ -8567,24 +8595,46 @@ +@@ -8567,24 +8605,46 @@ if (load_raw == &CLASS lossless_jpeg_load_raw) load_raw = &CLASS hasselblad_load_raw; if (raw_width == 7262) { @@ -1423,7 +1433,7 @@ } else if (raw_width == 4090) { strcpy (model, "V96C"); height -= (top_margin = 6); -@@ -8637,6 +8687,7 @@ +@@ -8637,6 +8697,7 @@ filters = 0x16161616; } } else if (!strcmp(make,"Leica") || !strcmp(make,"Panasonic")) { @@ -1431,7 +1441,7 @@ if ((flen - data_offset) / (raw_width*8/7) == raw_height) load_raw = &CLASS panasonic_load_raw; if (!load_raw) { -@@ -8654,6 +8705,7 @@ +@@ -8654,6 +8715,7 @@ } filters = 0x01010101 * (uchar) "\x94\x61\x49\x16" [((filters-1) ^ (left_margin & 1) ^ (top_margin << 1)) & 3]; @@ -1439,7 +1449,7 @@ } else if (!strcmp(model,"C770UZ")) { height = 1718; width = 2304; -@@ -8883,6 +8935,14 @@ +@@ -8883,6 +8945,14 @@ memcpy (rgb_cam, cmatrix, sizeof cmatrix); raw_color = 0; } @@ -1454,7 +1464,7 @@ if (raw_color) adobe_coeff (make, model); if (load_raw == &CLASS kodak_radc_load_raw) if (raw_color) adobe_coeff ("Apple","Quicktake"); -@@ -8899,7 +8959,7 @@ +@@ -8899,7 +8969,7 @@ if (!tiff_bps) tiff_bps = 12; if (!maximum) maximum = (1 << tiff_bps) - 1; if (!load_raw || height < 22 || width < 22 || @@ -1463,7 +1473,7 @@ is_raw = 0; #ifdef NO_JASPER if (load_raw == &CLASS redcine_load_raw) { -@@ -8978,195 +9038,250 @@ +@@ -8978,195 +9048,250 @@ } #endif @@ -1889,7 +1899,7 @@ struct tiff_tag { ushort tag, type; int count; -@@ -9188,585 +9303,12 @@ +@@ -9188,585 +9313,12 @@ unsigned gps[26]; char desc[512], make[64], model[64], soft[32], date[20], artist[64]; };