diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 87e69c237..51027ecaf 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -27,6 +27,8 @@ #include #include #include "opthelper.h" +#define BENCHMARK +#include "StopWatch.h" /* dcraw.c -- Dave Coffin's raw photo decoder @@ -602,6 +604,36 @@ inline unsigned CLASS getbithuff_t::operator() (int nbits, ushort *huff) #define getbits(n) getbithuff(n,0) #define gethuff(h) getbithuff(*h,h+1) +inline unsigned CLASS nikbithuff_t::operator() (int nbits, ushort *huff) +{ + unsigned c; + + if (UNLIKELY(nbits == 0)) { + return 0; + } + if (vbits < nbits && LIKELY((c = fgetc(ifp)) != EOF)) { + bitbuf = (bitbuf << 8) + (uchar) c; + vbits += 8; + if (vbits < nbits && LIKELY((c = fgetc(ifp)) != EOF)) { + bitbuf = (bitbuf << 8) + (uchar) c; + vbits += 8; + } + } + c = bitbuf << (32-vbits) >> (32-nbits); + if (huff) { + vbits -= huff[c] >> 8; + c = (uchar) huff[c]; + derror(vbits < 0); + } else { + vbits -= nbits; + } + return c; +} + +#define nikinit(n) nikbithuff() +#define nikbits(n) nikbithuff(n,0) +#define nikhuff(h) nikbithuff(*h,h+1) + /* Construct a decode tree according the specification in *source. The first 16 bytes specify how many codes should be 1-bit, 2-bit @@ -1188,67 +1220,89 @@ void CLASS pentax_load_raw() void CLASS nikon_load_raw() { - static const uchar nikon_tree[][32] = { - { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */ - 5,4,3,6,2,7,1,0,8,9,11,10,12 }, - { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy after split */ - 0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 }, - { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, /* 12-bit lossless */ - 5,4,6,3,7,2,8,1,9,0,10,11,12 }, - { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0, /* 14-bit lossy */ - 5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 }, - { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0, /* 14-bit lossy after split */ - 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 }, - { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */ - 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } }; - ushort *huff, ver0, ver1, vpred[2][2], hpred[2], csize; - int i, min, max, step=0, tree=0, split=0, row, col, len, shl, diff; +BENCHFUN + static const uchar nikon_tree[][32] = { + { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */ + 5,4,3,6,2,7,1,0,8,9,11,10,12 }, + { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy after split */ + 0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 }, + { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, /* 12-bit lossless */ + 5,4,6,3,7,2,8,1,9,0,10,11,12 }, + { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0, /* 14-bit lossy */ + 5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 }, + { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0, /* 14-bit lossy after split */ + 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 }, + { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */ + 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } }; + ushort *huff, ver0, ver1, vpred[2][2], hpred[2], csize; + int max, step=0, tree=0, split=0; - fseek (ifp, meta_offset, SEEK_SET); - ver0 = fgetc(ifp); - ver1 = fgetc(ifp); - if (ver0 == 0x49 || ver1 == 0x58) - fseek (ifp, 2110, SEEK_CUR); - if (ver0 == 0x46) tree = 2; - if (tiff_bps == 14) tree += 3; - read_shorts (vpred[0], 4); - max = 1 << tiff_bps & 0x7fff; - if ((csize = get2()) > 1) - step = max / (csize-1); - if (ver0 == 0x44 && ver1 == 0x20 && step > 0) { - for (i=0; i < csize; i++) - curve[i*step] = get2(); - for (i=0; i < max; i++) - curve[i] = ( curve[i-i%step]*(step-i%step) + - curve[i-i%step+step]*(i%step) ) / step; - fseek (ifp, meta_offset+562, SEEK_SET); - split = get2(); - } else if (ver0 != 0x46 && csize <= 0x4001) - read_shorts (curve, max=csize); - while (curve[max-2] == curve[max-1]) max--; - huff = make_decoder (nikon_tree[tree]); - fseek (ifp, data_offset, SEEK_SET); - getbits(-1); - for (min=row=0; row < height; row++) { - if (split && row == split) { - free (huff); - huff = make_decoder (nikon_tree[tree+1]); - max += (min = 16) << 1; + fseek (ifp, meta_offset, SEEK_SET); + ver0 = fgetc(ifp); + ver1 = fgetc(ifp); + if (ver0 == 0x49 || ver1 == 0x58) + fseek (ifp, 2110, SEEK_CUR); + if (ver0 == 0x46) tree = 2; + if (tiff_bps == 14) tree += 3; + read_shorts (vpred[0], 4); + max = 1 << tiff_bps & 0x7fff; + if ((csize = get2()) > 1) + step = max / (csize-1); + if (ver0 == 0x44 && ver1 == 0x20 && step > 0) { + for (int i=0; i < csize; i++) + curve[i*step] = get2(); + for (int i=0; i < max; i++) + curve[i] = ( curve[i-i%step]*(step-i%step) + + curve[i-i%step+step]*(i%step) ) / step; + fseek (ifp, meta_offset+562, SEEK_SET); + split = get2(); + } else if (ver0 != 0x46 && csize <= 0x4001) + read_shorts (curve, max=csize); + while (curve[max-2] == curve[max-1]) max--; + huff = make_decoder (nikon_tree[tree]); + fseek (ifp, data_offset, SEEK_SET); + nikinit(); + if (split) { + for (int min = 0, row = 0; row < height; row++) { + if (row == split) { + free (huff); + huff = make_decoder (nikon_tree[tree+1]); + max += (min = 16) << 1; + } + for (int col=0; col < raw_width; col++) { + int i = nikhuff(huff); + int len = i & 15; + int shl = i >> 4; + int diff = ((nikbits(len-shl) << 1) + 1) << shl >> 1; + if ((diff & (1 << (len-1))) == 0) + diff -= (1 << len) - !shl; + if (col < 2) hpred[col] = vpred[row & 1][col] += diff; + else hpred[col & 1] += diff; + derror((ushort)(hpred[col & 1] + min) >= max); + RAW(row,col) = curve[LIM((short)hpred[col & 1],0,0x3fff)]; + } + } + } else { + for (int row=0; row < height; row++) { + for (int col=0; col < raw_width; col++) { + int len = nikhuff(huff) & 15; + int diff = ((nikbits(len) << 1) + 1) >> 1; + if ((diff & (1 << (len-1))) == 0) + diff -= (1 << len) - 1; + if (col < 2) hpred[col] = vpred[row & 1][col] += diff; + else hpred[col & 1] += diff; + if((ushort)(hpred[col & 1]) >= max) derror(); +// derror((ushort)(hpred[col & 1]) >= max); + RAW(row,col) = curve[LIM((short)hpred[col & 1],0,0x3fff)]; + } + } } - for (col=0; col < raw_width; col++) { - i = gethuff(huff); - len = i & 15; - shl = i >> 4; - diff = ((getbits(len-shl) << 1) + 1) << shl >> 1; - if ((diff & (1 << (len-1))) == 0) - diff -= (1 << len) - !shl; - if (col < 2) hpred[col] = vpred[row & 1][col] += diff; - else hpred[col & 1] += diff; - if ((ushort)(hpred[col & 1] + min) >= max) derror(); - RAW(row,col) = curve[LIM((short)hpred[col & 1],0,0x3fff)]; + free (huff); + data_error += nikbithuff.errorCount(); + if(data_error) { + std::cerr << nikbithuff.errorCount() << " / " << data_error << std::endl; + std::cerr << ifname << " decoded with " << data_error << " errors. File possibly corrupted" << std::endl; } - } - free (huff); } void CLASS nikon_yuv_load_raw() diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h index 9edc4196b..b17a93c28 100644 --- a/rtengine/dcraw.h +++ b/rtengine/dcraw.h @@ -60,6 +60,7 @@ public: ,RT_matrix_from_constant(0) ,RT_from_adobe_dng_converter(false) ,getbithuff(this,ifp,zero_after_ff) + ,nikbithuff(this,ifp) { memset(&hbd, 0, sizeof(hbd)); aber[0]=aber[1]=aber[2]=aber[3]=1; @@ -214,6 +215,7 @@ protected: int fcol (int row, int col); void merror (void *ptr, const char *where); void derror(); +void derror(bool condition) {data_error += condition;} ushort sget2 (uchar *s); ushort get2(); unsigned sget4 (uchar *s); @@ -252,6 +254,25 @@ private: }; getbithuff_t getbithuff; +class nikbithuff_t +{ +public: + nikbithuff_t(DCraw *p,IMFILE *&i):parent(p),bitbuf(0),errors(0),vbits(0),ifp(i){} + void operator()() {bitbuf = vbits = 0;}; + unsigned operator()(int nbits, ushort *huff); + unsigned errorCount() { return errors; } +private: + bool derror(bool condition){ + errors += condition; + return condition; + } + DCraw *parent; + unsigned bitbuf, errors; + int vbits; + IMFILE *&ifp; +}; +nikbithuff_t nikbithuff; + ushort * make_decoder_ref (const uchar **source); ushort * make_decoder (const uchar *source); void crw_init_tables (unsigned table, ushort *huff[2]);