Fixed whitelevel bug in 3FR calibration data handling

This commit is contained in:
torger
2015-01-04 18:50:11 +01:00
parent d2a4faea14
commit 0e638ebc4a
2 changed files with 126 additions and 106 deletions

View File

@@ -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 <glib.h>
+/*RT*/#include <glib/gstdio.h>
@@ -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];
};