This repository has been archived by the owner on Jul 22, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
/
SrwDecoder.cpp
502 lines (448 loc) · 17.9 KB
/
SrwDecoder.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
#include "StdAfx.h"
#include "SrwDecoder.h"
#include "ByteStreamSwap.h"
#if defined(__unix__) || defined(__APPLE__)
#include <stdlib.h>
#endif
/*
RawSpeed - RAW file decoder.
Copyright (C) 2009-2010 Klaus Post
Copyright (C) 2014-2015 Pedro Côrte-Real
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
http://www.klauspost.com
*/
namespace RawSpeed {
SrwDecoder::SrwDecoder(TiffIFD *rootIFD, FileMap* file):
RawDecoder(file), mRootIFD(rootIFD) {
decoderVersion = 3;
b = NULL;
}
SrwDecoder::~SrwDecoder(void) {
if (mRootIFD)
delete mRootIFD;
mRootIFD = NULL;
if (NULL != b)
delete b;
b = NULL;
}
RawImage SrwDecoder::decodeRawInternal() {
vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(STRIPOFFSETS);
if (data.empty())
ThrowRDE("Srw Decoder: No image data found");
TiffIFD* raw = data[0];
int compression = raw->getEntry(COMPRESSION)->getInt();
int bits = raw->getEntry(BITSPERSAMPLE)->getInt();
if (32769 != compression && 32770 != compression && 32772 != compression && 32773 != compression)
ThrowRDE("Srw Decoder: Unsupported compression");
if (32769 == compression)
{
bool bit_order = false; // Default guess
map<string,string>::iterator msb_hint = hints.find("msb_override");
if (msb_hint != hints.end())
bit_order = (0 == (msb_hint->second).compare("true"));
this->decodeUncompressed(raw, bit_order ? BitOrder_Jpeg : BitOrder_Plain);
return mRaw;
}
if (32770 == compression)
{
if (!raw->hasEntry ((TiffTag)40976)) {
bool bit_order = (bits == 12); // Default guess
map<string,string>::iterator msb_hint = hints.find("msb_override");
if (msb_hint != hints.end())
bit_order = (0 == (msb_hint->second).compare("true"));
this->decodeUncompressed(raw, bit_order ? BitOrder_Jpeg : BitOrder_Plain);
return mRaw;
} else {
uint32 nslices = raw->getEntry(STRIPOFFSETS)->count;
if (nslices != 1)
ThrowRDE("Srw Decoder: Only one slice supported, found %u", nslices);
try {
decodeCompressed(raw);
} catch (RawDecoderException& e) {
mRaw->setError(e.what());
}
return mRaw;
}
}
if (32772 == compression)
{
uint32 nslices = raw->getEntry(STRIPOFFSETS)->count;
if (nslices != 1)
ThrowRDE("Srw Decoder: Only one slice supported, found %u", nslices);
try {
decodeCompressed2(raw, bits);
} catch (RawDecoderException& e) {
mRaw->setError(e.what());
}
return mRaw;
}
if (32773 == compression)
{
decodeCompressed3(raw, bits);
return mRaw;
}
ThrowRDE("Srw Decoder: Unsupported compression");
return mRaw;
}
// Decoder for compressed srw files (NX300 and later)
void SrwDecoder::decodeCompressed( TiffIFD* raw )
{
uint32 width = raw->getEntry(IMAGEWIDTH)->getInt();
uint32 height = raw->getEntry(IMAGELENGTH)->getInt();
mRaw->dim = iPoint2D(width, height);
mRaw->createData();
const uint32 offset = raw->getEntry(STRIPOFFSETS)->getInt();
uint32 compressed_offset = raw->getEntry((TiffTag)40976)->getInt();
if (NULL != b)
delete b;
if (getHostEndianness() == little)
b = new ByteStream(mFile, 0);
else
b = new ByteStreamSwap(mFile, 0);
b->setAbsoluteOffset(compressed_offset);
for (uint32 y = 0; y < height; y++) {
uint32 line_offset = offset + b->getInt();
if (line_offset >= mFile->getSize())
ThrowRDE("Srw decoder: Offset outside image file, file probably truncated.");
int len[4];
for (int i = 0; i < 4; i++)
len[i] = y < 2 ? 7 : 4;
BitPumpMSB32 bits(mFile, line_offset);
int op[4];
ushort16* img = (ushort16*)mRaw->getData(0, y);
ushort16* img_up = (ushort16*)mRaw->getData(0, max(0, (int)y - 1));
ushort16* img_up2 = (ushort16*)mRaw->getData(0, max(0, (int)y - 2));
// Image is arranged in groups of 16 pixels horizontally
for (uint32 x = 0; x < width; x += 16) {
bits.fill();
bool dir = !!bits.getBitNoFill();
for (int i = 0; i < 4; i++)
op[i] = bits.getBitsNoFill(2);
for (int i = 0; i < 4; i++) {
switch (op[i]) {
case 3: len[i] = bits.getBits(4);
break;
case 2: len[i]--;
break;
case 1: len[i]++;
}
if (len[i] < 0)
ThrowRDE("Srw Decompressor: Bit length less than 0.");
if (len[i] > 16)
ThrowRDE("Srw Decompressor: Bit Length more than 16.");
}
if (dir) {
// Upward prediction
// First we decode even pixels
for (int c = 0; c < 16; c += 2) {
int b = len[(c >> 3)];
int32 adj = ((int32) bits.getBits(b) << (32-b) >> (32-b));
img[c] = adj + img_up[c];
}
// Now we decode odd pixels
// Why on earth upward prediction only looks up 1 line above
// is beyond me, it will hurt compression a deal.
for (int c = 1; c < 16; c += 2) {
int b = len[2 | (c >> 3)];
int32 adj = ((int32) bits.getBits(b) << (32-b) >> (32-b));
img[c] = adj + img_up2[c];
}
} else {
// Left to right prediction
// First we decode even pixels
int pred_left = x ? img[-2] : 128;
for (int c = 0; c < 16; c += 2) {
int b = len[(c >> 3)];
int32 adj = ((int32) bits.getBits(b) << (32-b) >> (32-b));
img[c] = adj + pred_left;
}
// Now we decode odd pixels
pred_left = x ? img[-1] : 128;
for (int c = 1; c < 16; c += 2) {
int b = len[2 | (c >> 3)];
int32 adj = ((int32) bits.getBits(b) << (32-b) >> (32-b));
img[c] = adj + pred_left;
}
}
bits.checkPos();
img += 16;
img_up += 16;
img_up2 += 16;
}
}
// Swap red and blue pixels to get the final CFA pattern
for (uint32 y = 0; y < height-1; y+=2) {
ushort16* topline = (ushort16*)mRaw->getData(0, y);
ushort16* bottomline = (ushort16*)mRaw->getData(0, y+1);
for (uint32 x = 0; x < width-1; x += 2) {
ushort16 temp = topline[1];
topline[1] = bottomline[0];
bottomline[0] = temp;
topline += 2;
bottomline += 2;
}
}
}
// Decoder for compressed srw files (NX3000 and later)
void SrwDecoder::decodeCompressed2( TiffIFD* raw, int bits)
{
uint32 width = raw->getEntry(IMAGEWIDTH)->getInt();
uint32 height = raw->getEntry(IMAGELENGTH)->getInt();
uint32 offset = raw->getEntry(STRIPOFFSETS)->getInt();
mRaw->dim = iPoint2D(width, height);
mRaw->createData();
// This format has a variable length encoding of how many bits are needed
// to encode the difference between pixels, we use a table to process it
// that has two values, the first the number of bits that were used to
// encode, the second the number of bits that come after with the difference
// The table has 14 entries because the difference can have between 0 (no
// difference) and 13 bits (differences between 12 bits numbers can need 13)
const uchar8 tab[14][2] = {{3,4}, {3,7}, {2,6}, {2,5}, {4,3}, {6,0}, {7,9},
{8,10}, {9,11}, {10,12}, {10,13}, {5,1}, {4,8}, {4,2}};
encTableItem tbl[1024];
ushort16 vpred[2][2] = {{0,0},{0,0}}, hpred[2];
// We generate a 1024 entry table (to be addressed by reading 10 bits) by
// consecutively filling in 2^(10-N) positions where N is the variable number of
// bits of the encoding. So for example 4 is encoded with 3 bits so the first
// 2^(10-3)=128 positions are set with 3,4 so that any time we read 000 we
// know the next 4 bits are the difference. We read 10 bits because that is
// the maximum number of bits used in the variable encoding (for the 12 and
// 13 cases)
uint32 n = 0;
for (uint32 i=0; i < 14; i++) {
for(int32 c = 0; c < (1024 >> tab[i][0]); c++) {
tbl[n ].encLen = tab[i][0];
tbl[n++].diffLen = tab[i][1];
}
}
BitPumpMSB pump(mFile, offset);
for (uint32 y = 0; y < height; y++) {
ushort16* img = (ushort16*)mRaw->getData(0, y);
for (uint32 x = 0; x < width; x++) {
int32 diff = samsungDiff(pump, tbl);
if (x < 2)
hpred[x] = vpred[y & 1][x] += diff;
else
hpred[x & 1] += diff;
img[x] = hpred[x & 1];
if (img[x] >> bits)
ThrowRDE("SRW: Error: decoded value out of bounds at %d:%d", x, y);
}
}
}
int32 SrwDecoder::samsungDiff (BitPumpMSB &pump, encTableItem *tbl)
{
// We read 10 bits to index into our table
uint32 c = pump.peekBits(10);
// Skip the bits that were used to encode this case
pump.getBitsSafe(tbl[c].encLen);
// Read the number of bits the table tells me
int32 len = tbl[c].diffLen;
int32 diff = pump.getBitsSafe(len);
// If the first bit is 0 we need to turn this into a negative number
if (len && (diff & (1 << (len-1))) == 0)
diff -= (1 << len) - 1;
return diff;
}
// Decoder for third generation compressed SRW files (NX1)
// Seriously Samsung just use lossless jpeg already, it compresses better too :)
// Thanks to Michael Reichmann (Luminous Landscape) for putting me in contact
// and Loring von Palleske (Samsung) for pointing to the open-source code of
// Samsung's DNG converter at http://opensource.samsung.com/
void SrwDecoder::decodeCompressed3( TiffIFD* raw, int bits)
{
uint32 offset = raw->getEntry(STRIPOFFSETS)->getInt();
BitPumpMSB32 startpump(mFile, offset);
// Process the initial metadata bits, we only really use initVal, width and
// height (the last two match the TIFF values anyway)
startpump.getBitsSafe(16); // NLCVersion
startpump.getBitsSafe(4); // ImgFormat
uint32 bitDepth = startpump.getBitsSafe(4)+1;
startpump.getBitsSafe(4); // NumBlkInRCUnit
startpump.getBitsSafe(4); // CompressionRatio
uint32 width = startpump.getBitsSafe(16);
uint32 height = startpump.getBitsSafe(16);
startpump.getBitsSafe(16); // TileWidth
startpump.getBitsSafe(4); // reserved
// The format includes an optimization code that sets 3 flags to change the
// decoding parameters
uint32 optflags = startpump.getBitsSafe(4);
#define OPT_SKIP 1 // Skip checking if we need differences from previous line
#define OPT_MV 2 // Simplify motion vector definition
#define OPT_QP 4 // Don't scale the diff values
startpump.getBitsSafe(8); // OverlapWidth
startpump.getBitsSafe(8); // reserved
startpump.getBitsSafe(8); // Inc
startpump.getBitsSafe(2); // reserved
uint32 initVal = startpump.getBitsSafe(14);
mRaw->dim = iPoint2D(width, height);
mRaw->createData();
// The format is relatively straightforward. Each line gets encoded as a set
// of differences from pixels from another line. Pixels are grouped in blocks
// of 16 (8 green, 8 red or blue). Each block is encoded in three sections.
// First 1 or 4 bits to specify which reference pixels to use, then a section
// that specifies for each pixel the number of bits in the difference, then
// the actual difference bits
uint32 motion;
uint32 diffBitsMode[3][2] = {{0}};
uint32 line_offset = startpump.getOffset();
for (uint32 row=0; row < height; row++) {
// Align pump to 16byte boundary
if ((line_offset & 0xf) != 0)
line_offset += 16 - (line_offset & 0xf);
BitPumpMSB32 pump(mFile, offset+line_offset);
ushort16* img = (ushort16*)mRaw->getData(0, row);
ushort16* img_up = (ushort16*)mRaw->getData(0, max(0, (int)row - 1));
ushort16* img_up2 = (ushort16*)mRaw->getData(0, max(0, (int)row - 2));
// Initialize the motion and diff modes at the start of the line
motion = 7;
// By default we are not scaling values at all
int32 scale = 0;
for (uint32 i=0; i<3; i++)
diffBitsMode[i][0] = diffBitsMode[i][1] = (row==0 || row==1) ? 7 : 4;
for (uint32 col=0; col < width; col += 16) {
if (!(optflags & OPT_QP) && !(col & 63)) {
int32 scalevals[] = {0,-2,2};
uint32 i = pump.getBitsSafe(2);
scale = i < 3 ? scale+scalevals[i] : pump.getBitsSafe(12);
}
// First we figure out which reference pixels mode we're in
if (optflags & OPT_MV)
motion = pump.getBitsSafe(1) ? 3 : 7;
else if (!pump.getBitsSafe(1))
motion = pump.getBitsSafe(3);
if ((row==0 || row==1) && (motion != 7))
ThrowRDE("SRW Decoder: At start of image and motion isn't 7. File corrupted?");
if (motion == 7) {
// The base case, just set all pixels to the previous ones on the same line
// If we're at the left edge we just start at the initial value
for (uint32 i=0; i<16; i++) {
img[i] = (col == 0) ? initVal : *(img+i-2);
}
} else {
// The complex case, we now need to actually lookup one or two lines above
if (row < 2)
ThrowRDE("SRW: Got a previous line lookup on first two lines. File corrupted?");
int32 motionOffset[7] = {-4,-2,-2,0,0,2,4};
int32 motionDoAverage[7] = { 0, 0, 1,0,1,0,0};
int32 slideOffset = motionOffset[motion];
int32 doAverage = motionDoAverage[motion];
for (uint32 i=0; i<16; i++) {
ushort16* refpixel;
if ((row+i) & 0x1) // Red or blue pixels use same color two lines up
refpixel = img_up2 + i + slideOffset;
else // Green pixel N uses Green pixel N from row above (top left or top right)
refpixel = img_up + i + slideOffset + ((i%2) ? -1 : 1);
// In some cases we use as reference interpolation of this pixel and the next
if (doAverage)
img[i] = (*refpixel + *(refpixel+2) + 1) >> 1;
else
img[i] = *refpixel;
}
}
// Figure out how many difference bits we have to read for each pixel
uint32 diffBits[4] = {0};
if (optflags & OPT_SKIP || !pump.getBitsSafe(1)) {
uint32 flags[4];
for (uint32 i=0; i<4; i++)
flags[i] = pump.getBitsSafe(2);
for (uint32 i=0; i<4; i++) {
// The color is 0-Green 1-Blue 2-Red
uint32 colornum = (row % 2 != 0) ? i>>1 : ((i>>1)+2) % 3;
switch(flags[i]) {
case 0: diffBits[i] = diffBitsMode[colornum][0]; break;
case 1: diffBits[i] = diffBitsMode[colornum][0]+1; break;
case 2: diffBits[i] = diffBitsMode[colornum][0]-1; break;
case 3: diffBits[i] = pump.getBitsSafe(4); break;
}
diffBitsMode[colornum][0] = diffBitsMode[colornum][1];
diffBitsMode[colornum][1] = diffBits[i];
if(diffBits[i] > bitDepth+1)
ThrowRDE("SRW Decoder: Too many difference bits. File corrupted?");
}
}
// Actually read the differences and write them to the pixels
for (uint32 i=0; i<16; i++) {
uint32 len = diffBits[i>>2];
int32 diff = pump.getBitsSafe(len);
// If the first bit is 1 we need to turn this into a negative number
if (diff >> (len-1))
diff -= (1 << len);
ushort16 *value = NULL;
// Apply the diff to pixels 0 2 4 6 8 10 12 14 1 3 5 7 9 11 13 15
if (row % 2)
value = &img[((i&0x7)<<1)+1-(i>>3)];
else
value = &img[((i&0x7)<<1)+(i>>3)];
diff = diff * (scale*2+1) + scale;
*value = clampbits(*value + diff, bits);
}
img += 16;
img_up += 16;
img_up2 += 16;
}
line_offset += pump.getOffset();
}
}
string SrwDecoder::getMode() {
vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(CFAPATTERN);
ostringstream mode;
if (!data.empty() && data[0]->hasEntryRecursive(BITSPERSAMPLE)) {
mode << data[0]->getEntryRecursive(BITSPERSAMPLE)->getInt() << "bit";
return mode.str();
}
return "";
}
void SrwDecoder::checkSupportInternal(CameraMetaData *meta) {
vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);
if (data.empty())
ThrowRDE("Srw Support check: Model name found");
if (!data[0]->hasEntry(MAKE))
ThrowRDE("SRW Support: Make name not found");
string make = data[0]->getEntry(MAKE)->getString();
string model = data[0]->getEntry(MODEL)->getString();
string mode = getMode();
if (meta->hasCamera(make, model, mode))
this->checkCameraSupported(meta, make, model, getMode());
else
this->checkCameraSupported(meta, make, model, "");
}
void SrwDecoder::decodeMetaDataInternal(CameraMetaData *meta) {
vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);
if (data.empty())
ThrowRDE("SRW Meta Decoder: Model name found");
string make = data[0]->getEntry(MAKE)->getString();
string model = data[0]->getEntry(MODEL)->getString();
int iso = 0;
if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getInt();
string mode = getMode();
if (meta->hasCamera(make, model, mode))
setMetaData(meta, make, model, mode, iso);
else
setMetaData(meta, make, model, "", iso);
// Set the whitebalance
if (mRootIFD->hasEntryRecursive(SAMSUNG_WB_RGGBLEVELSUNCORRECTED) &&
mRootIFD->hasEntryRecursive(SAMSUNG_WB_RGGBLEVELSBLACK)) {
TiffEntry *wb_levels = mRootIFD->getEntryRecursive(SAMSUNG_WB_RGGBLEVELSUNCORRECTED);
TiffEntry *wb_black = mRootIFD->getEntryRecursive(SAMSUNG_WB_RGGBLEVELSBLACK);
if (wb_levels->count == 4 && wb_black->count == 4) {
wb_levels->offsetFromParent();
wb_black->offsetFromParent();
mRaw->metadata.wbCoeffs[0] = wb_levels->getFloat(0) - wb_black->getFloat(0);
mRaw->metadata.wbCoeffs[1] = wb_levels->getFloat(1) - wb_black->getFloat(1);
mRaw->metadata.wbCoeffs[2] = wb_levels->getFloat(3) - wb_black->getFloat(3);
}
}
}
} // namespace RawSpeed