-
Notifications
You must be signed in to change notification settings - Fork 228
/
jpg_0XC3.cpp
513 lines (502 loc) · 22.3 KB
/
jpg_0XC3.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
503
504
505
506
507
508
509
510
511
512
513
#include "jpg_0XC3.h"
#include "print.h"
#include <stdbool.h> //requires VS 2015 or later
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
unsigned char readByte(unsigned char *lRawRA, long *lRawPos, long lRawSz) {
unsigned char ret = 0x00;
if (*lRawPos < lRawSz)
ret = lRawRA[*lRawPos];
(*lRawPos)++;
return ret;
} // readByte()
uint16_t readWord(unsigned char *lRawRA, long *lRawPos, long lRawSz) {
return ((readByte(lRawRA, lRawPos, lRawSz) << 8) + readByte(lRawRA, lRawPos, lRawSz));
} // readWord()
int readBit(unsigned char *lRawRA, long *lRawPos, int *lCurrentBitPos) { //Read the next single bit
int result = (lRawRA[*lRawPos] >> (7 - *lCurrentBitPos)) & 1;
(*lCurrentBitPos)++;
if (*lCurrentBitPos == 8) {
(*lRawPos)++;
*lCurrentBitPos = 0;
}
return result;
} // readBit()
int bitMask(int bits) {
return ((2 << (bits - 1)) - 1);
} // bitMask()
int readBits(unsigned char *lRawRA, long *lRawPos, int *lCurrentBitPos, int lNum) { //lNum: bits to read, not to exceed 16
int result = lRawRA[*lRawPos];
result = (result << 8) + lRawRA[(*lRawPos) + 1];
result = (result << 8) + lRawRA[(*lRawPos) + 2];
result = (result >> (24 - *lCurrentBitPos - lNum)) & bitMask(lNum); //lCurrentBitPos is incremented from 1, so -1
*lCurrentBitPos = *lCurrentBitPos + lNum;
if (*lCurrentBitPos > 7) {
*lRawPos = *lRawPos + (*lCurrentBitPos >> 3); // div 8
*lCurrentBitPos = *lCurrentBitPos & 7; //mod 8
}
return result;
} // readBits()
struct HufTables {
uint8_t SSSSszRA[18];
uint8_t LookUpRA[256];
int DHTliRA[32];
int DHTstartRA[32];
int HufSz[32];
int HufCode[32];
int HufVal[32];
int MaxHufSi;
int MaxHufVal;
}; // HufTables()
int decodePixelDifference(unsigned char *lRawRA, long *lRawPos, int *lCurrentBitPos, struct HufTables l) {
int lByte = (lRawRA[*lRawPos] << *lCurrentBitPos) + (lRawRA[*lRawPos + 1] >> (8 - *lCurrentBitPos));
lByte = lByte & 255;
int lHufValSSSS = l.LookUpRA[lByte];
if (lHufValSSSS < 255) {
*lCurrentBitPos = l.SSSSszRA[lHufValSSSS] + *lCurrentBitPos;
*lRawPos = *lRawPos + (*lCurrentBitPos >> 3);
*lCurrentBitPos = *lCurrentBitPos & 7;
} else { //full SSSS is not in the first 8-bits
int lInput = lByte;
int lInputBits = 8;
(*lRawPos)++; // forward 8 bits = precisely 1 byte
do {
lInputBits++;
lInput = (lInput << 1) + readBit(lRawRA, lRawPos, lCurrentBitPos);
if (l.DHTliRA[lInputBits] != 0) { //if any entries with this length
for (int lI = l.DHTstartRA[lInputBits]; lI <= (l.DHTstartRA[lInputBits] + l.DHTliRA[lInputBits] - 1); lI++) {
if (lInput == l.HufCode[lI])
lHufValSSSS = l.HufVal[lI];
} //check each code
} //if any entries with this length
if ((lInputBits >= l.MaxHufSi) && (lHufValSSSS > 254)) { //exhausted options CR: added rev13
lHufValSSSS = l.MaxHufVal;
}
} while (!(lHufValSSSS < 255)); // found;
} //answer in first 8 bits
//The HufVal is referred to as the SSSS in the Codec, so it is called 'lHufValSSSS'
if (lHufValSSSS == 0) //NO CHANGE
return 0;
if (lHufValSSSS == 1) {
if (readBit(lRawRA, lRawPos, lCurrentBitPos) == 0)
return -1;
else
return 1;
}
if (lHufValSSSS == 16) { //ALL CHANGE 16 bit difference: Codec H.1.2.2 "No extra bits are appended after SSSS = 16 is encoded." Osiris fails here
return 32768;
}
//to get here - there is a 2..15 bit difference
int lDiff = readBits(lRawRA, lRawPos, lCurrentBitPos, lHufValSSSS);
if (lDiff <= bitMask(lHufValSSSS - 1)) //add
lDiff = lDiff - bitMask(lHufValSSSS);
return lDiff;
} // decodePixelDifference()
unsigned char *decode_JPEG_SOF_0XC3(const char *fn, int skipBytes, bool verbose, int *dimX, int *dimY, int *bits, int *frames, int diskBytes) {
//decompress JPEG image named "fn" where image data is located skipBytes into file. diskBytes is compressed size of image (set to 0 if unknown)
//next line breaks MSVC
#define abortGoto(...) do {printError(__VA_ARGS__); free(lRawRA); return NULL;} while(0)
unsigned char *lImgRA8 = NULL;
FILE *reader = fopen(fn, "rb");
int lSuccess = fseek(reader, 0, SEEK_END);
long lRawSz = ftell(reader) - skipBytes;
if ((diskBytes > 0) && (diskBytes < lRawSz)) //only if diskBytes is known and does not exceed length of file
lRawSz = diskBytes;
if ((lSuccess != 0) || (lRawSz <= 8)) {
printError("Unable to load 0XC3 JPEG %s\n", fn);
return NULL; //read failure
}
lSuccess = fseek(reader, skipBytes, SEEK_SET); //If successful, the function returns zero
if (lSuccess != 0) {
printError("Unable to open 0XC3 JPEG %s\n", fn);
return NULL; //read failure
}
unsigned char *lRawRA = (unsigned char *)malloc(lRawSz);
size_t lSz = fread(lRawRA, 1, lRawSz, reader);
fclose(reader);
if ((lSz < (size_t)lRawSz) || (lRawRA[0] != 0xFF) || (lRawRA[1] != 0xD8) || (lRawRA[2] != 0xFF)) {
abortGoto("JPEG signature 0xFFD8FF not found at offset %d of %s\n", skipBytes, fn); //signature failure http://en.wikipedia.org/wiki/List_of_file_signatures
}
if (verbose)
printMessage("JPEG signature 0xFFD8FF found at offset %d of %s\n", skipBytes, fn);
//next: read header
long lRawPos = 2; //Skip initial 0xFFD8, begin with third byte
//long lRawPos = 0; //Skip initial 0xFFD8, begin with third byte
unsigned char btS1, btS2, SOSse, SOSahal, btMarkerType, SOSns = 0x00; //tag
unsigned char SOSpttrans = 0;
unsigned char SOSss = 0;
uint8_t SOFnf = 0;
uint8_t SOFprecision = 0;
uint16_t SOFydim = 0;
uint16_t SOFxdim = 0;
// long SOSarrayPos; //SOFarrayPos
int lnHufTables = 0;
int lFrameCount = 1;
const int kmaxFrames = 4;
struct HufTables l[kmaxFrames + 1];
do { //read each marker in the header
do {
btS1 = readByte(lRawRA, &lRawPos, lRawSz);
if (btS1 != 0xFF) {
abortGoto("JPEG header tag must begin with 0xFF\n");
}
btMarkerType = readByte(lRawRA, &lRawPos, lRawSz);
if ((btMarkerType == 0x01) || (btMarkerType == 0xFF) || ((btMarkerType >= 0xD0) && (btMarkerType <= 0xD7)))
btMarkerType = 0; //only process segments with length fields
} while ((lRawPos < lRawSz) && (btMarkerType == 0));
uint16_t lSegmentLength = readWord(lRawRA, &lRawPos, lRawSz); //read marker length
long lSegmentEnd = lRawPos + (lSegmentLength - 2);
if (lSegmentEnd > lRawSz) {
abortGoto("Segment larger than image\n");
}
if (verbose)
printMessage("btMarkerType %#02X length %d@%ld\n", btMarkerType, lSegmentLength, lRawPos);
if (((btMarkerType >= 0xC0) && (btMarkerType <= 0xC3)) || ((btMarkerType >= 0xC5) && (btMarkerType <= 0xCB)) || ((btMarkerType >= 0xCD) && (btMarkerType <= 0xCF))) {
//if Start-Of-Frame (SOF) marker
SOFprecision = readByte(lRawRA, &lRawPos, lRawSz);
SOFydim = readWord(lRawRA, &lRawPos, lRawSz);
SOFxdim = readWord(lRawRA, &lRawPos, lRawSz);
SOFnf = readByte(lRawRA, &lRawPos, lRawSz);
//SOFarrayPos = lRawPos;
lRawPos = (lSegmentEnd);
if (verbose)
printMessage(" [Precision %d X*Y %d*%d Frames %d]\n", SOFprecision, SOFxdim, SOFydim, SOFnf);
if (btMarkerType != 0xC3) { //lImgTypeC3 = true;
abortGoto("This JPEG decoder can only decompress lossless JPEG ITU-T81 images (SoF must be 0XC3, not %#02X)\n", btMarkerType);
}
if ((SOFprecision < 1) || (SOFprecision > 16) || (SOFnf < 1) || (SOFnf == 2) || (SOFnf > 3) || ((SOFnf == 3) && (SOFprecision > 8))) {
abortGoto("Scalar data must be 1..16 bit, RGB data must be 8-bit (%d-bit, %d frames)\n", SOFprecision, SOFnf);
}
} else if (btMarkerType == 0xC4) { //if SOF marker else if define-Huffman-tables marker (DHT)
if (verbose)
printMessage(" [Huffman Length %d]\n", lSegmentLength);
do {
uint8_t DHTnLi = readByte(lRawRA, &lRawPos, lRawSz); //we read but ignore DHTtcth.
#pragma unused(DHTnLi) //we need to increment the input file position, but we do not care what the value is
DHTnLi = 0;
for (int lInc = 1; lInc <= 16; lInc++) {
l[lFrameCount].DHTliRA[lInc] = readByte(lRawRA, &lRawPos, lRawSz);
DHTnLi = DHTnLi + l[lFrameCount].DHTliRA[lInc];
if (l[lFrameCount].DHTliRA[lInc] != 0)
l[lFrameCount].MaxHufSi = lInc;
if (verbose)
printMessage("DHT has %d combinations with %d bits\n", l[lFrameCount].DHTliRA[lInc], lInc);
}
if (DHTnLi > 17) {
abortGoto("Huffman table corrupted.\n");
}
int lIncY = 0; //frequency
for (int lInc = 0; lInc <= 31; lInc++) { //lInc := 0 to 31 do begin
l[lFrameCount].HufVal[lInc] = -1;
l[lFrameCount].HufSz[lInc] = -1;
l[lFrameCount].HufCode[lInc] = -1;
}
for (int lInc = 1; lInc <= 16; lInc++) { //set the huffman size values
if (l[lFrameCount].DHTliRA[lInc] > 0) {
l[lFrameCount].DHTstartRA[lInc] = lIncY + 1;
for (int lIncX = 1; lIncX <= l[lFrameCount].DHTliRA[lInc]; lIncX++) {
lIncY++;
btS1 = readByte(lRawRA, &lRawPos, lRawSz);
l[lFrameCount].HufVal[lIncY] = btS1;
l[lFrameCount].MaxHufVal = btS1;
if (verbose)
printMessage("DHT combination %d has a value of %d\n", lIncY, btS1);
if (btS1 <= 16) //unsigned ints ALWAYS >0, so no need for(btS1 >= 0)
l[lFrameCount].HufSz[lIncY] = lInc;
else {
abortGoto("Huffman size array corrupted.\n");
}
}
}
} //set huffman size values
int K = 1;
int Code = 0;
int Si = l[lFrameCount].HufSz[K];
do {
while (Si == l[lFrameCount].HufSz[K]) {
l[lFrameCount].HufCode[K] = Code;
Code = Code + 1;
K++;
}
if (K <= DHTnLi) {
while (l[lFrameCount].HufSz[K] > Si) {
Code = Code << 1; //Shl!!!
Si = Si + 1;
} //while Si
} //K <= 17
} while (K <= DHTnLi);
//if (verbose)
// for (int j = 1; j <= DHTnLi; j++)
// printMessage(" [%d Sz %d Code %d Value %d]\n", j, l[lFrameCount].HufSz[j], l[lFrameCount].HufCode[j], l[lFrameCount].HufVal[j]);
lFrameCount++;
} while ((lSegmentEnd - lRawPos) >= 18);
lnHufTables = lFrameCount - 1;
lRawPos = (lSegmentEnd);
if (verbose)
printMessage(" [FrameCount %d]\n", lnHufTables);
} else if (btMarkerType == 0xDD) { //if DHT marker else if Define restart interval (DRI) marker
abortGoto("btMarkerType == 0xDD: unsupported Restart Segments\n");
//lRestartSegmentSz = ReadWord(lRawRA, &lRawPos, lRawSz);
//lRawPos = lSegmentEnd;
} else if (btMarkerType == 0xDA) { //if DRI marker else if read Start of Scan (SOS) marker
SOSns = readByte(lRawRA, &lRawPos, lRawSz);
//if Ns = 1 then NOT interleaved, else interleaved: see B.2.3
// SOSarrayPos = lRawPos; //not required...
if (SOSns > 0) {
for (int lInc = 1; lInc <= SOSns; lInc++) {
btS1 = readByte(lRawRA, &lRawPos, lRawSz); //component identifier 1=Y,2=Cb,3=Cr,4=I,5=Q
#pragma unused(btS1) //dummy value used to increment file position
btS2 = readByte(lRawRA, &lRawPos, lRawSz); //horizontal and vertical sampling factors
#pragma unused(btS2) //dummy value used to increment file position
}
}
SOSss = readByte(lRawRA, &lRawPos, lRawSz); //predictor selection B.3
SOSse = readByte(lRawRA, &lRawPos, lRawSz);
#pragma unused(SOSse) //dummy value used to increment file position
SOSahal = readByte(lRawRA, &lRawPos, lRawSz); //lower 4bits= pointtransform
SOSpttrans = SOSahal & 16;
if (verbose)
printMessage(" [Predictor: %d Transform %d]\n", SOSss, SOSahal);
lRawPos = (lSegmentEnd);
} else //if SOS marker else skip marker
lRawPos = (lSegmentEnd);
} while ((lRawPos < lRawSz) && (btMarkerType != 0xDA)); //0xDA=Start of scan: loop for reading header
//NEXT: Huffman decoding
if (lnHufTables < 1) {
abortGoto("Decoding error: no Huffman tables.\n");
}
//NEXT: unpad data - delete byte that follows $FF
//int lIsRestartSegments = 0;
long lIncI = lRawPos; //input position
long lIncO = lRawPos; //output position
do {
lRawRA[lIncO] = lRawRA[lIncI];
if (lRawRA[lIncI] == 255) {
if (lRawRA[lIncI + 1] == 0)
lIncI = lIncI + 1;
else if (lRawRA[lIncI + 1] == 0xD9)
lIncO = -666; //end of padding
//else
// lIsRestartSegments = lRawRA[lIncI+1];
}
lIncI++;
lIncO++;
} while (lIncO > 0);
//if (lIsRestartSegments != 0) //detects both restart and corruption https://groups.google.com/forum/#!topic/comp.protocols.dicom/JUuz0B_aE5o
// printWarning("Detected restart segments, decompress with dcmdjpeg or gdcmconv 0xFF%02X.\n", lIsRestartSegments);
//NEXT: some RGB images use only a single Huffman table for all 3 colour planes. In this case, replicate the correct values
//NEXT: prepare lookup table
for (int lFrameCount = 1; lFrameCount <= lnHufTables; lFrameCount++) {
for (int lInc = 0; lInc <= 17; lInc++)
l[lFrameCount].SSSSszRA[lInc] = 123; //Impossible value for SSSS, suggests 8-bits can not describe answer
for (int lInc = 0; lInc <= 255; lInc++)
l[lFrameCount].LookUpRA[lInc] = 255; //Impossible value for SSSS, suggests 8-bits can not describe answer
}
//NEXT: fill lookuptable
for (int lFrameCount = 1; lFrameCount <= lnHufTables; lFrameCount++) {
int lIncY = 0;
for (int lSz = 1; lSz <= 8; lSz++) { //set the huffman lookup table for keys with lengths <=8
if (l[lFrameCount].DHTliRA[lSz] > 0) {
for (int lIncX = 1; lIncX <= l[lFrameCount].DHTliRA[lSz]; lIncX++) {
lIncY++;
int lHufVal = l[lFrameCount].HufVal[lIncY]; //SSSS
l[lFrameCount].SSSSszRA[lHufVal] = lSz;
int k = (l[lFrameCount].HufCode[lIncY] << (8 - lSz)) & 255; //K= most sig bits for hufman table
if (lSz < 8) { //fill in all possible bits that exceed the huffman table
int lInc = bitMask(8 - lSz);
for (int lCurrentBitPos = 0; lCurrentBitPos <= lInc; lCurrentBitPos++) {
l[lFrameCount].LookUpRA[k + lCurrentBitPos] = lHufVal;
}
} else
l[lFrameCount].LookUpRA[k] = lHufVal; //SSSS
//printMessage("Frame %d SSSS %d Size %d Code %d SHL %d EmptyBits %ld\n", lFrameCount, lHufRA[lFrameCount][lIncY].HufVal, lHufRA[lFrameCount][lIncY].HufSz,lHufRA[lFrameCount][lIncY].HufCode, k, lInc);
} //Set SSSS
} //Length of size lInc > 0
} //for lInc := 1 to 8
} //For each frame, e.g. once each for Red/Green/Blue
//NEXT: some RGB images use only a single Huffman table for all 3 colour planes. In this case, replicate the correct values
if (lnHufTables < SOFnf) { //use single Hufman table for each frame
for (int lFrameCount = lnHufTables + 1; lFrameCount <= SOFnf; lFrameCount++) {
l[lFrameCount] = l[lnHufTables];
} //for each frame
} // if lnHufTables < SOFnf
//NEXT: uncompress data: different loops for different predictors
int lItems = SOFxdim * SOFydim * SOFnf;
// lRawPos++;// <- only for Pascal where array is indexed from 1 not 0 first byte of data
int lCurrentBitPos = 0; //read in a new byte
//depending on SOSss, we see Table H.1
int lPredA = 0;
int lPredB = 0;
int lPredC = 0;
if (SOSss == 2) //predictor selection 2: above
lPredA = SOFxdim - 1;
else if (SOSss == 3) //predictor selection 3: above+left
lPredA = SOFxdim;
else if ((SOSss == 4) || (SOSss == 5)) { //these use left, above and above+left WEIGHT LEFT
lPredA = 0; //Ra left
lPredB = SOFxdim - 1; //Rb directly above
lPredC = SOFxdim; //Rc UpperLeft:above and to the left
} else if (SOSss == 6) { //also use left, above and above+left, WEIGHT ABOVE
lPredB = 0;
lPredA = SOFxdim - 1; //Rb directly above
lPredC = SOFxdim; //Rc UpperLeft:above and to the left
} else
lPredA = 0; //Ra: directly to left)
if (SOFprecision > 8) { //start - 16 bit data
*bits = 16;
int lPx = -1; //pixel position
int lPredicted = 1 << (SOFprecision - 1 - SOSpttrans);
lImgRA8 = (unsigned char *)malloc(lItems * 2);
uint16_t *lImgRA16 = (uint16_t *)lImgRA8;
for (int i = 0; i < lItems; i++)
lImgRA16[i] = 0; //zero array
int frame = 1;
for (int lIncX = 1; lIncX <= SOFxdim; lIncX++) { //for first row - here we ALWAYS use LEFT as predictor
lPx++; //writenext voxel
if (lIncX > 1)
lPredicted = lImgRA16[lPx - 1];
lImgRA16[lPx] = lPredicted + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[frame]);
}
for (int lIncY = 2; lIncY <= SOFydim; lIncY++) { //for all subsequent rows
lPx++; //write next voxel
lPredicted = lImgRA16[lPx - SOFxdim]; //use ABOVE
lImgRA16[lPx] = lPredicted + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[frame]);
if (SOSss == 4) {
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
lPredicted = lImgRA16[lPx - lPredA] + lImgRA16[lPx - lPredB] - lImgRA16[lPx - lPredC];
lPx++; //writenext voxel
lImgRA16[lPx] = lPredicted + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[frame]);
} //for lIncX
} else if ((SOSss == 5) || (SOSss == 6)) {
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
lPredicted = lImgRA16[lPx - lPredA] + ((lImgRA16[lPx - lPredB] - lImgRA16[lPx - lPredC]) >> 1);
lPx++; //writenext voxel
lImgRA16[lPx] = lPredicted + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[frame]);
} //for lIncX
} else if (SOSss == 7) {
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
lPx++; //writenext voxel
lPredicted = (lImgRA16[lPx - 1] + lImgRA16[lPx - SOFxdim]) >> 1;
lImgRA16[lPx] = lPredicted + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[frame]);
} //for lIncX
} else { //SOSss 1,2,3 read single values
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
lPredicted = lImgRA16[lPx - lPredA];
lPx++; //writenext voxel
lImgRA16[lPx] = lPredicted + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[frame]);
} //for lIncX
} // if..else possible predictors
} //for lIncY
} else if (SOFnf == 3) { //if 16-bit data; else 8-bit 3 frames
*bits = 8;
lImgRA8 = (unsigned char *)malloc(lItems);
int lPx[kmaxFrames + 1], lPredicted[kmaxFrames + 1]; //pixel position
for (int f = 1; f <= SOFnf; f++) {
lPx[f] = ((f - 1) * (SOFxdim * SOFydim)) - 1;
lPredicted[f] = 1 << (SOFprecision - 1 - SOSpttrans);
}
for (int i = 0; i < lItems; i++)
lImgRA8[i] = 255; //zero array
for (int lIncX = 1; lIncX <= SOFxdim; lIncX++) { //for first row - here we ALWAYS use LEFT as predictor
for (int f = 1; f <= SOFnf; f++) {
lPx[f]++; //writenext voxel
if (lIncX > 1)
lPredicted[f] = lImgRA8[lPx[f] - 1];
lImgRA8[lPx[f]] = lPredicted[f] + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[f]);
}
} //first row always predicted by LEFT
for (int lIncY = 2; lIncY <= SOFydim; lIncY++) { //for all subsequent rows
for (int f = 1; f <= SOFnf; f++) {
lPx[f]++; //write next voxel
lPredicted[f] = lImgRA8[lPx[f] - SOFxdim]; //use ABOVE
lImgRA8[lPx[f]] = lPredicted[f] + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[f]);
} //first column of row always predicted by ABOVE
if (SOSss == 4) {
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
for (int f = 1; f <= SOFnf; f++) {
lPredicted[f] = lImgRA8[lPx[f] - lPredA] + lImgRA8[lPx[f] - lPredB] - lImgRA8[lPx[f] - lPredC];
lPx[f]++; //writenext voxel
lImgRA8[lPx[f]] = lPredicted[f] + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[f]);
}
} //for lIncX
} else if ((SOSss == 5) || (SOSss == 6)) {
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
for (int f = 1; f <= SOFnf; f++) {
lPredicted[f] = lImgRA8[lPx[f] - lPredA] + ((lImgRA8[lPx[f] - lPredB] - lImgRA8[lPx[f] - lPredC]) >> 1);
lPx[f]++; //writenext voxel
lImgRA8[lPx[f]] = lPredicted[f] + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[f]);
}
} //for lIncX
} else if (SOSss == 7) {
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
for (int f = 1; f <= SOFnf; f++) {
lPx[f]++; //writenext voxel
lPredicted[f] = (lImgRA8[lPx[f] - 1] + lImgRA8[lPx[f] - SOFxdim]) >> 1;
lImgRA8[lPx[f]] = lPredicted[f] + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[f]);
}
} //for lIncX
} else { //SOSss 1,2,3 read single values
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
for (int f = 1; f <= SOFnf; f++) {
lPredicted[f] = lImgRA8[lPx[f] - lPredA];
lPx[f]++; //writenext voxel
lImgRA8[lPx[f]] = lPredicted[f] + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[f]);
}
} //for lIncX
} // if..else possible predictors
} //for lIncY
} else { //if 8-bit data 3frames; else 8-bit 1 frames
*bits = 8;
lImgRA8 = (unsigned char *)malloc(lItems);
int lPx = -1; //pixel position
int lPredicted = 1 << (SOFprecision - 1 - SOSpttrans);
for (int i = 0; i < lItems; i++)
lImgRA8[i] = 0; //zero array
for (int lIncX = 1; lIncX <= SOFxdim; lIncX++) { //for first row - here we ALWAYS use LEFT as predictor
lPx++; //writenext voxel
if (lIncX > 1)
lPredicted = lImgRA8[lPx - 1];
int dx = decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[1]);
lImgRA8[lPx] = lPredicted + dx;
}
for (int lIncY = 2; lIncY <= SOFydim; lIncY++) { //for all subsequent rows
lPx++; //write next voxel
lPredicted = lImgRA8[lPx - SOFxdim]; //use ABOVE
lImgRA8[lPx] = lPredicted + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[1]);
if (SOSss == 4) {
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
lPredicted = lImgRA8[lPx - lPredA] + lImgRA8[lPx - lPredB] - lImgRA8[lPx - lPredC];
lPx++; //writenext voxel
lImgRA8[lPx] = lPredicted + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[1]);
} //for lIncX
} else if ((SOSss == 5) || (SOSss == 6)) {
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
lPredicted = lImgRA8[lPx - lPredA] + ((lImgRA8[lPx - lPredB] - lImgRA8[lPx - lPredC]) >> 1);
lPx++; //writenext voxel
lImgRA8[lPx] = lPredicted + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[1]);
} //for lIncX
} else if (SOSss == 7) {
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
lPx++; //writenext voxel
lPredicted = (lImgRA8[lPx - 1] + lImgRA8[lPx - SOFxdim]) >> 1;
lImgRA8[lPx] = lPredicted + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[1]);
} //for lIncX
} else { //SOSss 1,2,3 read single values
for (int lIncX = 2; lIncX <= SOFxdim; lIncX++) {
lPredicted = lImgRA8[lPx - lPredA];
lPx++; //writenext voxel
lImgRA8[lPx] = lPredicted + decodePixelDifference(lRawRA, &lRawPos, &lCurrentBitPos, l[1]);
} //for lIncX
} // if..else possible predictors
} //for lIncY
} //if 16bit else 8bit
free(lRawRA);
*dimX = SOFxdim;
*dimY = SOFydim;
*frames = SOFnf;
if (verbose)
printMessage("JPEG ends %ld@%ld\n", lRawPos, lRawPos + skipBytes);
return lImgRA8;
} // decode_JPEG_SOF_0XC3()