1 /*******************************************************************************
2 **
3 ** Photivo
4 **
5 ** Copyright (C) 2008,2009 Jos De Laender <jos.de_laender@telenet.be>
6 ** Copyright (C) 2009-2012 Michael Munzert <mail@mm-log.com>
7 ** Copyright (C) 2011 Bernd Schoeler <brjohn@brother-john.net>
8 **
9 ** This file is part of Photivo.
10 **
11 ** Photivo is free software: you can redistribute it and/or modify
12 ** it under the terms of the GNU General Public License version 3
13 ** as published by the Free Software Foundation.
14 **
15 ** Photivo is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ** GNU General Public License for more details.
19 **
20 ** You should have received a copy of the GNU General Public License
21 ** along with Photivo. If not, see <http://www.gnu.org/licenses/>.
22 **
23 *******************************************************************************/
24 /*
25 ** This is basically the translation into a more or less C++ object of
26 ** dcraw.c -- Dave Coffin's raw photo decoder
27 ** Copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net
28 **
29 *******************************************************************************/
30
31 #include "ptDcRaw.h"
32
33 #include "ptDefines.h"
34 #include "ptError.h"
35 #include "ptConstants.h"
36 #include "ptCalloc.h"
37
38 #include <cassert>
39
40 #define NO_JASPER
41 #ifndef NO_JASPER
42 #include <jasper/jasper.h>
43 #endif
44
45 // Macro fix for explicit fread returnvalue check.
46 #define ptfread(ptr,size,n,stream) \
47 { \
48 size_t RV = fread(ptr,size,n,stream); \
49 if (RV != (size_t) n) assert(!ferror(stream)); \
50 }
51 #define ptfwrite(ptr,size,n,stream) \
52 { \
53 size_t RV = fwrite(ptr,size,n,stream); \
54 assert(RV == (size_t) n); \
55 }
56 #define ptfscanf(file,format,arg) \
57 { \
58 int RV = fscanf(file,format,arg); \
59 assert (RV == 1); \
60 }
61 #define ptfgets(str,num,file) \
62 { \
63 char* RV = fgets(str,num,file); \
64 assert (RV); \
65 }
66
VAppend(TImage8RawData & AVector,char * AArray,const int ALength)67 inline void VAppend(TImage8RawData &AVector, char* AArray, const int ALength) {
68 char* hEnd = AArray + ALength * sizeof(char);
69 AVector.insert(AVector.end(), AArray, hEnd);
70 }
71
72 // The class.
73 #define CLASS ptDcRaw::
ptDcRaw()74 CLASS ptDcRaw() {
75 //printf("(%s,%d) '%s'\n",__FILE__,__LINE__,__PRETTY_FUNCTION__);
76
77 // This were the original global variables initialized.
78 // Now moved into constructor.
79 // All m_UserSetting* are obviously ,uh, usersettings
80 // that were done via the command line parameters.
81 m_UserSetting_ShotSelect=0;
82 m_UserSetting_MaxMultiplier=0;
83 m_UserSetting_Multiplier[0]=0;
84 m_UserSetting_Multiplier[1]=0;
85 m_UserSetting_Multiplier[2]=0;
86 m_UserSetting_Multiplier[3]=0;
87 m_UserSetting_HalfSize=0;
88 m_UserSetting_HotpixelReduction=0;
89 m_UserSetting_BayerDenoise=0;
90 m_UserSetting_CfaLineDn=0;
91 m_UserSetting_GreenEquil=0;
92 m_UserSetting_CaCorrect=0;
93 m_UserSetting_CaRed=0;
94 m_UserSetting_CaBlue=0;
95 m_UserSetting_AutoWb=0;
96 m_UserSetting_CameraWb=0;
97 m_UserSetting_CameraMatrix=-1;
98 m_UserSetting_GreyBox[0] = 0;
99 m_UserSetting_GreyBox[1] = 0;
100 m_UserSetting_GreyBox[2] = 0xFFFF;
101 m_UserSetting_GreyBox[3] = 0xFFFF;
102 m_UserSetting_photivo_ClipMode = ptClipMode_Clip;
103 m_UserSetting_photivo_ClipParameter = 0;
104 m_UserSetting_Quality = 3;
105 m_UserSetting_BlackPoint = -1;
106 m_UserSetting_Saturation = -1;
107 m_UserSetting_InputFileName = NULL;
108 m_UserSetting_DetailView = 0;
109 m_UserSetting_DetailViewCropX = 0;
110 m_UserSetting_DetailViewCropY = 0;
111 m_UserSetting_DetailViewCropW = 0;
112 m_UserSetting_DetailViewCropH = 0;
113 m_UserSetting_BadPixelsFileName = NULL;
114 m_UserSetting_DarkFrameFileName = NULL;
115 m_UserSetting_AdjustMaximum = 0;
116 m_UserSetting_DenoiseThreshold = 0;
117 m_UserSetting_InterpolationPasses = 0;
118 m_UserSetting_MedianPasses = 0;
119 m_UserSetting_ESMedianPasses = 0;
120
121
122 // Safety settings to have NULL on uninitialized images.
123 m_Image = NULL;
124 m_Image_AfterPhase1 = NULL;
125 m_Image_AfterPhase2 = NULL;
126 m_Image_AfterPhase3 = NULL;
127 m_Image_AfterPhase4 = NULL;
128
129 // Some other pointers that are in a dynamic environment better NULL.
130 m_MetaData = NULL;
131 m_InputFile = NULL;
132
133 m_Thumb.clear();
134 ResetNonUserSettings();
135 }
136
137 ////////////////////////////////////////////////////////////////////////////////
138 //
139 // Destructor
140 // Deallocate everything dynamic.
141 //
142 ////////////////////////////////////////////////////////////////////////////////
143
~ptDcRaw()144 CLASS ~ptDcRaw() {
145
146 //printf("(%s,%d) '%s'\n",__FILE__,__LINE__,__PRETTY_FUNCTION__);
147
148 FREE(m_UserSetting_InputFileName);
149 FREE(m_UserSetting_BadPixelsFileName);
150 FREE(m_UserSetting_DarkFrameFileName);
151 FREE(m_Image);
152 FREE(m_Image_AfterPhase1);
153 FREE(m_Image_AfterPhase2);
154 FREE(m_Image_AfterPhase3);
155 FCLOSE(m_InputFile);
156 FREE(m_MetaData);
157 }
158
159 ////////////////////////////////////////////////////////////////////////////////
160 //
161 // ResetNonUserSettings
162 // Reset all variables except user settings.
163 // This is for second entry support.
164 //
165 ////////////////////////////////////////////////////////////////////////////////
166
ResetNonUserSettings()167 void CLASS ResetNonUserSettings() {
168 // Safety settings to have NULL on uninitialized images.
169 // And freeing the underlying memory (which was long time a leak !)
170 // FREE(NULL) is safe, so the beginsituation is fine too.
171 // FREE implies setting of the pointer to NULL
172 FREE(m_Image);
173 FREE(m_Image_AfterPhase1);
174 FREE(m_Image_AfterPhase2);
175 FREE(m_Image_AfterPhase3);
176 FREE(m_Image_AfterPhase4);
177
178 // Some other pointers that are in a dynamic environment better NULL.
179 // Same remarks as above.
180 FREE(m_MetaData);
181 FCLOSE(m_InputFile);
182
183 // This was originally in the identify code, but which is called
184 // anyway in the beginning. So this is simply global initialization like
185 // anything else.
186
187 m_Tiff_Flip = m_Flip = -1; /* 0 is valid, so -1 is unknown */
188 m_Filters = (unsigned)(-1); // hack not to change dcraw.
189 m_RawHeight = m_RawWidth = m_Fuji_Width = m_IsFuji = fuji_layout = cr2_slice[0] = 0;
190 m_WhiteLevel = m_Height = m_Width = m_TopMargin = m_LeftMargin = 0;
191 m_ColorDescriptor[0] = m_Description[0] = m_Artist[0] = m_CameraMake[0] = m_CameraModel[0] = m_CameraModelBis[0] = 0;
192 m_IsoSpeed = m_Shutter = m_Aperture = m_FocalLength = unique_id = 0;
193 m_Tiff_NrIFDs = 0;
194 memset (m_Tiff_IFD, 0, sizeof m_Tiff_IFD);
195 memset (white, 0, sizeof white);
196 m_ThumbOffset = m_ThumbLength = m_ThumbWidth = m_ThumbHeight = 0;
197 m_LoadRawFunction = m_ThumbLoadRawFunction = 0;
198 m_WriteThumb = &CLASS jpeg_thumb;
199 m_Data_Offset = m_MetaLength = m_Tiff_bps = m_Tiff_Compress = 0;
200 m_Kodak_cbpp = zero_after_ff = m_DNG_Version = m_Load_Flags = 0;
201 m_TimeStamp = m_ShotOrder = m_Tiff_Samples = m_BlackLevel = m_IsFoveon = 0;
202 for (int k=0; k<8; k++) m_CBlackLevel[k] = 0;
203 m_MixGreen = m_ProfileLength = data_error = m_ZeroIsBad = 0;
204 m_PixelAspect = m_IsRaw = m_RawColor = 1; m_RawColorPhotivo = 0;
205 m_TileWidth = m_TileLength = 0;
206 m_Raw_Image = 0;
207 memset (m_Mask, 0, sizeof m_Mask);
208 for (int i=0; i < 4; i++) {
209 short c;
210 ASSIGN(m_CameraMultipliers[i], i == 1);
211 ASSIGN(m_PreMultipliers[i], i < 3);
212 ASSIGN(m_D65Multipliers[i], i < 3);
213 for (c=0; c<3; c++) m_cmatrix[c][i] = 0;
214 for (c=0; c<3; c++) m_MatrixCamRGBToSRGB[c][i] = c == i;
215 }
216 m_Colors = 3;
217 for (int i=0; i < 0x10000; i++) m_Curve[i] = i;
218
219 m_Gamma[0] = 0.45;
220 m_Gamma[1] = 4.50;
221 m_Gamma[2] = 0;
222 m_Gamma[3] = 0;
223 m_Gamma[4] = 0;
224 m_Gamma[5] = 0;
225
226 m_getbithuff_bitbuf=0;
227 m_getbithuff_reset=0;
228 m_getbithuff_vbits=0;
229 m_ph1_bithuffbitbuf=0;
230 m_ph1_bithuffvbits=0;
231 for (int i = 0; i < 0x4000; i++) m_pana_bits_buf[i] = 0;
232 m_pana_bits_vbits = 0;
233 for (int i = 0; i < 4096; i++) jpeg_buffer[i] = 0;
234 for (int i = 0; i < 128; i++) m_sony_decrypt_pad[i] = 0;
235 m_sony_decrypt_p = 0;
236 for (int i = 0; i < 1024; i++) m_foveon_decoder_huff[i] = 0;
237
238 for (int i = 0; i < 4; i++) {
239 for (int j = 0; j < 3; j++) {
240 MatrixXYZToCam[i][j] = 0.0;
241 }
242 }
243
244 ToCamFunctionInited = 0;
245 for (int i = 0; i < 0x20000; i++) ToLABFunctionTable[i] = 0.0;
246 ToLABFunctionInited = 0;
247
248 for (int i = 0; i < 3; i++) {
249 for (int j = 0; j < 4; j++) {
250 MatrixCamToXYZ[i][j] = 0.0;
251 }
252 }
253
254 }
255
256 /*
257 In order to inline this calculation, I make the risky
258 assumption that all filter patterns can be described
259 by a repeating pattern of eight rows and two columns
260
261 Do not use the FC or BAYER macros with the Leaf CatchLight,
262 because its pattern is 16x16, not 2x8.
263
264 Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
265
266 PowerShot 600 PowerShot A50 PowerShot Pro70 Pro90 & G1
267 0xe1e4e1e4: 0x1b4e4b1e: 0x1e4b4e1b: 0xb4b4b4b4:
268
269 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
270 0 G M G M G M 0 C Y C Y C Y 0 Y C Y C Y C 0 G M G M G M
271 1 C Y C Y C Y 1 M G M G M G 1 M G M G M G 1 Y C Y C Y C
272 2 M G M G M G 2 Y C Y C Y C 2 C Y C Y C Y
273 3 C Y C Y C Y 3 G M G M G M 3 G M G M G M
274 4 C Y C Y C Y 4 Y C Y C Y C
275 PowerShot A5 5 G M G M G M 5 G M G M G M
276 0x1e4e1e4e: 6 Y C Y C Y C 6 C Y C Y C Y
277 7 M G M G M G 7 M G M G M G
278 0 1 2 3 4 5
279 0 C Y C Y C Y
280 1 G M G M G M
281 2 C Y C Y C Y
282 3 M G M G M G
283
284 All RGB cameras use one of these Bayer grids:
285
286 0x16161616: 0x61616161: 0x49494949: 0x94949494:
287
288 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
289 0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G
290 1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B
291 2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G
292 3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B
293 */
294
295 #define RAW(row,col) \
296 m_Raw_Image[(row)*m_RawWidth+(col)]
297
298 #define FC(row,col) \
299 (m_Filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
300
301 #define BAYER(row,col) \
302 m_Image[(row)*m_Width + (col)][FC(row,col)]
303 // old: m_Image[((row) >> m_Shrink)*m_OutWidth + ((col) >> m_Shrink)][FC(row,col)]
304
305 #define BAYER2(row,col) \
306 m_Image[(row)*m_Width + (col)][fcol(row,col)]
307
fcol(int row,int col)308 int CLASS fcol (int row, int col)
309 {
310 static const char filter[16][16] =
311 { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
312 { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
313 { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
314 { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
315 { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
316 { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
317 { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
318 { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
319 { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
320 { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
321 { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
322 { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
323 { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
324 { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
325 { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
326 { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
327 static const char filter2[6][6] =
328 { { 1,1,0,1,1,2 },
329 { 1,1,2,1,1,0 },
330 { 2,0,1,0,2,1 },
331 { 1,1,2,1,1,0 },
332 { 1,1,0,1,1,2 },
333 { 0,2,1,2,0,1 } };
334
335 if (m_Filters == 1) return filter[(row+m_TopMargin)&15][(col+m_LeftMargin)&15];
336 if (m_Filters == 2) return filter2[(row+6) % 6][(col+6) % 6];
337 return FC(row,col);
338 }
339
340 #ifndef __GLIBC__
my_memmem(char * haystack,size_t haystacklen,char * neepte,size_t neeptelen)341 char* CLASS my_memmem (char *haystack, size_t haystacklen,
342 char *neepte, size_t neeptelen)
343 {
344 char *c;
345 for (c = haystack; c <= haystack + haystacklen - neeptelen; c++)
346 if (!memcmp (c, neepte, neeptelen))
347 return c;
348 return 0;
349 }
350 #define memmem my_memmem
351 #endif
352
353 float rgb_cam[3][4];
354 const double xyz_rgb[3][3] = { /* XYZ from RGB */
355 { 0.412453, 0.357580, 0.180423 },
356 { 0.212671, 0.715160, 0.072169 },
357 { 0.019334, 0.119193, 0.950227 } };
358 const float d65_white[3] = { 0.950456, 1, 1.088754 };
359
360 // Now everything importent is set up, so we can include external demosaicers
361 #include "dcb/dcb_demosaicing.c"
362 #include "dcb/dcb_demosaicing_old.c"
363 #include "vcd/ahd_interpolate_mod.c"
364 #include "vcd/ahd_partial_interpolate.c"
365 #include "vcd/refinement.c"
366 #include "vcd/vcd_interpolate.c"
367 #include "vcd/es_median_filter.c"
368 #include "vcd/median_filter_new.c"
369 #include "perfectraw/lmmse_interpolate.c"
370 #include "rawtherapee/amaze_interpolate.c"
371 #include "rawtherapee/cfa_line_dn.c"
372 #include "rawtherapee/ca_correct.c"
373 #include "rawtherapee/green_equil.c"
374
merror(void * ptr,const char * where)375 void CLASS merror (void *ptr, const char *where)
376 {
377 if (ptr) return;
378 fprintf (stderr,_("%s: Out of memory in %s\n"), m_UserSetting_InputFileName, where);
379 longjmp (m_Failure, 1);
380 }
381
derror()382 void CLASS derror()
383 {
384 if (!data_error) {
385 fprintf (stderr, "%s: ", m_UserSetting_InputFileName);
386 if (feof(m_InputFile))
387 fprintf (stderr,_("Unexpected end of file\n"));
388 else
389 //fprintf (stderr,_("Corrupt data near 0x%lx\n"), (int64_t) ftell(m_InputFile));
390 fprintf (stderr,_("Corrupt data near 0x%lx\n"), (long unsigned int) ftell(m_InputFile));
391 }
392 data_error++;
393 }
394
sget2(uint8_t * s)395 uint16_t CLASS sget2 (uint8_t *s)
396 {
397 if (m_ByteOrder == 0x4949) /* "II" means little-endian */
398 return s[0] | s[1] << 8;
399 else /* "MM" means big-endian */
400 return s[0] << 8 | s[1];
401 }
402
get2()403 uint16_t CLASS get2()
404 {
405 uint8_t str[2] = { 0xff,0xff };
406 ptfread (str, 1, 2, m_InputFile);
407 return sget2(str);
408 }
409
sget4(uint8_t * s)410 unsigned CLASS sget4 (uint8_t *s)
411 {
412 if (m_ByteOrder == 0x4949)
413 return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
414 else
415 return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
416 }
417 #define sget4(s) sget4((uint8_t *)s)
418
get4()419 unsigned CLASS get4()
420 {
421 uint8_t str[4] = { 0xff,0xff,0xff,0xff };
422 ptfread (str, 1, 4, m_InputFile);
423 return sget4(str);
424 }
425
getint(int type)426 unsigned CLASS getint (int type)
427 {
428 return type == 3 ? get2() : get4();
429 }
430
int_to_float(int i)431 float CLASS int_to_float (int i)
432 {
433 union { int i; float f; } u;
434 u.i = i;
435 return u.f;
436 }
437
getreal(int type)438 double CLASS getreal (int type)
439 {
440 union { char c[8]; double d; } u;
441 int i, rev;
442
443 switch (type) {
444 case 3: return (unsigned short) get2();
445 case 4: return (unsigned int) get4();
446 case 5: u.d = (unsigned int) get4();
447 return u.d / (unsigned int) get4();
448 case 8: return (signed short) get2();
449 case 9: return (signed int) get4();
450 case 10: u.d = (signed int) get4();
451 return u.d / (signed int) get4();
452 case 11: return int_to_float (get4());
453 case 12:
454 rev = 7 * ((m_ByteOrder == 0x4949) == (ntohs(0x1234) == 0x1234));
455 for (i=0; i < 8; i++)
456 u.c[i ^ rev] = fgetc(m_InputFile);
457 return u.d;
458 default: return fgetc(m_InputFile);
459 }
460 }
461
read_shorts(uint16_t * pixel,int count)462 void CLASS read_shorts (uint16_t *pixel, int count)
463 {
464 if (fread (pixel, 2, count, m_InputFile) < (size_t) count) derror();
465 if ((m_ByteOrder == 0x4949) == (ntohs(0x1234) == 0x1234))
466 swab ((char *)pixel, (char *)pixel, count*2);
467 }
468
469 /* -> 1438
470 void CLASS canon_black (double dark[2], int nblack)
471 {
472 int c, diff, row, col;
473
474 if (!nblack) return;
475 for (c=0; c<2; c++) dark[c] /= nblack >> 1;
476 if ((diff = (int)(dark[0] - dark[1])))
477 for (row=0; row < m_Height; row++)
478 for (col=1; col < m_Width; col+=2)
479 BAYER(row,col) += diff;
480 dark[1] += diff;
481 m_BlackLevel = (unsigned)((dark[0] + dark[1] + 1) / 2);
482 }
483 */
484
canon_600_fixed_wb(int temp)485 void CLASS canon_600_fixed_wb (int temp)
486 {
487 static const short mul[4][5] = {
488 { 667, 358,397,565,452 },
489 { 731, 390,367,499,517 },
490 { 1119, 396,348,448,537 },
491 { 1399, 485,431,508,688 } };
492 int lo, hi, i;
493 float frac=0;
494
495 for (lo=4; --lo; )
496 if (*mul[lo] <= temp) break;
497 for (hi=0; hi < 3; hi++)
498 if (*mul[hi] >= temp) break;
499 if (lo != hi)
500 frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]);
501 for (i=1; i < 5; i++)
502 ASSIGN(m_D65Multipliers[i-1],1/(frac * mul[hi][i] + (1-frac) * mul[lo][i]));
503 }
504
505 /* Return values: 0 = white 1 = near white 2 = not white */
canon_600_color(int ratio[2],int mar)506 int CLASS canon_600_color (int ratio[2], int mar)
507 {
508 int clipped=0, target, miss;
509
510 if (flash_used) {
511 if (ratio[1] < -104)
512 { ratio[1] = -104; clipped = 1; }
513 if (ratio[1] > 12)
514 { ratio[1] = 12; clipped = 1; }
515 } else {
516 if (ratio[1] < -264 || ratio[1] > 461) return 2;
517 if (ratio[1] < -50)
518 { ratio[1] = -50; clipped = 1; }
519 if (ratio[1] > 307)
520 { ratio[1] = 307; clipped = 1; }
521 }
522 target = flash_used || ratio[1] < 197
523 ? -38 - (398 * ratio[1] >> 10)
524 : -123 + (48 * ratio[1] >> 10);
525 if (target - mar <= ratio[0] &&
526 target + 20 >= ratio[0] && !clipped) return 0;
527 miss = target - ratio[0];
528 if (abs(miss) >= mar*4) return 2;
529 if (miss < -20) miss = -20;
530 if (miss > mar) miss = mar;
531 ratio[0] = target - miss;
532 return 1;
533 }
534
canon_600_auto_wb()535 void CLASS canon_600_auto_wb()
536 {
537 int mar, row, col, i, j, st, count[] = { 0,0 };
538 int test[8], total[2][8], ratio[2][2], stat[2];
539
540 memset (&total, 0, sizeof total);
541 i = int ( canon_ev + 0.5 );
542 if (i < 10) mar = 150;
543 else if (i > 12) mar = 20;
544 else mar = 280 - 20 * i;
545 if (flash_used) mar = 80;
546 for (row=14; row < m_Height-14; row+=4)
547 for (col=10; col < m_Width; col+=2) {
548 for (i=0; i < 8; i++)
549 test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] =
550 BAYER(row+(i >> 1),col+(i & 1));
551 for (i=0; i < 8; i++)
552 if (test[i] < 150 || test[i] > 1500) goto next;
553 for (i=0; i < 4; i++)
554 if (abs(test[i] - test[i+4]) > 50) goto next;
555 for (i=0; i < 2; i++) {
556 for (j=0; j < 4; j+=2)
557 ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j];
558 stat[i] = canon_600_color (ratio[i], mar);
559 }
560 if ((st = stat[0] | stat[1]) > 1) goto next;
561 for (i=0; i < 2; i++)
562 if (stat[i])
563 for (j=0; j < 2; j++)
564 test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10;
565 for (i=0; i < 8; i++)
566 total[st][i] += test[i];
567 count[st]++;
568 next: ;
569 }
570 if (count[0] | count[1]) {
571 st = count[0]*200 < count[1];
572 for (i=0; i < 4; i++)
573 ASSIGN(m_D65Multipliers[i], 1.0 / (total[st][i] + total[st][i+4]));
574 }
575 }
576
canon_600_coeff()577 void CLASS canon_600_coeff()
578 {
579 static const short table[6][12] = {
580 { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
581 { -1203,1715,-1136,1648, 1388,-876,267,245, -1641,2153,3921,-3409 },
582 { -615,1127,-1563,2075, 1437,-925,509,3, -756,1268,2519,-2007 },
583 { -190,702,-1886,2398, 2153,-1641,763,-251, -452,964,3040,-2528 },
584 { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
585 { -807,1319,-1785,2297, 1388,-876,769,-257, -230,742,2067,-1555 } };
586 int t=0, i, c;
587 float mc, yc;
588
589 mc = VALUE(m_D65Multipliers[1]) / VALUE(m_D65Multipliers[2]);
590 yc = VALUE(m_D65Multipliers[3]) / VALUE(m_D65Multipliers[2]);
591 if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1;
592 if (mc > 1.28 && mc <= 2) {
593 if (yc < 0.8789) t=3;
594 else if (yc <= 2) t=4;
595 }
596 if (flash_used) t=5;
597 for (m_RawColor = i=0; i < 3; i++)
598 for (c=0; c < m_Colors; c++)
599 m_MatrixCamRGBToSRGB[i][c] = table[t][i*4 + c] / 1024.0;
600 }
601
canon_600_load_raw()602 void CLASS canon_600_load_raw()
603 {
604 uint8_t data[1120], *dp;
605 uint16_t *pix;
606 int irow, row;
607
608 for (irow=row=0; irow < m_Height; irow++) {
609 if (fread (data, 1, 1120, m_InputFile) < 1120) derror();
610 pix = m_Raw_Image + row*m_RawWidth;
611 for (dp=data; dp < data+1120; dp+=10, pix+=8) {
612 pix[0] = (dp[0] << 2) + (dp[1] >> 6 );
613 pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
614 pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
615 pix[3] = (dp[4] << 2) + (dp[1] & 3);
616 pix[4] = (dp[5] << 2) + (dp[9] & 3);
617 pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
618 pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
619 pix[7] = (dp[8] << 2) + (dp[9] >> 6 );
620 }
621 if ((row+=2) > m_Height) row = 1;
622 }
623 }
624
canon_600_correct()625 void CLASS canon_600_correct()
626 {
627 int row, col, val;
628 static const short mul[4][2] =
629 { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
630
631 for (row=0; row < m_Height; row++)
632 for (col=0; col < m_Width; col++) {
633 if ((val = BAYER(row,col) - m_BlackLevel) < 0) val = 0;
634 val = val * mul[row & 3][col & 1] >> 9;
635 BAYER(row,col) = val;
636 }
637 canon_600_fixed_wb(1311);
638 canon_600_auto_wb();
639 canon_600_coeff();
640 m_WhiteLevel = (0x3ff - m_BlackLevel) * 1109 >> 9;
641 m_BlackLevel = 0;
642 }
643
canon_s2is()644 int CLASS canon_s2is()
645 {
646 unsigned row;
647
648 for (row=0; row < 100; row++) {
649 fseek (m_InputFile, row*3340 + 3284, SEEK_SET);
650 if (getc(m_InputFile) > 15) return 1;
651 }
652 return 0;
653 }
654
655 /*
656 getbits(-1) initializes the buffer
657 getbits(n) where 0 <= n <= 25 returns an n-bit integer
658 */
getbithuff(int nbits,uint16_t * huff)659 unsigned CLASS getbithuff(int nbits,uint16_t *huff)
660 {
661 // unsigned c;
662 int c;
663
664 if (nbits == -1)
665 return m_getbithuff_bitbuf = m_getbithuff_vbits = m_getbithuff_reset = 0;
666 if (nbits == 0 || m_getbithuff_vbits < 0) return 0;
667 while (!m_getbithuff_reset && m_getbithuff_vbits < nbits && (c = fgetc(m_InputFile)) != EOF &&
668 !(m_getbithuff_reset = zero_after_ff && c == 0xff && fgetc(m_InputFile))) {
669 m_getbithuff_bitbuf = (m_getbithuff_bitbuf << 8) + (uint8_t) c;
670 m_getbithuff_vbits += 8;
671 }
672 c = m_getbithuff_bitbuf << (32-m_getbithuff_vbits) >> (32-nbits);
673 if (huff) {
674 m_getbithuff_vbits -= huff[c] >> 8;
675 c = (uint8_t) huff[c];
676 } else
677 m_getbithuff_vbits -= nbits;
678 if (m_getbithuff_vbits < 0) derror();
679 return c;
680 }
681
682 #define getbits(n) getbithuff(n,0)
683 #define gethuff(h) getbithuff(*h,h+1)
684
685 /*
686 Construct a decode tree according the specification in *source.
687 The first 16 bytes specify how many codes should be 1-bit, 2-bit
688 3-bit, etc. Bytes after that are the leaf values.
689
690 For example, if the source is
691
692 { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
693 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
694
695 then the code is
696
697 00 0x04
698 010 0x03
699 011 0x05
700 100 0x06
701 101 0x02
702 1100 0x07
703 1101 0x01
704 11100 0x08
705 11101 0x09
706 11110 0x00
707 111110 0x0a
708 1111110 0x0b
709 1111111 0xff
710 */
make_decoder_ref(const uint8_t ** source)711 uint16_t * CLASS make_decoder_ref (const uint8_t **source)
712 {
713 int max, len, h, i, j;
714 const uint8_t *count;
715 uint16_t *huff;
716
717 count = (*source += 16) - 17;
718 for (max=16; max && !count[max]; max--) {} ;
719 huff = (uint16_t *) CALLOC (1 + (1 << max), sizeof *huff);
720 merror (huff, "make_decoder()");
721 huff[0] = max;
722 for (h=len=1; len <= max; len++)
723 for (i=0; i < count[len]; i++, ++*source)
724 for (j=0; j < 1 << (max-len); j++)
725 if (h <= 1 << max)
726 huff[h++] = len << 8 | **source;
727 return huff;
728 }
729
730
make_decoder(const uint8_t * source)731 uint16_t * CLASS make_decoder (const uint8_t *source)
732 {
733 return make_decoder_ref (&source);
734 }
735
crw_init_tables(unsigned table,uint16_t * huff[2])736 void CLASS crw_init_tables (unsigned table, uint16_t *huff[2])
737 {
738 static const uint8_t first_tree[3][29] = {
739 { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
740 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
741 { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0,
742 0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff },
743 { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0,
744 0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff },
745 };
746 static const uint8_t second_tree[3][180] = {
747 { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139,
748 0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08,
749 0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0,
750 0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42,
751 0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57,
752 0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9,
753 0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98,
754 0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6,
755 0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4,
756 0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7,
757 0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1,
758 0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64,
759 0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba,
760 0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4,
761 0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff },
762 { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140,
763 0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06,
764 0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32,
765 0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51,
766 0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26,
767 0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59,
768 0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9,
769 0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99,
770 0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85,
771 0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8,
772 0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a,
773 0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9,
774 0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8,
775 0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8,
776 0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff },
777 { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117,
778 0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08,
779 0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22,
780 0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34,
781 0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41,
782 0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48,
783 0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69,
784 0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8,
785 0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94,
786 0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a,
787 0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6,
788 0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62,
789 0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5,
790 0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3,
791 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff }
792 };
793 if (table > 2) table = 2;
794 huff[0] = make_decoder ( first_tree[table]);
795 huff[1] = make_decoder (second_tree[table]);
796 }
797
798 /*
799 Return 0 if the image starts with compressed data,
800 1 if it starts with uncompressed low-order bits.
801
802 In Canon compressed data, 0xff is always followed by 0x00.
803 */
canon_has_lowbits()804 int CLASS canon_has_lowbits()
805 {
806 uint8_t test[0x4000];
807 int ret=1, i;
808
809 fseek (m_InputFile, 0, SEEK_SET);
810 ptfread (test, 1, sizeof test, m_InputFile);
811 for (i=540; i < (int)(sizeof test) - 1; i++)
812 if (test[i] == 0xff) {
813 if (test[i+1]) return 1;
814 ret=0;
815 }
816 return ret;
817 }
818
canon_load_raw()819 void CLASS canon_load_raw()
820 {
821 uint16_t *pixel, *prow, *huff[2];
822 int nblocks, lowbits, i, c, row, r, save, val;
823 int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
824
825 crw_init_tables (m_Tiff_Compress,huff);
826 lowbits = canon_has_lowbits();
827 if (!lowbits) m_WhiteLevel = 0x3ff;
828 fseek (m_InputFile, 540 + lowbits*m_RawHeight*m_RawWidth/4, SEEK_SET);
829 zero_after_ff = 1;
830 getbits(-1);
831 for (row=0; row < m_RawHeight; row+=8) {
832 pixel = m_Raw_Image + row*m_RawWidth;
833 nblocks = MIN (8, m_RawHeight-row) * m_RawWidth >> 6;
834 for (block=0; block < nblocks; block++) {
835 memset (diffbuf, 0, sizeof diffbuf);
836 for (i=0; i < 64; i++ ) {
837 leaf = gethuff(huff[i>0]);
838 if (leaf == 0 && i) break;
839 if (leaf == 0xff) continue;
840 i += leaf >> 4;
841 len = leaf & 15;
842 if (len == 0) continue;
843 diff = getbits(len);
844 if ((diff & (1 << (len-1))) == 0)
845 diff -= (1 << len) - 1;
846 if (i < 64) diffbuf[i] = diff;
847 }
848 diffbuf[0] += carry;
849 carry = diffbuf[0];
850 for (i=0; i < 64; i++ ) {
851 if (pnum++ % m_RawWidth == 0)
852 base[0] = base[1] = 512;
853 if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10)
854 derror();
855 }
856 }
857 if (lowbits) {
858 save = ftell(m_InputFile);
859 fseek (m_InputFile, 26 + row*m_RawWidth/4, SEEK_SET);
860 for (prow=pixel, i=0; i < m_RawWidth*2; i++) {
861 c = fgetc(m_InputFile);
862 for (r=0; r < 8; r+=2, prow++) {
863 val = (*prow << 2) + ((c >> r) & 3);
864 if (m_RawWidth == 2672 && val < 512) val += 2;
865 *prow = val;
866 }
867 }
868 fseek (m_InputFile, save, SEEK_SET);
869 }
870 }
871 FREE(huff[0]);
872 FREE(huff[1]);
873 }
874
875 /*
876 Not a full implementation of Lossless JPEG, just
877 enough to decode Canon, Kodak and Adobe DNG images.
878 */
879 struct jhead {
880 int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
881 uint16_t *huff[6], *free[4], *row;
882 };
883
ljpeg_start(struct jhead * jh,int info_only)884 int CLASS ljpeg_start (struct jhead *jh, int info_only)
885 {
886 int c, tag, len;
887 uint8_t data[0x10000];
888 const uint8_t *dp;
889
890 memset (jh, 0, sizeof *jh);
891 jh->restart = INT_MAX;
892 ptfread (data, 2, 1, m_InputFile);
893 if (data[1] != 0xd8) return 0;
894 do {
895 ptfread (data, 2, 2, m_InputFile);
896 tag = data[0] << 8 | data[1];
897 len = (data[2] << 8 | data[3]) - 2;
898 if (tag <= 0xff00) return 0;
899 ptfread (data, 1, len, m_InputFile);
900 switch (tag) {
901 case 0xffc3:
902 jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
903 case 0xffc0:
904 jh->bits = data[0];
905 jh->high = data[1] << 8 | data[2];
906 jh->wide = data[3] << 8 | data[4];
907 jh->clrs = data[5] + jh->sraw;
908 if (len == 9 && !m_DNG_Version) getc(m_InputFile);
909 break;
910 case 0xffc4:
911 if (info_only) break;
912 for (dp = data; dp < data+len && (c = *dp++) < 4; )
913 jh->free[c] = jh->huff[c] = make_decoder_ref (&dp);
914 break;
915 case 0xffda:
916 jh->psv = data[1+data[0]*2];
917 jh->bits -= data[3+data[0]*2] & 15;
918 break;
919 case 0xffdd:
920 jh->restart = data[0] << 8 | data[1];
921 }
922 } while (tag != 0xffda);
923 if (info_only) return 1;
924 for (c=0;c<5;c++) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c];
925 if (jh->sraw) {
926 for (c=0;c<4;c++) jh->huff[2+c] = jh->huff[1];
927 for (c=0;c<(jh->sraw);c++) jh->huff[1+c] = jh->huff[0];
928 }
929 jh->row = (uint16_t *) CALLOC (jh->wide*jh->clrs, 4);
930 merror (jh->row, "ljpeg_start()");
931 return zero_after_ff = 1;
932 }
933
ljpeg_end(struct jhead * jh)934 void CLASS ljpeg_end (struct jhead *jh)
935 {
936 int c;
937 for(c=0;c<4;c++) if (jh->free[c]) FREE (jh->free[c]);
938 FREE (jh->row);
939 }
940
ljpeg_diff(uint16_t * huff)941 int CLASS ljpeg_diff (uint16_t *huff)
942 {
943 int len, diff;
944
945 len = gethuff(huff);
946
947 if (len == 16 && (!m_DNG_Version || m_DNG_Version >= 0x1010000))
948 return -32768;
949 diff = getbits(len);
950 if ((diff & (1 << (len-1))) == 0)
951 diff -= (1 << len) - 1;
952 return diff;
953 }
954
ljpeg_row(int jrow,struct jhead * jh)955 uint16_t * CLASS ljpeg_row (int jrow, struct jhead *jh)
956 {
957 int col, c, diff, pred, spred=0;
958 uint16_t mark=0, *row[3];
959
960 if (jrow * jh->wide % jh->restart == 0) {
961 for (c=0;c<6;c++) jh->vpred[c] = 1 << (jh->bits-1);
962 if (jrow) {
963 fseek(m_InputFile,-2,SEEK_CUR);
964 do mark = (mark << 8) + (c = fgetc(m_InputFile));
965 while (c != EOF && mark >> 4 != 0xffd);
966 }
967 getbits(-1);
968 }
969 for (c=0; c<3; c++) row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
970 for (col=0; col < jh->wide; col++)
971 for (c=0; c < jh->clrs; c++) {
972 diff = ljpeg_diff (jh->huff[c]);
973 if (jh->sraw && c <= jh->sraw && (col | c))
974 pred = spred;
975 else if (col) pred = row[0][-jh->clrs];
976 else pred = (jh->vpred[c] += diff) - diff;
977 if (jrow && col) switch (jh->psv) {
978 case 1: break;
979 case 2: pred = row[1][0]; break;
980 case 3: pred = row[1][-jh->clrs]; break;
981 case 4: pred = pred + row[1][0] - row[1][-jh->clrs]; break;
982 case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1); break;
983 case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1); break;
984 case 7: pred = (pred + row[1][0]) >> 1; break;
985 default: pred = 0;
986 }
987 if ((**row = pred + diff) >> jh->bits) derror();
988 if (c <= jh->sraw) spred = **row;
989 row[0]++; row[1]++;
990 }
991 return row[2];
992 }
993
lossless_jpeg_load_raw()994 void CLASS lossless_jpeg_load_raw()
995 {
996 int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0;
997 struct jhead jh;
998 uint16_t *rp;
999
1000 if (!ljpeg_start (&jh, 0)) return;
1001 jwide = jh.wide * jh.clrs;
1002
1003 TRACEKEYVALS("jh.high","%d",jh.high);
1004 TRACEKEYVALS("jwide","%d",jwide);
1005 for (jrow=0; jrow < jh.high; jrow++) {
1006 rp = ljpeg_row (jrow, &jh);
1007 if (m_Load_Flags & 1)
1008 row = jrow & 1 ? m_Height-1-jrow/2 : jrow/2;
1009 for (jcol=0; jcol < jwide; jcol++) {
1010 val = m_Curve[*rp++];
1011 if (cr2_slice[0]) {
1012 jidx = jrow*jwide + jcol;
1013 i = jidx / (cr2_slice[1]*jh.high);
1014 if ((j = i >= cr2_slice[0]))
1015 i = cr2_slice[0];
1016 jidx -= i * (cr2_slice[1]*jh.high);
1017 row = jidx / cr2_slice[1+j];
1018 col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
1019 }
1020 if (m_RawWidth == 3984 && (col -= 2) < 0)
1021 col += (row--,m_RawWidth);
1022 if (row >= 0) RAW(row,col) = val;
1023 if (++col >= m_RawWidth)
1024 col = (row++,0);
1025 }
1026 }
1027 ljpeg_end(&jh);
1028 // printf("TIEDELIE dark[0]:%f dark[1]:%f nblack:%d\n",dark[0],dark[1],nblack);
1029 }
1030
canon_sraw_load_raw()1031 void CLASS canon_sraw_load_raw()
1032 {
1033 struct jhead jh;
1034 short *rp=0, (*ip)[4];
1035 int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
1036 int v[3]={0,0,0}, ver, hue;
1037 char *cp;
1038
1039 if (!ljpeg_start (&jh, 0)) return;
1040 jwide = (jh.wide >>= 1) * jh.clrs;
1041
1042 for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
1043 scol = ecol;
1044 ecol += cr2_slice[1] * 2 / jh.clrs;
1045 if (!cr2_slice[0] || ecol > m_RawWidth-1) ecol = m_RawWidth & -2;
1046 for (row=0; row < m_Height; row += (jh.clrs >> 1) - 1) {
1047 ip = (short (*)[4]) m_Image + row*m_Width;
1048 for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
1049 if ((jcol %= jwide) == 0)
1050 rp = (short *) ljpeg_row (jrow++, &jh);
1051 if (col >= m_Width) continue;
1052 for (c=0; c< (jh.clrs-2); c++)
1053 ip[col + (c >> 1)*m_Width + (c & 1)][0] = rp[jcol+c];
1054 ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
1055 ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
1056 }
1057 }
1058 }
1059 for (cp=m_CameraModelBis; *cp && !isdigit(*cp); cp++) {};
1060 sscanf (cp, "%d.%d.%d", v, v+1, v+2);
1061 ver = (v[0]*1000 + v[1])*1000 + v[2];
1062 hue = (jh.sraw+1) << 2;
1063 if (unique_id >= 0x80000281 || (unique_id == 0x80000218 && ver > 1000006))
1064 hue = jh.sraw << 1;
1065 ip = (short (*)[4]) m_Image;
1066 rp = ip[0];
1067 for (row=0; row < m_Height; row++, ip+=m_Width) {
1068 if (row & (jh.sraw >> 1))
1069 for (col=0; col < m_Width; col+=2)
1070 for (c=1; c < 3; c++)
1071 if (row == m_Height-1) {
1072 ip[col][c] = ip[col-m_Width][c];
1073 } else {
1074 ip[col][c] = (ip[col-m_Width][c] + ip[col+m_Width][c] + 1) >> 1;
1075 }
1076 for (col=1; col < m_Width; col+=2)
1077 for (c=1; c < 3; c++)
1078 if (col == m_Width-1)
1079 ip[col][c] = ip[col-1][c];
1080 else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
1081 }
1082 for ( ; rp < ip[0]; rp+=4) {
1083 if (unique_id == 0x80000218 ||
1084 unique_id == 0x80000250 ||
1085 unique_id == 0x80000261 ||
1086 unique_id == 0x80000281 ||
1087 unique_id == 0x80000287) {
1088 rp[1] = (rp[1] << 2) + hue;
1089 rp[2] = (rp[2] << 2) + hue;
1090 pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 14);
1091 pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
1092 pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 14);
1093 } else {
1094 if (unique_id < 0x80000218) rp[0] -= 512;
1095 pix[0] = rp[0] + rp[2];
1096 pix[2] = rp[0] + rp[1];
1097 pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12);
1098 }
1099 for (c=0;c<3;c++) rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
1100 }
1101 ljpeg_end(&jh);
1102 m_WhiteLevel = 0x3fff;
1103 }
1104
adobe_copy_pixel(unsigned row,unsigned col,uint16_t ** rp)1105 void CLASS adobe_copy_pixel (unsigned row, unsigned col, uint16_t **rp)
1106 {
1107 int c;
1108
1109 if (m_IsRaw == 2 && m_UserSetting_ShotSelect) (*rp)++;
1110 if (m_Raw_Image) {
1111 if (row < m_RawHeight && col < m_RawWidth)
1112 RAW(row,col) = m_Curve[**rp];
1113 *rp += m_IsRaw;
1114 } else {
1115 if (row < m_Height && col < m_Width)
1116 for (c=0; c < (int32_t)m_Tiff_Samples; c++)
1117 m_Image[row*m_Width+col][c] = m_Curve[(*rp)[c]];
1118 *rp += m_Tiff_Samples;
1119 }
1120 if (m_IsRaw == 2 && m_UserSetting_ShotSelect) (*rp)--;
1121 }
1122
lossless_dng_load_raw()1123 void CLASS lossless_dng_load_raw()
1124 {
1125 unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
1126 struct jhead jh;
1127 uint16_t *rp;
1128
1129 while (trow < m_RawHeight) {
1130 save = ftell(m_InputFile);
1131 if (m_TileLength < INT_MAX)
1132 fseek (m_InputFile, get4(), SEEK_SET);
1133 if (!ljpeg_start (&jh, 0)) break;
1134 jwide = jh.wide;
1135 if (m_Filters) jwide *= jh.clrs;
1136 jwide /= m_IsRaw;
1137 for (row=col=jrow=0; jrow < (unsigned) jh.high; jrow++) {
1138 rp = ljpeg_row (jrow, &jh);
1139 for (jcol=0; jcol < jwide; jcol++) {
1140 adobe_copy_pixel (trow+row, tcol+col, &rp);
1141 if (++col >= m_TileWidth || col >= m_RawWidth)
1142 row += 1 + (col = 0);
1143 }
1144 }
1145 fseek (m_InputFile, save+4, SEEK_SET);
1146 if ((tcol += m_TileWidth) >= m_RawWidth)
1147 trow += m_TileLength + (tcol = 0);
1148 ljpeg_end(&jh);
1149 }
1150 }
1151
packed_dng_load_raw()1152 void CLASS packed_dng_load_raw()
1153 {
1154 uint16_t *pixel, *rp;
1155 // int row, col;
1156 unsigned row, col;
1157
1158 pixel = (uint16_t *) CALLOC (m_RawWidth * m_Tiff_Samples, sizeof *pixel);
1159 merror (pixel, "packed_dng_load_raw()");
1160 for (row=0; row < m_RawHeight; row++) {
1161 if (m_Tiff_bps == 16)
1162 read_shorts (pixel, m_RawWidth * m_Tiff_Samples);
1163 else {
1164 getbits(-1);
1165 for (col=0; col < m_RawWidth * m_Tiff_Samples; col++)
1166 pixel[col] = getbits(m_Tiff_bps);
1167 }
1168 for (rp=pixel, col=0; col < m_RawWidth; col++)
1169 adobe_copy_pixel (row, col, &rp);
1170 }
1171 FREE (pixel);
1172 }
1173
pentax_load_raw()1174 void CLASS pentax_load_raw()
1175 {
1176 uint16_t bit[2][15], huff[4097];
1177 int dep, row, col, diff, c, i;
1178 uint16_t vpred[2][2] = {{0,0},{0,0}}, hpred[2];
1179
1180 fseek (m_InputFile, meta_offset, SEEK_SET);
1181 dep = (get2() + 12) & 15;
1182 fseek (m_InputFile, 12, SEEK_CUR);
1183 for(c=0;c<dep;c++) bit[0][c] = get2();
1184 for(c=0;c<dep;c++) bit[1][c] = fgetc(m_InputFile);
1185 for(c=0;c<dep;c++)
1186 for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); )
1187 huff[++i] = bit[1][c] << 8 | c;
1188 huff[0] = 12;
1189 fseek (m_InputFile, m_Data_Offset, SEEK_SET);
1190 getbits(-1);
1191 for (row=0; row < m_RawHeight; row++)
1192 for (col=0; col < m_RawWidth; col++) {
1193 diff = ljpeg_diff (huff);
1194 if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
1195 else hpred[col & 1] += diff;
1196 RAW(row,col) = hpred[col & 1];
1197 if (hpred[col & 1] >> m_Tiff_bps) derror();
1198 }
1199 }
1200
nikon_load_raw()1201 void CLASS nikon_load_raw()
1202 {
1203 static const uint8_t nikon_tree[][32] = {
1204 { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */
1205 5,4,3,6,2,7,1,0,8,9,11,10,12 },
1206 { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy after split */
1207 0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 },
1208 { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, /* 12-bit lossless */
1209 5,4,6,3,7,2,8,1,9,0,10,11,12 },
1210 { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0, /* 14-bit lossy */
1211 5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 },
1212 { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0, /* 14-bit lossy after split */
1213 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 },
1214 { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */
1215 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } };
1216 uint16_t *huff, ver0, ver1, vpred[2][2], hpred[2], csize;
1217 int i, min, max, step=0, tree=0, split=0, row, col, len, shl, diff;
1218
1219 fseek (m_InputFile, meta_offset, SEEK_SET);
1220 ver0 = fgetc(m_InputFile);
1221 ver1 = fgetc(m_InputFile);
1222 if (ver0 == 0x49 || ver1 == 0x58)
1223 fseek (m_InputFile, 2110, SEEK_CUR);
1224 if (ver0 == 0x46) tree = 2;
1225 if (m_Tiff_bps == 14) tree += 3;
1226 read_shorts (vpred[0], 4);
1227 max = 1 << m_Tiff_bps & 0x7fff;
1228 if ((csize = get2()) > 1)
1229 step = max / (csize-1);
1230 if (ver0 == 0x44 && ver1 == 0x20 && step > 0) {
1231 for (i=0; i < csize; i++)
1232 m_Curve[i*step] = get2();
1233 for (i=0; i < max; i++)
1234 m_Curve[i] = ( m_Curve[i-i%step]*(step-i%step) +
1235 m_Curve[i-i%step+step]*(i%step) ) / step;
1236 fseek (m_InputFile, meta_offset+562, SEEK_SET);
1237 split = get2();
1238 } else if (ver0 != 0x46 && csize <= 0x4001)
1239 read_shorts (m_Curve, max=csize);
1240 while (m_Curve[max-2] == m_Curve[max-1]) max--;
1241 huff = make_decoder(nikon_tree[tree]);
1242 fseek (m_InputFile, m_Data_Offset, SEEK_SET);
1243 getbits(-1);
1244 for (min=row=0; row < m_Height; row++) {
1245 if (split && row == split) {
1246 FREE(huff);
1247 huff = make_decoder(nikon_tree[tree+1]);
1248 max += (min = 16) << 1;
1249 }
1250 for (col=0; col < m_RawWidth; col++) {
1251 i = gethuff(huff);
1252 len = i & 15;
1253 shl = i >> 4;
1254 diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
1255 if ((diff & (1 << (len-1))) == 0)
1256 diff -= (1 << len) - !shl;
1257 if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
1258 else hpred[col & 1] += diff;
1259 if ((uint16_t)(hpred[col & 1] + min) >= max) derror();
1260 RAW(row,col) = m_Curve[LIM((int16_t)hpred[col & 1],(int16_t)0,(int16_t)0x3fff)];
1261 }
1262 }
1263 FREE(huff);
1264 }
1265
1266 /*
1267 Returns 1 for a Coolpix 995, 0 for anything else.
1268 */
nikon_e995()1269 int CLASS nikon_e995()
1270 {
1271 int i, histo[256];
1272 const uint8_t often[] = { 0x00, 0x55, 0xaa, 0xff };
1273
1274 memset (histo, 0, sizeof histo);
1275 fseek (m_InputFile, -2000, SEEK_END);
1276 for (i=0; i < 2000; i++)
1277 histo[fgetc(m_InputFile)]++;
1278 for (i=0; i < 4; i++)
1279 if (histo[often[i]] < 200)
1280 return 0;
1281 return 1;
1282 }
1283
1284 /*
1285 Returns 1 for a Coolpix 2100, 0 for anything else.
1286 */
nikon_e2100()1287 int CLASS nikon_e2100()
1288 {
1289 uint8_t t[12];
1290 int i;
1291
1292 fseek (m_InputFile, 0, SEEK_SET);
1293 for (i=0; i < 1024; i++) {
1294 ptfread (t, 1, 12, m_InputFile);
1295 if (((t[2] & t[4] & t[7] & t[9]) >> 4
1296 & t[1] & t[6] & t[8] & t[11] & 3) != 3)
1297 return 0;
1298 }
1299 return 1;
1300 }
1301
nikon_3700()1302 void CLASS nikon_3700()
1303 {
1304 int bits; // i;
1305 uint8_t dp[24];
1306 static const struct {
1307 int bits;
1308 char make[12], model[15];
1309 } table[] = {
1310 { 0x00, "PENTAX", "Optio 33WR" },
1311 { 0x03, "NIKON", "E3200" },
1312 { 0x32, "NIKON", "E3700" },
1313 { 0x33, "OLYMPUS", "C740UZ" } };
1314
1315 fseek (m_InputFile, 3072, SEEK_SET);
1316 ptfread (dp, 1, 24, m_InputFile);
1317 bits = (dp[8] & 3) << 4 | (dp[20] & 3);
1318 for (unsigned i=0; i < sizeof table / sizeof *table; i++)
1319 if (bits == table[i].bits) {
1320 strcpy (m_CameraMake, table[i].make );
1321 strcpy (m_CameraModel, table[i].model);
1322 }
1323 }
1324
1325 /*
1326 Separates a Minolta DiMAGE Z2 from a Nikon E4300.
1327 */
minolta_z2()1328 int CLASS minolta_z2()
1329 {
1330 unsigned i,nz;
1331 char tail[424];
1332
1333 fseek (m_InputFile, (long)(-sizeof tail), SEEK_END);
1334 ptfread (tail, 1, sizeof tail, m_InputFile);
1335 for (nz=i=0; i < sizeof tail; i++)
1336 if (tail[i]) nz++;
1337 return nz > 20;
1338 }
1339
1340 //void CLASS jpeg_thumb ();
1341
ppm_thumb()1342 void CLASS ppm_thumb ()
1343 /* Remember: This function is modified to write the raw’s thumbnail to the
1344 m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
1345 */
1346 {
1347 char *thumb;
1348 m_ThumbLength = m_ThumbWidth*m_ThumbHeight*3;
1349 thumb = (char *) MALLOC (m_ThumbLength);
1350 merror (thumb, "ppm_thumb()");
1351 //fprintf (m_OutputFile, "P6\n%d %d\n255\n", m_ThumbWidth, m_ThumbHeight);
1352 QString dummy = QString("P6\n%1 %2\n255\n").arg(m_ThumbWidth).arg(m_ThumbHeight);
1353 VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
1354 ptfread (thumb, 1, m_ThumbLength, m_InputFile);
1355 VAppend(m_Thumb, thumb, m_ThumbLength);
1356 FREE (thumb);
1357 }
1358
ppm16_thumb()1359 void CLASS ppm16_thumb()
1360 {
1361 int i;
1362 char *thumb;
1363 m_ThumbLength = m_ThumbWidth*m_ThumbHeight*3;
1364 thumb = (char *) CALLOC (m_ThumbLength,2);
1365 merror (thumb, "ppm16_thumb()");
1366 read_shorts ((uint16_t *) thumb, m_ThumbLength);
1367 for (i=0; i < (int32_t)m_ThumbLength; i++)
1368 thumb[i] = ((uint16_t *) thumb)[i] >> 8;
1369 QString dummy = QString("P6\n%1 %2\n255\n").arg(m_ThumbWidth).arg(m_ThumbHeight);
1370 VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
1371 //fprintf (ofp, "P6\n%d %d\n255\n", m_ThumbWidth, m_ThumbHeight);
1372 //fwrite (thumb, 1, m_ThumbLength, ofp);
1373 VAppend(m_Thumb, thumb, m_ThumbLength);
1374 FREE (thumb);
1375 }
1376
layer_thumb()1377 void CLASS layer_thumb ()
1378 /* Remember: This function is modified to write the raw’s thumbnail to the
1379 m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
1380 */
1381 // TODO: Tests needed: What format is this? Can it be read by QPixmap?
1382 {
1383 // int i, c;
1384 int c;
1385 char *thumb, map[][4] = { "012","102" };
1386
1387 m_Colors = m_ThumbMisc >> 5 & 7;
1388 m_ThumbLength = m_ThumbWidth*m_ThumbHeight;
1389 thumb = (char *) CALLOC (m_Colors, m_ThumbLength);
1390 merror (thumb, "layer_thumb()");
1391 //fprintf (m_OutputFile, "P%d\n%d %d\n255\n", 5 + (m_Colors >> 1), m_ThumbWidth, m_ThumbHeight);
1392 QString dummy = QString("P%1\n%2 %3\n255\n")
1393 .arg(5 + (m_Colors >> 1)).arg(m_ThumbWidth).arg(m_ThumbHeight);
1394 VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
1395 ptfread (thumb, m_ThumbLength, m_Colors, m_InputFile);
1396 for (unsigned i=0; i < m_ThumbLength; i++) {
1397 for (c=0; c < m_Colors; c++) {
1398 //putc (thumb[i+m_ThumbLength*(map[m_ThumbMisc >> 8][c]-'0')], m_OutputFile);
1399 #pragma GCC diagnostic push
1400 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
1401 m_Thumb.push_back(thumb[i+m_ThumbLength*(map[m_ThumbMisc >> 8][c]-'0')]);
1402 #pragma GCC diagnostic pop
1403 }
1404 }
1405 FREE (thumb);
1406 }
1407
rollei_thumb()1408 void CLASS rollei_thumb ()
1409 /* Remember: This function is modified to write the raw’s thumbnail to the
1410 m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
1411 */
1412 // TODO: Tests needed: What format is this? Can it be read by QPixmap?
1413 {
1414 unsigned i;
1415 uint16_t *thumb;
1416
1417 m_ThumbLength = m_ThumbWidth * m_ThumbHeight;
1418 thumb = (uint16_t *) CALLOC (m_ThumbLength, 2);
1419 merror (thumb, "rollei_thumb()");
1420 //fprintf (m_OutputFile, "P6\n%d %d\n255\n", m_ThumbWidth, m_ThumbHeight);
1421 QString dummy = QString("P6\n%1 %2\n255\n").arg(m_ThumbWidth).arg(m_ThumbHeight);
1422 VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
1423 read_shorts (thumb, m_ThumbLength);
1424 for (i=0; i < m_ThumbLength; i++) {
1425 //putc (thumb[i] << 3, m_OutputFile);
1426 //putc (thumb[i] >> 5 << 2, m_OutputFile);
1427 //putc (thumb[i] >> 11 << 3, m_OutputFile);
1428 #pragma GCC diagnostic push
1429 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
1430 m_Thumb.push_back(thumb[i] << 3);
1431 m_Thumb.push_back(thumb[i] >> 5 << 2);
1432 m_Thumb.push_back(thumb[i] >> 11 << 3);
1433 #pragma GCC diagnostic pop
1434 }
1435 FREE (thumb);
1436 }
1437
rollei_load_raw()1438 void CLASS rollei_load_raw()
1439 {
1440 uint8_t pixel[10];
1441 unsigned iten=0, isix, i, buffer=0, todo[16];
1442
1443 isix = m_RawWidth * m_RawHeight * 5 / 8;
1444 while (fread (pixel, 1, 10, m_InputFile) == 10) {
1445 for (i=0; i < 10; i+=2) {
1446 todo[i] = iten++;
1447 todo[i+1] = pixel[i] << 8 | pixel[i+1];
1448 buffer = pixel[i] >> 2 | buffer << 6;
1449 }
1450 for ( ; i < 16; i+=2) {
1451 todo[i] = isix++;
1452 todo[i+1] = buffer >> (14-i)*5;
1453 }
1454 for (i=0; i < 16; i+=2)
1455 m_Raw_Image[todo[i]] = (todo[i+1] & 0x3ff);
1456 }
1457 m_WhiteLevel = 0x3ff;
1458 }
1459
raw(unsigned row,unsigned col)1460 int CLASS raw (unsigned row, unsigned col)
1461 {
1462 return (row < m_RawHeight && col < m_RawWidth) ? RAW(row,col) : 0;
1463 }
1464
phase_one_flat_field(int is_float,int nc)1465 void CLASS phase_one_flat_field (int is_float, int nc)
1466 {
1467 uint16_t head[8];
1468 unsigned wide, y, x, c, rend, cend, row, col;
1469 float *mrow, num, mult[4];
1470
1471 read_shorts (head, 8);
1472 wide = head[2] / head[4];
1473 mrow = (float *) CALLOC (nc*wide, sizeof *mrow);
1474 merror (mrow, "phase_one_flat_field()");
1475 for (y=0; y < (unsigned) (head[3] / head[5]); y++) {
1476 for (x=0; x < wide; x++)
1477 for (c=0; c < (unsigned) nc; c+=2) {
1478 num = is_float ? getreal(11) : get2()/32768.0;
1479 if (y==0) mrow[c*wide+x] = num;
1480 else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5];
1481 }
1482 if (y==0) continue;
1483 rend = head[1] + y*head[5];
1484 for (row = rend-head[5]; row < m_RawHeight && row < rend; row++) {
1485 for (x=1; x < wide; x++) {
1486 for (c=0; c < (unsigned) nc; c+=2) {
1487 mult[c] = mrow[c*wide+x-1];
1488 mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4];
1489 }
1490 cend = head[0] + x*head[4];
1491 for (col = cend-head[4]; col < m_RawWidth && col < cend; col++) {
1492 c = nc > 2 ? FC(row-m_TopMargin,col-m_LeftMargin) : 0;
1493 if (!(c & 1)) {
1494 c = unsigned(RAW(row,col) * mult[c]);
1495 RAW(row,col) = MIN((int32_t)c,65535);
1496 }
1497 for (c=0; c < (unsigned) nc; c+=2)
1498 mult[c] += mult[c+1];
1499 }
1500 }
1501 for (x=0; x < wide; x++)
1502 for (c=0; c < (unsigned) nc; c+=2)
1503 mrow[c*wide+x] += mrow[(c+1)*wide+x];
1504 }
1505 }
1506 FREE (mrow);
1507 }
1508
phase_one_correct()1509 void CLASS phase_one_correct()
1510 {
1511 unsigned entries, tag, data, save, col, row, type;
1512 int len, i, j, k, cip, val[4], dev[4], sum, max;
1513 int head[9], diff, mindiff=INT_MAX, off_412=0;
1514 static const signed char dir[12][2] =
1515 { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0},
1516 {-2,-2}, {-2,2}, {2,-2}, {2,2} };
1517 float poly[8], num, cfrac, frac, mult[2], *yval[2];
1518 uint16_t *xval[2];
1519
1520 if (m_UserSetting_HalfSize || !m_MetaLength) return;
1521 TRACEKEYVALS("Phase One correction","%s","");
1522 fseek (m_InputFile, meta_offset, SEEK_SET);
1523 m_ByteOrder = get2();
1524 fseek (m_InputFile, 6, SEEK_CUR);
1525 fseek (m_InputFile, meta_offset+get4(), SEEK_SET);
1526 entries = get4(); get4();
1527 while (entries--) {
1528 tag = get4();
1529 len = get4();
1530 data = get4();
1531 save = ftell(m_InputFile);
1532 fseek (m_InputFile, meta_offset+data, SEEK_SET);
1533 if (tag == 0x419) { /* Polynomial curve */
1534 for (get4(), i=0; i < 8; i++)
1535 poly[i] = getreal(11);
1536 poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1;
1537 for (i=0; i < 0x10000; i++) {
1538 num = (poly[5]*i + poly[3])*i + poly[1];
1539 m_Curve[i] = (uint16_t) LIM((int32_t)num,0,65535);
1540 } goto apply; /* apply to right half */
1541 } else if (tag == 0x41a) { /* Polynomial curve */
1542 for (i=0; i < 4; i++)
1543 poly[i] = getreal(11);
1544 for (i=0; i < 0x10000; i++) {
1545 for (num=0, j=4; j--; )
1546 num = num * i + poly[j];
1547 m_Curve[i] = (uint16_t) LIM((int32_t)(num+i),0,65535);
1548 } apply: /* apply to whole image */
1549 for (row=0; row < m_RawHeight; row++)
1550 for (col = (tag & 1)*ph1.split_col; col < m_RawWidth; col++)
1551 RAW(row,col) = m_Curve[RAW(row,col)];
1552 } else if (tag == 0x400) { /* Sensor defects */
1553 while ((len -= 8) >= 0) {
1554 col = get2();
1555 row = get2();
1556 type = get2(); get2();
1557 if (col >= m_RawWidth) continue;
1558 if (type == 131) /* Bad column */
1559 for (row=0; row < m_RawHeight; row++)
1560 if (FC(row-m_TopMargin,col-m_LeftMargin) == 1) {
1561 for (sum=i=0; i < 4; i++)
1562 sum += val[i] = raw (row+dir[i][0], col+dir[i][1]);
1563 for (max=i=0; i < 4; i++) {
1564 dev[i] = abs((val[i] << 2) - sum);
1565 if (dev[max] < dev[i]) max = i;
1566 }
1567 RAW(row,col) = (uint16_t) ((sum - val[max])/3.0 + 0.5);
1568 } else {
1569 for (sum=0, i=8; i < 12; i++)
1570 sum += raw (row+dir[i][0], col+dir[i][1]);
1571 RAW(row,col) = (uint16_t) (0.5 + sum * 0.0732233 +
1572 (raw(row,col-2) + raw(row,col+2)) * 0.3535534);
1573 }
1574 else if (type == 129) { /* Bad pixel */
1575 if (row >= m_RawHeight) continue;
1576 j = (FC(row-m_TopMargin,col-m_LeftMargin) != 1) * 4;
1577 for (sum=0, i=j; i < j+8; i++)
1578 sum += raw (row+dir[i][0], col+dir[i][1]);
1579 RAW(row,col) = (sum + 4) >> 3;
1580 }
1581 }
1582 } else if (tag == 0x401) { /* All-color flat fields */
1583 phase_one_flat_field (1, 2);
1584 } else if (tag == 0x416 || tag == 0x410) {
1585 phase_one_flat_field (0, 2);
1586 } else if (tag == 0x40b) { /* Red+blue flat field */
1587 phase_one_flat_field (0, 4);
1588 } else if (tag == 0x412) {
1589 fseek (m_InputFile, 36, SEEK_CUR);
1590 diff = abs (get2() - ph1.tag_21a);
1591 if (mindiff > diff) {
1592 mindiff = diff;
1593 off_412 = ftell(m_InputFile) - 38;
1594 }
1595 }
1596 fseek (m_InputFile, save, SEEK_SET);
1597 }
1598 if (off_412) {
1599 fseek (m_InputFile, off_412, SEEK_SET);
1600 for (i=0; i < 9; i++) head[i] = get4() & 0x7fff;
1601 yval[0] = (float *) CALLOC (head[1]*head[3] + head[2]*head[4], 6);
1602 merror (yval[0], "phase_one_correct()");
1603 yval[1] = (float *) (yval[0] + head[1]*head[3]);
1604 xval[0] = (uint16_t *) (yval[1] + head[2]*head[4]);
1605 xval[1] = (uint16_t *) (xval[0] + head[1]*head[3]);
1606 get2();
1607 for (i=0; i < 2; i++)
1608 for (j=0; j < head[i+1]*head[i+3]; j++)
1609 yval[i][j] = getreal(11);
1610 for (i=0; i < 2; i++)
1611 for (j=0; j < head[i+1]*head[i+3]; j++)
1612 xval[i][j] = get2();
1613 for (row=0; row < m_RawHeight; row++)
1614 for (col=0; col < m_RawWidth; col++) {
1615 cfrac = (float) col * head[3] / m_RawWidth;
1616 cfrac -= (cip = (int) cfrac);
1617 num = RAW(row,col) * 0.5;
1618 for (i=cip; i < cip+2; i++) {
1619 for (k=j=0; j < head[1]; j++)
1620 if (num < xval[0][k = head[1]*i+j]) break;
1621 frac = (j == 0 || j == head[1]) ? 0 :
1622 (xval[0][k] - num) / (xval[0][k] - xval[0][k-1]);
1623 mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac);
1624 }
1625 i = (int) (((mult[0] * (1-cfrac) + mult[1] * cfrac) * row + num) * 2);
1626 RAW(row,col) = LIM(i,0,65535);
1627 }
1628 FREE (yval[0]);
1629 }
1630 }
1631
phase_one_load_raw()1632 void CLASS phase_one_load_raw()
1633 {
1634 int a, b, i;
1635 uint16_t akey, bkey, m_Mask;
1636
1637 fseek (m_InputFile, ph1.key_off, SEEK_SET);
1638 akey = get2();
1639 bkey = get2();
1640 m_Mask = ph1.format == 1 ? 0x5555:0x1354;
1641 fseek (m_InputFile, m_Data_Offset, SEEK_SET);
1642 read_shorts (m_Raw_Image, m_RawWidth*m_RawHeight);
1643 if (ph1.format)
1644 for (i=0; i < m_RawWidth*m_RawHeight; i+=2) {
1645 a = m_Raw_Image[i+0] ^ akey;
1646 b = m_Raw_Image[i+1] ^ bkey;
1647 m_Raw_Image[i+0] = (a & m_Mask) | (b & ~m_Mask);
1648 m_Raw_Image[i+1] = (b & m_Mask) | (a & ~m_Mask);
1649 }
1650 }
1651
ph1_bithuff(int nbits,uint16_t * huff)1652 unsigned CLASS ph1_bithuff (int nbits, uint16_t *huff)
1653 {
1654 unsigned c;
1655
1656 if (nbits == -1)
1657 return m_ph1_bithuffbitbuf = m_ph1_bithuffvbits = 0;
1658 if (nbits == 0) return 0;
1659 if (m_ph1_bithuffvbits < nbits) {
1660 m_ph1_bithuffbitbuf = m_ph1_bithuffbitbuf << 32 | get4();
1661 m_ph1_bithuffvbits += 32;
1662 }
1663 c = m_ph1_bithuffbitbuf << (64-m_ph1_bithuffvbits) >> (64-nbits);
1664 if (huff) {
1665 m_ph1_bithuffvbits -= huff[c] >> 8;
1666 return (unsigned char) huff[c];
1667 }
1668 m_ph1_bithuffvbits -= nbits;
1669 return c;
1670 }
1671 #define ph1_bits(n) ph1_bithuff(n,0)
1672 #define ph1_huff(h) ph1_bithuff(*h,h+1)
1673
phase_one_load_raw_c()1674 void CLASS phase_one_load_raw_c()
1675 {
1676 static const int length[] = { 8,7,6,9,11,10,5,12,14,13 };
1677 int *offset, len[2], pred[2], row, col, i, j;
1678 uint16_t *pixel;
1679 short (*black)[2];
1680
1681 pixel = (uint16_t *) CALLOC (m_RawWidth + m_RawHeight*4, 2);
1682 merror (pixel, "phase_one_load_raw_c()");
1683 offset = (int *) (pixel + m_RawWidth);
1684 fseek (m_InputFile, strip_offset, SEEK_SET);
1685 for (row=0; row < m_RawHeight; row++)
1686 offset[row] = get4();
1687 black = (short (*)[2]) offset + m_RawHeight;
1688 fseek (m_InputFile, ph1.black_off, SEEK_SET);
1689 if (ph1.black_off)
1690 read_shorts ((uint16_t *) black[0], m_RawHeight*2);
1691 for (i=0; i < 256; i++)
1692 m_Curve[i] = (uint16_t) (i*i / 3.969 + 0.5);
1693 for (row=0; row < m_RawHeight; row++) {
1694 fseek (m_InputFile, m_Data_Offset + offset[row], SEEK_SET);
1695 ph1_bits(-1);
1696 pred[0] = pred[1] = 0;
1697 for (col=0; col < m_RawWidth; col++) {
1698 if (col >= (m_RawWidth & -8))
1699 len[0] = len[1] = 14;
1700 else if ((col & 7) == 0)
1701 for (i=0; i < 2; i++) {
1702 for (j=0; j < 5 && !ph1_bits(1); j++) {};
1703 if (j--) len[i] = length[j*2 + ph1_bits(1)];
1704 }
1705 if ((i = len[col & 1]) == 14)
1706 pixel[col] = pred[col & 1] = ph1_bits(16);
1707 else
1708 pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1));
1709 if (pred[col & 1] >> 16) derror();
1710 if (ph1.format == 5 && pixel[col] < 256)
1711 pixel[col] = m_Curve[pixel[col]];
1712 }
1713 for (col=0; col < m_RawWidth; col++) {
1714 i = (pixel[col] << 2) - ph1.black + black[row][col >= ph1.split_col];
1715 if (i > 0) RAW(row,col) = i;
1716 }
1717 }
1718 FREE (pixel);
1719 m_WhiteLevel = 0xfffc - ph1.black;
1720 }
1721
hasselblad_load_raw()1722 void CLASS hasselblad_load_raw()
1723 {
1724 struct jhead jh;
1725 int row, col, pred[2], len[2], diff, c;
1726
1727 if (!ljpeg_start (&jh, 0)) return;
1728 m_ByteOrder = 0x4949;
1729 ph1_bits(-1);
1730 for (row=0; row < m_RawHeight; row++) {
1731 pred[0] = pred[1] = 0x8000 + m_Load_Flags;
1732 for (col=0; col < m_RawWidth; col+=2) {
1733 for(c=0;c<2;c++) len[c] = ph1_huff(jh.huff[0]);
1734 for(c=0;c<2;c++) {
1735 diff = ph1_bits(len[c]);
1736 if ((diff & (1 << (len[c]-1))) == 0)
1737 diff -= (1 << len[c]) - 1;
1738 if (diff == 65535) diff = -32768;
1739 RAW(row,col+c) = pred[c] += diff;
1740 }
1741 }
1742 }
1743 ljpeg_end (&jh);
1744 m_WhiteLevel = 0xffff;
1745 }
1746
leaf_hdr_load_raw()1747 void CLASS leaf_hdr_load_raw()
1748 {
1749 uint16_t *pixel=0;
1750 unsigned tile=0, r, c, row, col;
1751
1752 if (!m_Filters) {
1753 pixel = (uint16_t *) CALLOC (m_RawWidth, sizeof *pixel);
1754 merror (pixel, "leaf_hdr_load_raw()");
1755 }
1756 for (c=0; c < m_Tiff_Samples; c++) {
1757 for (r=0; r < m_RawHeight; r++) {
1758 if (r % m_TileLength == 0) {
1759 fseek (m_InputFile, m_Data_Offset + 4*tile++, SEEK_SET);
1760 fseek (m_InputFile, get4(), SEEK_SET);
1761 }
1762 if (m_Filters && c != m_UserSetting_ShotSelect) continue;
1763 if (m_Filters) pixel = m_Raw_Image + r*m_RawWidth;
1764 read_shorts (pixel, m_RawWidth);
1765 if (!m_Filters && (row = r - m_TopMargin) < m_Height)
1766 for (col=0; col < m_Width; col++)
1767 m_Image[row*m_Width+col][c] = pixel[col+m_LeftMargin];
1768 }
1769 }
1770 if (!m_Filters) {
1771 m_WhiteLevel = 0xffff;
1772 m_RawColor = 1;
1773 FREE (pixel);
1774 }
1775 }
1776
unpacked_load_raw()1777 void CLASS unpacked_load_raw()
1778 {
1779 int row, col, bits=0;
1780
1781 while ((1 << ++bits) < (int32_t)m_WhiteLevel);
1782 read_shorts (m_Raw_Image, m_RawWidth*m_RawHeight);
1783 for (row=0; row < m_RawHeight; row++)
1784 for (col=0; col < m_RawWidth; col++)
1785 if ((RAW(row,col) >>= m_Load_Flags) >> bits
1786 && (unsigned) (row-m_TopMargin) < m_Height
1787 && (unsigned) (col-m_LeftMargin) < m_Width) derror();
1788 }
1789
sinar_4shot_load_raw()1790 void CLASS sinar_4shot_load_raw()
1791 {
1792 uint16_t *pixel;
1793 unsigned shot, row, col, r, c;
1794
1795 if ((shot = m_UserSetting_ShotSelect) || m_UserSetting_HalfSize) {
1796 if (shot) shot--;
1797 if (shot > 3) shot = 3;
1798 fseek (m_InputFile, m_Data_Offset + shot*4, SEEK_SET);
1799 fseek (m_InputFile, get4(), SEEK_SET);
1800 unpacked_load_raw();
1801 return;
1802 }
1803 FREE (m_Raw_Image);
1804 m_Raw_Image = 0;
1805 m_Image = (uint16_t (*)[4])
1806 CALLOC ((m_OutHeight=m_Height)*(m_OutWidth=m_Width), sizeof *m_Image);
1807 merror (m_Image, "sinar_4shot_load_raw()");
1808 pixel = (uint16_t *) CALLOC (m_RawWidth, sizeof *pixel);
1809 merror (pixel, "sinar_4shot_load_raw()");
1810 for (shot=0; shot < 4; shot++) {
1811 fseek (m_InputFile, m_Data_Offset + shot*4, SEEK_SET);
1812 fseek (m_InputFile, get4(), SEEK_SET);
1813 for (row=0; row < m_RawHeight; row++) {
1814 read_shorts (pixel, m_RawWidth);
1815 if ((r = row-m_TopMargin - (shot >> 1 & 1)) >= m_Height) continue;
1816 for (col=0; col < m_RawWidth; col++) {
1817 if ((c = col-m_LeftMargin - (shot & 1)) >= m_Width) continue;
1818 m_Image[r*m_Width+c][FC(row,col)] = pixel[col];
1819 }
1820 }
1821 }
1822 FREE (pixel);
1823 m_Shrink = m_Filters = 0;
1824 }
1825
imacon_full_load_raw()1826 void CLASS imacon_full_load_raw()
1827 {
1828 int row, col;
1829
1830 for (row=0; row < m_Height; row++)
1831 for (col=0; col < m_Width; col++)
1832 read_shorts (m_Image[row*m_Width+col], 3);
1833 }
1834
packed_load_raw()1835 void CLASS packed_load_raw()
1836 {
1837 int vbits=0, bwide, pwide, rbits, bite, half, irow, row, col, val, i;
1838 uint64_t bitbuf=0;
1839
1840 if (m_RawWidth * 8U >= m_Width * m_Tiff_bps) /* Is m_RawWidth in bytes? */
1841 pwide = (bwide = m_RawWidth) * 8 / m_Tiff_bps;
1842 else bwide = (pwide = m_RawWidth) * m_Tiff_bps / 8;
1843 rbits = bwide * 8 - pwide * m_Tiff_bps;
1844 if (m_Load_Flags & 1) bwide = bwide * 16 / 15;
1845 bite = 8 + (m_Load_Flags & 24);
1846 half = (m_RawHeight+1) >> 1;
1847 for (irow=0; irow < m_RawHeight; irow++) {
1848 row = irow;
1849 if (m_Load_Flags & 2 &&
1850 (row = irow % half * 2 + irow / half) == 1 &&
1851 m_Load_Flags & 4) {
1852 if (vbits=0, m_Tiff_Compress)
1853 fseek (m_InputFile, m_Data_Offset - (-half*bwide & -2048), SEEK_SET);
1854 else {
1855 fseek (m_InputFile, 0, SEEK_END);
1856 fseek (m_InputFile, ftell(m_InputFile) >> 3 << 2, SEEK_SET);
1857 }
1858 }
1859 for (col=0; col < pwide; col++) {
1860 for (vbits -= m_Tiff_bps; vbits < 0; vbits += bite) {
1861 bitbuf <<= bite;
1862 for (i=0; i < bite; i+=8)
1863 bitbuf |= (unsigned) (fgetc(m_InputFile) << i);
1864 }
1865 val = bitbuf << (64-m_Tiff_bps-vbits) >> (64-m_Tiff_bps);
1866 RAW(row,col ^ (m_Load_Flags >> 6)) = val;
1867 if (m_Load_Flags & 1 && (col % 10) == 9 &&
1868 fgetc(m_InputFile) && col < m_Width+m_LeftMargin) derror();
1869 }
1870 vbits -= rbits;
1871 }
1872 }
1873
nokia_load_raw()1874 void CLASS nokia_load_raw()
1875 {
1876 uint8_t *data, *dp;
1877 int rev, dwide, row, col, c;
1878
1879 rev = 3 * (m_ByteOrder == 0x4949);
1880 dwide = m_RawWidth * 5 / 4;
1881 data = (uint8_t *) MALLOC (dwide*2);
1882 merror (data, "nokia_load_raw()");
1883 for (row=0; row < m_RawHeight; row++) {
1884 if (fread (data+dwide, 1, dwide, m_InputFile) < (size_t) dwide) derror();
1885 for(c=0;c<dwide;c++) data[c] = data[dwide+(c ^ rev)];
1886 for (dp=data, col=0; col < m_RawWidth; dp+=5, col+=4)
1887 for (c=0; c<4; c++) RAW(row,col+c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
1888 }
1889 FREE (data);
1890 m_WhiteLevel = 0x3ff;
1891 }
1892
pana_bits(int nbits)1893 unsigned CLASS pana_bits (int nbits)
1894 {
1895 int byte;
1896
1897
1898
1899 if (!nbits) return m_pana_bits_vbits=0;
1900 if (!m_pana_bits_vbits) {
1901 ptfread (m_pana_bits_buf+m_Load_Flags, 1, 0x4000-m_Load_Flags, m_InputFile);
1902 ptfread (m_pana_bits_buf, 1, m_Load_Flags, m_InputFile);
1903 }
1904 m_pana_bits_vbits = (m_pana_bits_vbits - nbits) & 0x1ffff;
1905 byte = m_pana_bits_vbits >> 3 ^ 0x3ff0;
1906 return (m_pana_bits_buf[byte] | m_pana_bits_buf[byte+1] << 8) >> (m_pana_bits_vbits & 7) & ~(-1 << nbits);
1907 }
1908
panasonic_load_raw()1909 void CLASS panasonic_load_raw()
1910 {
1911 int row, col, i, j, sh=0, pred[2], nonz[2];
1912
1913 pana_bits(0);
1914 for (row=0; row < m_Height; row++)
1915 for (col=0; col < m_RawWidth; col++) {
1916 if ((i = col % 14) == 0)
1917 pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
1918 if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
1919 if (nonz[i & 1]) {
1920 if ((j = pana_bits(8))) {
1921 if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
1922 pred[i & 1] &= ~(-1 << sh);
1923 pred[i & 1] += j << sh;
1924 }
1925 } else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
1926 pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
1927 if ((RAW(row,col) = pred[col & 1]) > 4098 && col < m_Width) derror();
1928 }
1929 }
1930
olympus_load_raw()1931 void CLASS olympus_load_raw()
1932 {
1933 uint16_t huff[4096];
1934 int row, col, nbits, sign, low, high, i, c, w, n, nw;
1935 int acarry[2][3], *carry, pred, diff;
1936
1937 huff[n=0] = 0xc0c;
1938 for (i=12; i--; )
1939 for (c=0;c<(2048>>i);c++) huff[++n] = (i+1) << 8 | i;
1940 fseek (m_InputFile, 7, SEEK_CUR);
1941 getbits(-1);
1942 for (row=0; row < m_Height; row++) {
1943 memset (acarry, 0, sizeof acarry);
1944 for (col=0; col < m_RawWidth; col++) {
1945 carry = acarry[col & 1];
1946 i = 2 * (carry[2] < 3);
1947 for (nbits=2+i; (uint16_t) carry[0] >> (nbits+i); nbits++){} ;
1948 low = (sign = getbits(3)) & 3;
1949 sign = sign << 29 >> 31;
1950 if ((high = getbithuff(12,huff)) == 12)
1951 high = getbits(16-nbits) >> 1;
1952 carry[0] = (high << nbits) | getbits(nbits);
1953 diff = (carry[0] ^ sign) + carry[1];
1954 carry[1] = (diff*3 + carry[1]) >> 5;
1955 carry[2] = carry[0] > 16 ? 0 : carry[2]+1;
1956 if (col >= m_Width) continue;
1957 if (row < 2 && col < 2) pred = 0;
1958 else if (row < 2) pred = RAW(row,col-2);
1959 else if (col < 2) pred = RAW(row-2,col);
1960 else {
1961 w = RAW(row,col-2);
1962 n = RAW(row-2,col);
1963 nw = RAW(row-2,col-2);
1964 if ((w < nw && nw < n) || (n < nw && nw < w)) {
1965 if (ABS(w-nw) > 32 || ABS(n-nw) > 32)
1966 pred = w + n - nw;
1967 else pred = (w + n) >> 1;
1968 } else pred = ABS(w-nw) > ABS(n-nw) ? w : n;
1969 }
1970 if ((RAW(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
1971 }
1972 }
1973 }
1974
olympus_cseries_load_raw()1975 void CLASS olympus_cseries_load_raw()
1976 {
1977 int irow, row, col;
1978
1979 for (irow=0; irow < m_Height; irow++) {
1980 row = irow * 2 % m_Height + irow / (m_Height/2);
1981 if (row < 2) {
1982 fseek (m_InputFile, m_Data_Offset - row*(-m_Width*m_Height*3/4 & -2048), SEEK_SET);
1983 getbits(-1);
1984 }
1985 for (col=0; col < m_Width; col++)
1986 BAYER(row,col) = getbits(12);
1987 }
1988 m_BlackLevel >>= 4;
1989 }
1990
minolta_rd175_load_raw()1991 void CLASS minolta_rd175_load_raw()
1992 {
1993 uint8_t pixel[768];
1994 unsigned irow, box, row, col;
1995
1996 for (irow=0; irow < 1481; irow++) {
1997 if (fread (pixel, 1, 768, m_InputFile) < 768) derror();
1998 box = irow / 82;
1999 row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2);
2000 switch (irow) {
2001 case 1477: case 1479: continue;
2002 case 1476: row = 984; break;
2003 case 1480: row = 985; break;
2004 case 1478: row = 985; box = 1;
2005 }
2006 if ((box < 12) && (box & 1)) {
2007 for (col=0; col < 1533; col++, row ^= 1)
2008 if (col != 1) RAW(row,col) = (col+1) & 2 ?
2009 pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
2010 RAW(row,1) = pixel[1] << 1;
2011 RAW(row,1533) = pixel[765] << 1;
2012 } else
2013 for (col=row & 1; col < 1534; col+=2)
2014 RAW(row,col) = pixel[col/2] << 1;
2015 }
2016 m_WhiteLevel = 0xff << 1;
2017 }
2018
quicktake_100_load_raw()2019 void CLASS quicktake_100_load_raw()
2020 {
2021 uint8_t pixel[484][644];
2022 static const short gstep[16] =
2023 { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 };
2024 static const short rstep[6][4] =
2025 { { -3,-1,1,3 }, { -5,-1,1,5 }, { -8,-2,2,8 },
2026 { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } };
2027 int rb, row, col, sharp, val=0;
2028
2029 getbits(-1);
2030 memset (pixel, 0x80, sizeof pixel);
2031 for (row=2; row < m_Height+2; row++) {
2032 for (col=2+(row & 1); col < m_Width+2; col+=2) {
2033 val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] +
2034 pixel[row][col-2]) >> 2) + gstep[getbits(4)];
2035 pixel[row][col] = val = LIM(val,0,255);
2036 if (col < 4)
2037 pixel[row][col-2] = pixel[row+1][~row & 1] = val;
2038 if (row == 2)
2039 pixel[row-1][col+1] = pixel[row-1][col+3] = val;
2040 }
2041 pixel[row][col] = val;
2042 }
2043 for (rb=0; rb < 2; rb++)
2044 for (row=2+rb; row < m_Height+2; row+=2)
2045 for (col=3-(row & 1); col < m_Width+2; col+=2) {
2046 if (row < 4 || col < 4) sharp = 2;
2047 else {
2048 val = ABS(pixel[row-2][col] - pixel[row][col-2])
2049 + ABS(pixel[row-2][col] - pixel[row-2][col-2])
2050 + ABS(pixel[row][col-2] - pixel[row-2][col-2]);
2051 sharp = val < 4 ? 0 : val < 8 ? 1 : val < 16 ? 2 :
2052 val < 32 ? 3 : val < 48 ? 4 : 5;
2053 }
2054 val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1)
2055 + rstep[sharp][getbits(2)];
2056 pixel[row][col] = val = LIM(val,0,255);
2057 if (row < 4) pixel[row-2][col+2] = val;
2058 if (col < 4) pixel[row+2][col-2] = val;
2059 }
2060 for (row=2; row < m_Height+2; row++)
2061 for (col=3-(row & 1); col < m_Width+2; col+=2) {
2062 val = ((pixel[row][col-1] + (pixel[row][col] << 2) +
2063 pixel[row][col+1]) >> 1) - 0x100;
2064 pixel[row][col] = LIM(val,0,255);
2065 }
2066 for (row=0; row < m_Height; row++)
2067 for (col=0; col < m_Width; col++)
2068 RAW(row,col) = m_Curve[pixel[row+2][col+2]];
2069 m_WhiteLevel = 0x3ff;
2070 }
2071
2072 #define radc_token(tree) ((signed char) getbithuff(8,huff[tree]))
2073
2074 #define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
2075
2076 #define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
2077 : (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
2078
kodak_radc_load_raw()2079 void CLASS kodak_radc_load_raw()
2080 {
2081 static const int8_t src[] = {
2082 1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8,
2083 1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8,
2084 2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8,
2085 2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8,
2086 2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8,
2087 2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8,
2088 2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8,
2089 2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8,
2090 2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4,
2091 2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8,
2092 1,0, 2,2, 2,-2,
2093 1,-3, 1,3,
2094 2,-17, 2,-5, 2,5, 2,17,
2095 2,-7, 2,2, 2,9, 2,18,
2096 2,-18, 2,-9, 2,-2, 2,7,
2097 2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79,
2098 2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76,
2099 2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37
2100 };
2101 uint16_t huff[19][256];
2102 int row, col, tree, nreps, rep, step, /* i,*/ c, s, r, x, y, val;
2103 constexpr unsigned int bufi1 = 3;
2104 constexpr unsigned int bufi2 = 386;
2105 short last[3] = { 16,16,16 }, mul[3], buf[3][bufi1][bufi2];
2106 static const uint16_t pt[] =
2107 { 0,0, 1280,1344, 2320,3616, 3328,8000, 4095,16383, 65535,16383 };
2108 int i;
2109
2110 for (i=2; i < 12; i+=2)
2111 for (c=pt[i-2]; c <= pt[i]; c++)
2112 m_Curve[c] = (float)
2113 (c-pt[i-2]) / (pt[i]-pt[i-2]) * (pt[i+1]-pt[i-1]) + pt[i-1] + 0.5;
2114 for (s=i=0; i < (int)(sizeof(src)); i+=2)
2115 for(c=0;c<(256>>src[i]);c++)
2116 huff[0][s++] = src[i] << 8 | (unsigned char) src[i+1];
2117 s = m_Kodak_cbpp == 243 ? 2 : 3;
2118 for(c=0;c<256;c++) huff[18][c] = (8-s) << 8 | c >> s << s | 1 << (s-1);
2119 getbits(-1);
2120 memset(buf, 2048, sizeof(buf)/sizeof(short));
2121 // for (unsigned i=0; i < sizeof(buf)/sizeof(short); i++)
2122 // buf[0][0][i] = 2048;
2123 for (row=0; row < m_Height; row+=4) {
2124 for (c=0; c<3; c++) mul[c] = getbits(6);
2125 for (c=0; c<3; c++) {
2126 val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
2127 s = val > 65564 ? 10:12;
2128 x = ~(-1 << (s-1));
2129 val <<= 12-s;
2130 for (unsigned i=0; i < bufi1; i++)
2131 for (unsigned j=0; j < bufi2; j++)
2132 buf[c][i][j] = (buf[c][i][j] * val + x) >> s;
2133 // for (unsigned i=0; i < sizeof(buf[0])/sizeof(short); i++)
2134 // buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
2135 last[c] = mul[c];
2136 for (r=0; r <= !c; r++) {
2137 buf[c][1][m_Width/2] = buf[c][2][m_Width/2] = mul[c] << 7;
2138 for (tree=1, col=m_Width/2; col > 0; ) {
2139 if ((tree = radc_token(tree))) {
2140 col -= 2;
2141 if (tree == 8)
2142 FORYX buf[c][y][x] = (uint8_t) radc_token(18) * mul[c];
2143 else
2144 FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
2145 } else
2146 do {
2147 nreps = (col > 2) ? radc_token(9) + 1 : 1;
2148 for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) {
2149 col -= 2;
2150 FORYX buf[c][y][x] = PREDICTOR;
2151 if (rep & 1) {
2152 step = radc_token(10) << 4;
2153 FORYX buf[c][y][x] += step;
2154 }
2155 }
2156 } while (nreps == 9);
2157 }
2158 for (y=0; y < 2; y++)
2159 for (x=0; x < m_Width/2; x++) {
2160 val = (buf[c][y+1][x] << 4) / mul[c];
2161 if (val < 0) val = 0;
2162 if (c) RAW(row+y*2+c-1,x*2+2-c) = val;
2163 else RAW(row+r*2+y,x*2+y) = val;
2164 }
2165 memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
2166 }
2167 }
2168 for (y=row; y < row+4; y++)
2169 for (x=0; x < m_Width; x++)
2170 if ((x+y) & 1) {
2171 r = x ? x-1 : x+1;
2172 s = x+1 < m_Width ? x+1 : x-1;
2173 val = (RAW(y,x)-2048)*2 + (RAW(y,r)+RAW(y,s))/2;
2174 if (val < 0) val = 0;
2175 RAW(y,x) = val;
2176 }
2177 }
2178 for (i=0; i < m_Height*m_Width; i++)
2179 m_Raw_Image[i] = m_Curve[m_Raw_Image[i]];
2180
2181 m_WhiteLevel = 0xfff;
2182 }
2183
2184 #undef FORYX
2185 #undef PREDICTOR
2186
2187 #ifdef NO_JPEG
kodak_jpeg_load_raw()2188 void CLASS kodak_jpeg_load_raw() {}
lossy_dng_load_raw()2189 void CLASS lossy_dng_load_raw() {}
2190 #else
2191
2192 METHODDEF(boolean)
fill_input_buffer(j_decompress_ptr cinfo)2193 fill_input_buffer (j_decompress_ptr cinfo)
2194 {
2195 static uint8_t jpeg_buffer[4096];
2196 size_t nbytes;
2197 ptDcRaw *data = (ptDcRaw*) cinfo->client_data;
2198
2199 nbytes = fread (jpeg_buffer, 1, 4096, data->m_InputFile);
2200 swab ((char *)jpeg_buffer, (char *)jpeg_buffer, nbytes);
2201 cinfo->src->next_input_byte = jpeg_buffer;
2202 cinfo->src->bytes_in_buffer = nbytes;
2203 return TRUE;
2204 }
2205
kodak_jpeg_load_raw()2206 void CLASS kodak_jpeg_load_raw()
2207 {
2208 struct jpeg_decompress_struct cinfo;
2209 struct jpeg_error_mgr jerr;
2210 JSAMPARRAY buf;
2211 JSAMPLE (*pixel)[3];
2212 int row, col;
2213
2214 cinfo.client_data = this;
2215 cinfo.err = jpeg_std_error (&jerr);
2216 jpeg_create_decompress (&cinfo);
2217 jpeg_stdio_src (&cinfo, m_InputFile);
2218 cinfo.src->fill_input_buffer = fill_input_buffer;
2219 jpeg_read_header (&cinfo, TRUE);
2220 jpeg_start_decompress (&cinfo);
2221 if ((cinfo.output_width != m_Width ) ||
2222 (cinfo.output_height*2 != m_Height ) ||
2223 (cinfo.output_components != 3 )) {
2224 fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), m_UserSetting_InputFileName);
2225 jpeg_destroy_decompress (&cinfo);
2226 longjmp (m_Failure, 3);
2227 }
2228 buf = (*cinfo.mem->alloc_sarray)
2229 ((j_common_ptr) &cinfo, JPOOL_IMAGE, m_Width*3, 1);
2230
2231 while (cinfo.output_scanline < cinfo.output_height) {
2232 row = cinfo.output_scanline * 2;
2233 jpeg_read_scanlines (&cinfo, buf, 1);
2234 pixel = (JSAMPLE (*)[3]) buf[0];
2235 for (col=0; col < m_Width; col+=2) {
2236 RAW(row+0,col+0) = pixel[col+0][1] << 1;
2237 RAW(row+1,col+1) = pixel[col+1][1] << 1;
2238 RAW(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
2239 RAW(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
2240 }
2241 }
2242 jpeg_finish_decompress (&cinfo);
2243 jpeg_destroy_decompress (&cinfo);
2244 m_WhiteLevel = 0xff << 1;
2245 }
2246
lossy_dng_load_raw()2247 void CLASS lossy_dng_load_raw()
2248 {
2249 struct jpeg_decompress_struct cinfo;
2250 struct jpeg_error_mgr jerr;
2251 JSAMPARRAY buf;
2252 JSAMPLE (*pixel)[3];
2253 unsigned sm_ByteOrder=m_ByteOrder, ntags, opcode, deg, i, j, c;
2254 unsigned save=m_Data_Offset-4, trow=0, tcol=0, row, col;
2255 ushort curve[3][256];
2256 double coeff[9], tot;
2257
2258 fseek (m_InputFile, meta_offset, SEEK_SET);
2259 m_ByteOrder = 0x4d4d;
2260 ntags = get4();
2261 while (ntags--) {
2262 opcode = get4(); get4(); get4();
2263 if (opcode != 8)
2264 { fseek (m_InputFile, get4(), SEEK_CUR); continue; }
2265 fseek (m_InputFile, 20, SEEK_CUR);
2266 if ((c = get4()) > 2) break;
2267 fseek (m_InputFile, 12, SEEK_CUR);
2268 if ((deg = get4()) > 8) break;
2269 for (i=0; i <= deg && i < 9; i++)
2270 coeff[i] = getreal(12);
2271 for (i=0; i < 256; i++) {
2272 for (tot=j=0; j <= deg; j++)
2273 tot += coeff[j] * pow(i/255.0, j);
2274 curve[c][i] = tot*0xffff;
2275 }
2276 }
2277 m_ByteOrder = sm_ByteOrder;
2278 cinfo.err = jpeg_std_error (&jerr);
2279 jpeg_create_decompress (&cinfo);
2280 while (trow < m_RawHeight) {
2281 fseek (m_InputFile, save+=4, SEEK_SET);
2282 if (m_TileLength < INT_MAX)
2283 fseek (m_InputFile, get4(), SEEK_SET);
2284 jpeg_stdio_src (&cinfo, m_InputFile);
2285 jpeg_read_header (&cinfo, TRUE);
2286 jpeg_start_decompress (&cinfo);
2287 buf = (*cinfo.mem->alloc_sarray)
2288 ((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width*3, 1);
2289 while (cinfo.output_scanline < cinfo.output_height &&
2290 (row = trow + cinfo.output_scanline) < m_Height) {
2291 jpeg_read_scanlines (&cinfo, buf, 1);
2292 pixel = (JSAMPLE (*)[3]) buf[0];
2293 for (col=0; col < cinfo.output_width && tcol+col < m_Width; col++) {
2294 for (c=0; c<3; c++) m_Image[row*m_Width+tcol+col][c] = curve[c][pixel[col][c]];
2295 }
2296 }
2297 jpeg_abort_decompress (&cinfo);
2298 if ((tcol += m_TileWidth) >= m_RawWidth)
2299 trow += m_TileLength + (tcol = 0);
2300 }
2301 jpeg_destroy_decompress (&cinfo);
2302 m_WhiteLevel = 0xffff;
2303 }
2304 #endif
2305
kodak_dc120_load_raw()2306 void CLASS kodak_dc120_load_raw()
2307 {
2308 static const int mul[4] = { 162, 192, 187, 92 };
2309 static const int add[4] = { 0, 636, 424, 212 };
2310 uint8_t pixel[848];
2311 int row, shift, col;
2312
2313 for (row=0; row < m_Height; row++) {
2314 if (fread (pixel, 1, 848, m_InputFile) < 848) derror();
2315 shift = row * mul[row & 3] + add[row & 3];
2316 for (col=0; col < m_Width; col++)
2317 RAW(row,col) = (uint16_t) pixel[(col + shift) % 848];
2318 }
2319 m_WhiteLevel = 0xff;
2320 }
2321
eight_bit_load_raw()2322 void CLASS eight_bit_load_raw()
2323 {
2324 uint8_t *pixel;
2325 unsigned row, col;
2326
2327 pixel = (uint8_t *) CALLOC (m_RawWidth, sizeof *pixel);
2328 merror (pixel, "eight_bit_load_raw()");
2329 for (row=0; row < m_RawHeight; row++) {
2330 if (fread (pixel, 1, m_RawWidth, m_InputFile) < m_RawWidth) derror();
2331 for (col=0; col < m_RawWidth; col++)
2332 RAW(row,col) = m_Curve[pixel[col]];
2333 }
2334 FREE (pixel);
2335 m_WhiteLevel = m_Curve[0xff];
2336 }
2337
kodak_yrgb_load_raw()2338 void CLASS kodak_yrgb_load_raw()
2339 {
2340 uint8_t *pixel;
2341 int row, col, y, cb, cr, rgb[3], c;
2342
2343 pixel = (uint8_t *) CALLOC (m_RawWidth, 3*sizeof *pixel);
2344 merror (pixel, "kodak_yrgb_load_raw()");
2345 for (row=0; row < m_Height; row++) {
2346 if (~row & 1)
2347 if (fread (pixel, m_RawWidth, 3, m_InputFile) < 3) derror();
2348 for (col=0; col < m_RawWidth; col++) {
2349 y = pixel[m_Width*2*(row & 1) + col];
2350 cb = pixel[m_Width + (col & -2)] - 128;
2351 cr = pixel[m_Width + (col & -2)+1] - 128;
2352 rgb[1] = y-((cb + cr + 2) >> 2);
2353 rgb[2] = rgb[1] + cb;
2354 rgb[0] = rgb[1] + cr;
2355 for (c=0;c<3;c++) m_Image[row*m_Width+col][c] = m_Curve[LIM(rgb[c],0,255)];
2356 }
2357 }
2358 FREE (pixel);
2359 m_WhiteLevel = m_Curve[0xff];
2360 }
2361
kodak_262_load_raw()2362 void CLASS kodak_262_load_raw()
2363 {
2364 static const uint8_t kodak_tree[2][26] =
2365 { { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 },
2366 { 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } };
2367 uint16_t *huff[2];
2368 uint8_t *pixel;
2369 int *strip, ns, c, row, col, chess, pi=0, pi1, pi2, pred, val;
2370 huff[0] = make_decoder (kodak_tree[0]);
2371 huff[1] = make_decoder (kodak_tree[1]);
2372 ns = (m_RawHeight+63) >> 5;
2373 pixel = (uint8_t *) MALLOC (m_RawWidth*32 + ns*4);
2374 merror (pixel, "kodak_262_load_raw()");
2375 strip = (int *) (pixel + m_RawWidth*32);
2376 m_ByteOrder = 0x4d4d;
2377 for(c=0;c<ns;c++) strip[c] = get4();
2378 for (row=0; row < m_RawHeight; row++) {
2379 if ((row & 31) == 0) {
2380 fseek (m_InputFile, strip[row >> 5], SEEK_SET);
2381 getbits(-1);
2382 pi = 0;
2383 }
2384 for (col=0; col < m_RawWidth; col++) {
2385 chess = (row + col) & 1;
2386 pi1 = chess ? pi-2 : pi-m_RawWidth-1;
2387 pi2 = chess ? pi-2*m_RawWidth : pi-m_RawWidth+1;
2388 if (col <= chess) pi1 = -1;
2389 if (pi1 < 0) pi1 = pi2;
2390 if (pi2 < 0) pi2 = pi1;
2391 if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2;
2392 pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
2393 pixel[pi] = val = pred + ljpeg_diff (huff[chess]);
2394 if (val >> 8) derror();
2395 val = m_Curve[pixel[pi++]];
2396 RAW(row,col) = val;
2397 }
2398 }
2399 FREE (pixel);
2400 FREE (huff[0]);
2401 FREE (huff[1]);
2402 }
2403
kodak_65000_decode(short * out,int bsize)2404 int CLASS kodak_65000_decode (short *out, int bsize)
2405 {
2406 uint8_t c, blen[768];
2407 uint16_t raw[6];
2408 int64_t bitbuf=0;
2409 int save, bits=0, i, j, len, diff;
2410
2411 save = ftell(m_InputFile);
2412 bsize = (bsize + 3) & -4;
2413 for (i=0; i < bsize; i+=2) {
2414 c = fgetc(m_InputFile);
2415 if ((blen[i ] = c & 15) > 12 ||
2416 (blen[i+1] = c >> 4) > 12 ) {
2417 fseek (m_InputFile, save, SEEK_SET);
2418 for (i=0; i < bsize; i+=8) {
2419 read_shorts (raw, 6);
2420 out[i ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
2421 out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
2422 for (j=0; j < 6; j++)
2423 out[i+2+j] = raw[j] & 0xfff;
2424 }
2425 return 1;
2426 }
2427 }
2428 if ((bsize & 7) == 4) {
2429 bitbuf = fgetc(m_InputFile) << 8;
2430 bitbuf += fgetc(m_InputFile);
2431 bits = 16;
2432 }
2433 for (i=0; i < bsize; i++) {
2434 len = blen[i];
2435 if (bits < len) {
2436 for (j=0; j < 32; j+=8)
2437 bitbuf += (int64_t) fgetc(m_InputFile) << (bits+(j^8));
2438 bits += 32;
2439 }
2440 diff = bitbuf & (0xffff >> (16-len));
2441 bitbuf >>= len;
2442 bits -= len;
2443 if ((diff & (1 << (len-1))) == 0)
2444 diff -= (1 << len) - 1;
2445 out[i] = diff;
2446 }
2447 return 0;
2448 }
2449
kodak_65000_load_raw()2450 void CLASS kodak_65000_load_raw()
2451 {
2452 short buf[256];
2453 int row, col, len, pred[2], ret, i;
2454
2455 for (row=0; row < m_Height; row++)
2456 for (col=0; col < m_Width; col+=256) {
2457 pred[0] = pred[1] = 0;
2458 len = MIN (256, m_Width-col);
2459 ret = kodak_65000_decode (buf, len);
2460 for (i=0; i < len; i++)
2461 if ((RAW(row,col+i) = m_Curve[ret ? buf[i] :
2462 (pred[i & 1] += buf[i])]) >> 12) derror();
2463 }
2464 }
2465
kodak_ycbcr_load_raw()2466 void CLASS kodak_ycbcr_load_raw()
2467 {
2468 short buf[384], *bp;
2469 int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
2470 uint16_t *ip;
2471
2472 for (row=0; row < m_Height; row+=2)
2473 for (col=0; col < m_Width; col+=128) {
2474 len = MIN (128, m_Width-col);
2475 kodak_65000_decode (buf, len*3);
2476 y[0][1] = y[1][1] = cb = cr = 0;
2477 for (bp=buf, i=0; i < len; i+=2, bp+=2) {
2478 cb += bp[4];
2479 cr += bp[5];
2480 rgb[1] = -((cb + cr + 2) >> 2);
2481 rgb[2] = rgb[1] + cb;
2482 rgb[0] = rgb[1] + cr;
2483 for (j=0; j < 2; j++)
2484 for (k=0; k < 2; k++) {
2485 if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror();
2486 ip = m_Image[(row+j)*m_Width + col+i+k];
2487 for (c=0; c<3; c++) ip[c] = m_Curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
2488 }
2489 }
2490 }
2491 }
2492
kodak_rgb_load_raw()2493 void CLASS kodak_rgb_load_raw()
2494 {
2495 short buf[768], *bp;
2496 int row, col, len, c, i, rgb[3];
2497 uint16_t *ip=m_Image[0];
2498
2499 if (m_Raw_Image) FREE (m_Raw_Image);
2500 m_Raw_Image = 0;
2501 for (row=0; row < m_Height; row++)
2502 for (col=0; col < m_Width; col+=256) {
2503 len = MIN (256, m_Width-col);
2504 kodak_65000_decode (buf, len*3);
2505 memset (rgb, 0, sizeof rgb);
2506 for (bp=buf, i=0; i < len; i++, ip+=4)
2507 for (c=0; c<3; c++) if ((ip[c] = rgb[c] += *bp++) >> 12) derror();
2508 }
2509 }
2510
kodak_thumb_load_raw()2511 void CLASS kodak_thumb_load_raw()
2512 {
2513 int row, col;
2514 m_Colors = m_ThumbMisc >> 5;
2515 for (row=0; row < m_Height; row++)
2516 for (col=0; col < m_Width; col++)
2517 read_shorts (m_Image[row*m_Width+col], m_Colors);
2518 m_WhiteLevel = (1 << (m_ThumbMisc & 31)) - 1;
2519 }
2520
sony_decrypt(unsigned * data,int len,int start,int key)2521 void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
2522 {
2523 if (start) {
2524 for (m_sony_decrypt_p=0; m_sony_decrypt_p < 4; m_sony_decrypt_p++)
2525 m_sony_decrypt_pad[m_sony_decrypt_p] = key = key * 48828125 + 1;
2526 m_sony_decrypt_pad[3] = m_sony_decrypt_pad[3] << 1 | (m_sony_decrypt_pad[0]^m_sony_decrypt_pad[2]) >> 31;
2527 for (m_sony_decrypt_p=4; m_sony_decrypt_p < 127; m_sony_decrypt_p++)
2528 m_sony_decrypt_pad[m_sony_decrypt_p] = (m_sony_decrypt_pad[m_sony_decrypt_p-4]^m_sony_decrypt_pad[m_sony_decrypt_p-2]) << 1 | (m_sony_decrypt_pad[m_sony_decrypt_p-3]^m_sony_decrypt_pad[m_sony_decrypt_p-1]) >> 31;
2529 for (m_sony_decrypt_p=0; m_sony_decrypt_p < 127; m_sony_decrypt_p++)
2530 m_sony_decrypt_pad[m_sony_decrypt_p] = htonl(m_sony_decrypt_pad[m_sony_decrypt_p]);
2531 }
2532 while (len--)
2533 *data++ ^= m_sony_decrypt_pad[m_sony_decrypt_p++ & 127] = m_sony_decrypt_pad[(m_sony_decrypt_p+1) & 127] ^ m_sony_decrypt_pad[(m_sony_decrypt_p+65) & 127];
2534 }
2535
sony_load_raw()2536 void CLASS sony_load_raw()
2537 {
2538 uint8_t head[40];
2539 uint16_t *pixel;
2540 unsigned i, key; // row, col;
2541 uint16_t row,col;
2542
2543 fseek (m_InputFile, 200896, SEEK_SET);
2544 fseek (m_InputFile, (unsigned) fgetc(m_InputFile)*4 - 1, SEEK_CUR);
2545 m_ByteOrder = 0x4d4d;
2546 key = get4();
2547 fseek (m_InputFile, 164600, SEEK_SET);
2548 ptfread (head, 1, 40, m_InputFile);
2549 sony_decrypt ((unsigned int *) head, 10, 1, key);
2550 for (i=26; i-- > 22; )
2551 key = key << 8 | head[i];
2552 fseek (m_InputFile, m_Data_Offset, SEEK_SET);
2553 for (row=0; row < m_RawHeight; row++) {
2554 pixel = m_Raw_Image + row*m_RawWidth;
2555 if (fread (pixel, 2, m_RawWidth, m_InputFile) < m_RawWidth) derror();
2556 sony_decrypt ((unsigned int *) pixel, m_RawWidth/2, !row, key);
2557 for (col=0; col < m_RawWidth; col++)
2558 if ((pixel[col] = ntohs(pixel[col])) >> 14) derror();
2559 }
2560 m_WhiteLevel = 0x3ff0;
2561 }
2562
sony_arw_load_raw()2563 void CLASS sony_arw_load_raw()
2564 {
2565 uint16_t huff[32768];
2566 static const uint16_t tab[18] =
2567 { 0xf11,0xf10,0xe0f,0xd0e,0xc0d,0xb0c,0xa0b,0x90a,0x809,
2568 0x708,0x607,0x506,0x405,0x304,0x303,0x300,0x202,0x201 };
2569 int i, c, n, col, row, len, diff, sum=0;
2570
2571 for (n=i=0; i < 18; i++)
2572 for (c=0;c<(32768 >> (tab[i] >> 8));c++) huff[n++] = tab[i];
2573
2574 getbits(-1);
2575 for (col = m_RawWidth; col--; )
2576 for (row=0; row < m_RawHeight+1; row+=2) {
2577 if (row == m_RawHeight) row = 1;
2578 len = getbithuff(15,huff);
2579 diff = getbits(len);
2580 if ((diff & (1 << (len-1))) == 0)
2581 diff -= (1 << len) - 1;
2582 if ((sum += diff) >> 12) derror();
2583 if (row < m_Height) RAW(row,col) = sum;
2584 }
2585 }
2586
sony_arw2_load_raw()2587 void CLASS sony_arw2_load_raw()
2588 {
2589 uint8_t *data, *dp;
2590 uint16_t pix[16];
2591 int row, col, val, max, min, imax, imin, sh, bit, i;
2592
2593 data = (uint8_t *) MALLOC (m_RawWidth);
2594 merror (data, "sony_arw2_load_raw()");
2595 for (row=0; row < m_Height; row++) {
2596 ptfread (data, 1, m_RawWidth, m_InputFile);
2597 for (dp=data, col=0; col < m_RawWidth-30; dp+=16) {
2598 max = 0x7ff & (val = sget4(dp));
2599 min = 0x7ff & val >> 11;
2600 imax = 0x0f & val >> 22;
2601 imin = 0x0f & val >> 26;
2602 for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++) {};
2603 for (bit=30, i=0; i < 16; i++)
2604 if (i == imax) pix[i] = max;
2605 else if (i == imin) pix[i] = min;
2606 else {
2607 pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
2608 if (pix[i] > 0x7ff) pix[i] = 0x7ff;
2609 bit += 7;
2610 }
2611 for (i=0; i < 16; i++, col+=2)
2612 RAW(row,col) = m_Curve[pix[i] << 1] >> 2;
2613 col -= col & 1 ? 1:31;
2614 }
2615 }
2616 FREE (data);
2617 }
2618
2619 #define HOLE(row) ((holes >> (((row) - m_RawHeight) & 7)) & 1)
2620
2621 /* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
smal_decode_segment(unsigned seg[2][2],int holes)2622 void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
2623 {
2624 uint8_t hist[3][13] = {
2625 { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
2626 { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
2627 { 3, 3, 0, 0, 63, 47, 31, 15, 0 } };
2628 int low, high=0xff, carry=0, nbits=8;
2629 int pix, s, count, bin, next, i, sym[3];
2630 uint8_t diff, pred[]={0,0};
2631 uint16_t data=0, range=0;
2632
2633 fseek (m_InputFile, seg[0][1]+1, SEEK_SET);
2634 getbits(-1);
2635 for (pix=seg[0][0]; pix < (int32_t)seg[1][0]; pix++) {
2636 for (s=0; s < 3; s++) {
2637 data = data << nbits | getbits(nbits);
2638 if (carry < 0)
2639 carry = (nbits += carry+1) < 1 ? nbits-1 : 0;
2640 while (--nbits >= 0)
2641 if ((data >> nbits & 0xff) == 0xff) break;
2642 if (nbits > 0)
2643 data = ((data & ((1 << (nbits-1)) - 1)) << 1) |
2644 ((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits));
2645 if (nbits >= 0) {
2646 data += getbits(1);
2647 carry = nbits - 8;
2648 }
2649 count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4);
2650 for (bin=0; hist[s][bin+5] > count; bin++) {} ;
2651 low = hist[s][bin+5] * (high >> 4) >> 2;
2652 if (bin) high = hist[s][bin+4] * (high >> 4) >> 2;
2653 high -= low;
2654 for (nbits=0; high << nbits < 128; nbits++) {} ;
2655 range = (range+low) << nbits;
2656 high <<= nbits;
2657 next = hist[s][1];
2658 if (++hist[s][2] > hist[s][3]) {
2659 next = (next+1) & hist[s][0];
2660 hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2;
2661 hist[s][2] = 1;
2662 }
2663 if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) {
2664 if (bin < hist[s][1]) {
2665 #pragma GCC diagnostic push
2666 #pragma GCC diagnostic ignored "-Warray-bounds"
2667 for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--;
2668 #pragma GCC diagnostic pop
2669 } else if (next <= bin)
2670 for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++;
2671 }
2672 hist[s][1] = next;
2673 sym[s] = bin;
2674 }
2675 diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
2676 if (sym[0] & 4)
2677 diff = diff ? -diff : 0x80;
2678 if (unsigned(ftell(m_InputFile) + 12) >= seg[1][1])
2679 diff = 0;
2680 m_Raw_Image[pix] = pred[pix & 1] += diff;
2681 if (!(pix & 1) && HOLE(pix / m_RawWidth)) pix += 2;
2682 }
2683 m_WhiteLevel = 0xff;
2684 }
2685
smal_v6_load_raw()2686 void CLASS smal_v6_load_raw()
2687 {
2688 unsigned seg[2][2];
2689
2690 fseek (m_InputFile, 16, SEEK_SET);
2691 seg[0][0] = 0;
2692 seg[0][1] = get2();
2693 seg[1][0] = m_RawWidth * m_RawHeight;
2694 seg[1][1] = INT_MAX;
2695 smal_decode_segment (seg, 0);
2696 }
2697
median4(int * p)2698 int CLASS median4 (int *p)
2699 {
2700 int min, max, sum, i;
2701
2702 min = max = sum = p[0];
2703 for (i=1; i < 4; i++) {
2704 sum += p[i];
2705 if (min > p[i]) min = p[i];
2706 if (max < p[i]) max = p[i];
2707 }
2708 return (sum - min - max) >> 1;
2709 }
2710
fill_holes(int holes)2711 void CLASS fill_holes (int holes)
2712 {
2713 int row, col, val[4];
2714
2715 for (row=2; row < m_Height-2; row++) {
2716 if (!HOLE(row)) continue;
2717 for (col=1; col < m_Width-1; col+=4) {
2718 val[0] = RAW(row-1,col-1);
2719 val[1] = RAW(row-1,col+1);
2720 val[2] = RAW(row+1,col-1);
2721 val[3] = RAW(row+1,col+1);
2722 RAW(row,col) = median4(val);
2723 }
2724 for (col=2; col < m_Width-2; col+=4)
2725 if (HOLE(row-2) || HOLE(row+2))
2726 RAW(row,col) = (RAW(row,col-2) + RAW(row,col+2)) >> 1;
2727 else {
2728 val[0] = RAW(row,col-2);
2729 val[1] = RAW(row,col+2);
2730 val[2] = RAW(row-2,col);
2731 val[3] = RAW(row+2,col);
2732 RAW(row,col) = median4(val);
2733 }
2734 }
2735 }
2736
smal_v9_load_raw()2737 void CLASS smal_v9_load_raw()
2738 {
2739 unsigned seg[256][2], offset, nseg, holes, i;
2740
2741 fseek (m_InputFile, 67, SEEK_SET);
2742 offset = get4();
2743 nseg = fgetc(m_InputFile);
2744 fseek (m_InputFile, offset, SEEK_SET);
2745 for (i=0; i < nseg*2; i++)
2746 seg[0][i] = get4() + m_Data_Offset*(i & 1);
2747 fseek (m_InputFile, 78, SEEK_SET);
2748 holes = fgetc(m_InputFile);
2749 fseek (m_InputFile, 88, SEEK_SET);
2750 seg[nseg][0] = m_RawHeight * m_RawWidth;
2751 seg[nseg][1] = get4() + m_Data_Offset;
2752 for (i=0; i < nseg; i++)
2753 smal_decode_segment (seg+i, holes);
2754 if (holes) fill_holes (holes);
2755 }
2756
redcine_load_raw()2757 void CLASS redcine_load_raw()
2758 {
2759 #ifndef NO_JASPER
2760 int c, row, col;
2761 jas_stream_t *in;
2762 jas_m_Image_t *jimg;
2763 jas_matrix_t *jmat;
2764 jas_seqent_t *data;
2765 uint16_t *img, *pix;
2766
2767 jas_init();
2768 in = jas_stream_fopen (ifname, "rb");
2769 jas_stream_seek (in, m_Data_Offset+20, SEEK_SET);
2770 jimg = jas_m_Image_decode (in, -1, 0);
2771 if (!jimg) longjmp (failure, 3);
2772 jmat = jas_matrix_create (m_Height/2, m_Width/2);
2773 merror (jmat, "redcine_m_load_raw()");
2774 img = (uint16_t *) calloc ((m_Height+2)*(m_Width+2), 2);
2775 merror (img, "redcine_m_load_raw()");
2776 for (c=0; c<4; c++) {
2777 jas_m_Image_readcmpt (jimg, c, 0, 0, m_Width/2, m_Height/2, jmat);
2778 data = jas_matrix_getref (jmat, 0, 0);
2779 for (row = c >> 1; row < m_Height; row+=2)
2780 for (col = c & 1; col < m_Width; col+=2)
2781 img[(row+1)*(m_Width+2)+col+1] = data[(row/2)*(m_Width/2)+col/2];
2782 }
2783 for (col=1; col <= m_Width; col++) {
2784 img[col] = img[2*(m_Width+2)+col];
2785 img[(m_Height+1)*(m_Width+2)+col] = img[(m_Height-1)*(m_Width+2)+col];
2786 }
2787 for (row=0; row < m_Height+2; row++) {
2788 img[row*(m_Width+2)] = img[row*(m_Width+2)+2];
2789 img[(row+1)*(m_Width+2)-1] = img[(row+1)*(m_Width+2)-3];
2790 }
2791 for (row=1; row <= m_Height; row++) {
2792 pix = img + row*(m_Width+2) + (col = 1 + (FC(row,1) & 1));
2793 for ( ; col <= m_Width; col+=2, pix+=2) {
2794 c = (((pix[0] - 0x800) << 3) +
2795 pix[-(m_Width+2)] + pix[m_Width+2] + pix[-1] + pix[1]) >> 2;
2796 pix[0] = LIM(c,0,4095);
2797 }
2798 }
2799 for (row=0; row < m_Height; row++)
2800 for (col=0; col < m_Width; col++)
2801 RAW(row,col) = m_Curve[img[(row+1)*(m_Width+2)+col+1]];
2802 free (img);
2803 jas_matrix_destroy (jmat);
2804 jas_m_Image_destroy (jimg);
2805 jas_stream_close (in);
2806 #endif
2807 }
2808
2809 /* RESTRICTED code starts here */
2810
foveon_decoder(unsigned size,unsigned code)2811 void CLASS foveon_decoder (unsigned size, unsigned code)
2812 {
2813 struct decode *cur;
2814 // int i, len;
2815 unsigned i,len;
2816
2817 if (!code) {
2818 for (unsigned i=0; i < size; i++)
2819 m_foveon_decoder_huff[i] = get4();
2820 memset (first_decode, 0, sizeof first_decode);
2821 free_decode = first_decode;
2822 }
2823 cur = free_decode++;
2824 if (free_decode > first_decode+2048) {
2825 fprintf (stderr,_("%s: decoder table overflow\n"), m_UserSetting_InputFileName);
2826 longjmp (m_Failure, 2);
2827 }
2828 if (code)
2829 for (i=0; i < size; i++)
2830 if (m_foveon_decoder_huff[i] == code) {
2831 cur->leaf = i;
2832 return;
2833 }
2834 if ((len = code >> 27) > 26) return;
2835 code = (len+1) << 27 | (code & 0x3ffffff) << 1;
2836
2837 cur->branch[0] = free_decode;
2838 foveon_decoder (size, code);
2839 cur->branch[1] = free_decode;
2840 foveon_decoder (size, code+1);
2841 }
2842
foveon_thumb()2843 void CLASS foveon_thumb ()
2844 /* Remember: This function is modified to write the raw’s thumbnail to the
2845 m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
2846 */
2847 // TODO: Tests needed: What format is this? Can it be read by QPixmap?
2848 {
2849 unsigned bwide, row, col, bitbuf=0, bit=1, c, i;
2850 char *buf;
2851 struct decode *dindex;
2852 short pred[3];
2853
2854 bwide = get4();
2855 //fprintf (m_OutputFile, "P6\n%d %d\n255\n", m_ThumbWidth, m_ThumbHeight);
2856 QString dummy = QString("P6\n%1 %2\n255\n").arg(m_ThumbWidth).arg(m_ThumbHeight);
2857 VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
2858 if (bwide > 0) {
2859 if (bwide < (unsigned)(m_ThumbWidth*3)) return;
2860 buf = (char *) MALLOC (bwide);
2861 merror (buf, "foveon_thumb()");
2862 for (row=0; row < m_ThumbHeight; row++) {
2863 ptfread (buf, 1, bwide, m_InputFile);
2864 //ptfwrite (buf, 3, m_ThumbWidth, m_OutputFile);
2865 VAppend(m_Thumb, buf, 3 * m_ThumbWidth);
2866 }
2867 FREE (buf);
2868 return;
2869 }
2870 foveon_decoder (256, 0);
2871
2872 for (row=0; row < m_ThumbHeight; row++) {
2873 memset (pred, 0, sizeof pred);
2874 if (!bit) get4();
2875 for (bit=col=0; col < m_ThumbWidth; col++)
2876 for (c=0; c<3; c++) {
2877 for (dindex=first_decode; dindex->branch[0]; ) {
2878 if ((bit = (bit-1) & 31) == 31)
2879 for (i=0; i < 4; i++)
2880 bitbuf = (bitbuf << 8) + fgetc(m_InputFile);
2881 dindex = dindex->branch[bitbuf >> bit & 1];
2882 }
2883 pred[c] += dindex->leaf;
2884 //fputc (pred[c], m_OutputFile);
2885 #pragma GCC diagnostic push
2886 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
2887 m_Thumb.push_back(pred[c]);
2888 #pragma GCC diagnostic pop
2889 }
2890 }
2891 }
2892
foveon_sd_load_raw()2893 void CLASS foveon_sd_load_raw()
2894 {
2895 struct decode *dindex;
2896 short diff[1024];
2897 unsigned bitbuf=0;
2898 int pred[3], row, col, bit=-1, c, i;
2899
2900 read_shorts ((uint16_t *) diff, 1024);
2901 if (!m_Load_Flags) foveon_decoder (1024, 0);
2902
2903 for (row=0; row < m_Height; row++) {
2904 memset (pred, 0, sizeof pred);
2905 if (!bit && !m_Load_Flags && atoi(m_CameraModel+2) < 14) get4();
2906 for (col=bit=0; col < m_Width; col++) {
2907 if (m_Load_Flags) {
2908 bitbuf = get4();
2909 for (c=0; c<3; c++) pred[2-c] += diff[bitbuf >> c*10 & 0x3ff];
2910 }
2911 else for (c=0; c<3; c++) {
2912 for (dindex=first_decode; dindex->branch[0]; ) {
2913 if ((bit = (bit-1) & 31) == 31)
2914 for (i=0; i < 4; i++)
2915 bitbuf = (bitbuf << 8) + fgetc(m_InputFile);
2916 dindex = dindex->branch[bitbuf >> bit & 1];
2917 }
2918 pred[c] += diff[dindex->leaf];
2919 if (pred[c] >> 16 && ~pred[c] >> 16) derror();
2920 }
2921 for (c=0; c<3; c++) m_Image[row*m_Width+col][c] = pred[c];
2922 }
2923 }
2924 }
2925
foveon_huff(uint16_t * huff)2926 void CLASS foveon_huff (uint16_t *huff)
2927 {
2928 int i, j, clen, code;
2929
2930 huff[0] = 8;
2931 for (i=0; i < 13; i++) {
2932 clen = getc(m_InputFile);
2933 code = getc(m_InputFile);
2934 for (j=0; j < 256 >> clen; )
2935 huff[code+ ++j] = clen << 8 | i;
2936 }
2937 get2();
2938 }
2939
foveon_dp_load_raw()2940 void CLASS foveon_dp_load_raw()
2941 {
2942 unsigned c, roff[4], row, col, diff;
2943 uint16_t huff[258], vpred[2][2], hpred[2];
2944
2945 fseek (m_InputFile, 8, SEEK_CUR);
2946 foveon_huff (huff);
2947 roff[0] = 48;
2948 for (c=0; c<3; c++) roff[c+1] = -(-(roff[c] + get4()) & -16);
2949 for (c=0; c<3; c++) {
2950 fseek (m_InputFile, m_Data_Offset+roff[c], SEEK_SET);
2951 getbits(-1);
2952 vpred[0][0] = vpred[0][1] = vpred[1][0] = vpred[1][1] = 512;
2953 for (row=0; row < m_Height; row++) {
2954 for (col=0; col < m_Width; col++) {
2955 diff = ljpeg_diff(huff);
2956 if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
2957 else hpred[col & 1] += diff;
2958 m_Image[row*m_Width+col][c] = hpred[col & 1];
2959 }
2960 }
2961 }
2962 }
2963
foveon_load_camf()2964 void CLASS foveon_load_camf()
2965 {
2966 unsigned type, wide, high, i, j, row, col, diff;
2967 uint16_t huff[258], vpred[2][2] = {{512,512},{512,512}}, hpred[2];
2968
2969 fseek (m_InputFile, meta_offset, SEEK_SET);
2970 type = get4(); get4(); get4();
2971 wide = get4();
2972 high = get4();
2973 if (type == 2) {
2974 ptfread (m_MetaData, 1, m_MetaLength, m_InputFile);
2975 for (i=0; i < m_MetaLength; i++) {
2976 high = (high * 1597 + 51749) % 244944;
2977 wide = high * (INT64) 301593171 >> 24;
2978 m_MetaData[i] ^= ((((high << 8) - wide) >> 1) + wide) >> 17;
2979 }
2980 } else if (type == 4) {
2981 FREE (m_MetaData);
2982 m_MetaData = (char *) MALLOC (m_MetaLength = wide*high*3/2);
2983 merror (m_MetaData, "foveon_load_camf()");
2984 foveon_huff (huff);
2985 get4();
2986 getbits(-1);
2987 for (j=row=0; row < high; row++) {
2988 for (col=0; col < wide; col++) {
2989 diff = ljpeg_diff(huff);
2990 if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
2991 else hpred[col & 1] += diff;
2992 if (col & 1) {
2993 m_MetaData[j++] = hpred[0] >> 4;
2994 m_MetaData[j++] = hpred[0] << 4 | hpred[1] >> 8;
2995 m_MetaData[j++] = hpred[1];
2996 }
2997 }
2998 }
2999 } else
3000 fprintf (stderr,_("%s has unknown CAMF type %d.\n"), m_UserSetting_InputFileName, type);
3001 }
3002
foveon_camf_param(const char * block,const char * param)3003 const char * CLASS foveon_camf_param (const char *block, const char *param)
3004 {
3005 unsigned idx, num;
3006 char *pos, *cp, *dp;
3007
3008 for (idx=0; idx < m_MetaLength; idx += sget4(pos+8)) {
3009 pos = m_MetaData + idx;
3010 if (strncmp (pos, "CMb", 3)) break;
3011 if (pos[3] != 'P') continue;
3012 if (strcmp (block, pos+sget4(pos+12))) continue;
3013 cp = pos + sget4(pos+16);
3014 num = sget4(cp);
3015 dp = pos + sget4(cp+4);
3016 while (num--) {
3017 cp += 8;
3018 if (!strcmp (param, dp+sget4(cp)))
3019 return dp+sget4(cp+4);
3020 }
3021 }
3022 return 0;
3023 }
3024
foveon_camf_matrix(unsigned dim[3],const char * name)3025 void * CLASS foveon_camf_matrix (unsigned dim[3], const char *name)
3026 {
3027 unsigned i, idx, type, ndim, size, *mat;
3028 char *pos, *cp, *dp;
3029 double dsize;
3030
3031 for (idx=0; idx < m_MetaLength; idx += sget4(pos+8)) {
3032 pos = m_MetaData + idx;
3033 if (strncmp (pos, "CMb", 3)) break;
3034 if (pos[3] != 'M') continue;
3035 if (strcmp (name, pos+sget4(pos+12))) continue;
3036 dim[0] = dim[1] = dim[2] = 1;
3037 cp = pos + sget4(pos+16);
3038 type = sget4(cp);
3039 if ((ndim = sget4(cp+4)) > 3) break;
3040 dp = pos + sget4(cp+8);
3041 for (i=ndim; i--; ) {
3042 cp += 12;
3043 dim[i] = sget4(cp);
3044 }
3045 if ((dsize = (double) dim[0]*dim[1]*dim[2]) > m_MetaLength/4) break;
3046 mat = (unsigned *) MALLOC ((size = (unsigned) dsize) * 4);
3047 merror (mat, "foveon_camf_matrix()");
3048 for (i=0; i < size; i++)
3049 if (type && type != 6)
3050 mat[i] = sget4(dp + i*4);
3051 else
3052 mat[i] = sget4(dp + i*2) & 0xffff;
3053 return mat;
3054 }
3055 fprintf (stderr,_("%s: \"%s\" matrix not found!\n"), m_UserSetting_InputFileName, name);
3056 return 0;
3057 }
3058
foveon_fixed(void * ptr,int size,const char * name)3059 int CLASS foveon_fixed (void *ptr, int size, const char *name)
3060 {
3061 void *dp;
3062 unsigned dim[3];
3063
3064 if (!name) return 0;
3065 dp = foveon_camf_matrix (dim, name);
3066 if (!dp) return 0;
3067 memcpy (ptr, dp, size*4);
3068 FREE (dp);
3069 return 1;
3070 }
3071
foveon_avg(short * pix,int range[2],float cfilt)3072 float CLASS foveon_avg (short *pix, int range[2], float cfilt)
3073 {
3074 int i;
3075 float val, min=FLT_MAX, max=-FLT_MAX, sum=0;
3076
3077 for (i=range[0]; i <= range[1]; i++) {
3078 sum += val = pix[i*4] + (pix[i*4]-pix[(i-1)*4]) * cfilt;
3079 if (min > val) min = val;
3080 if (max < val) max = val;
3081 }
3082 if (range[1] - range[0] == 1) return sum/2;
3083 return (sum - min - max) / (range[1] - range[0] - 1);
3084 }
3085
foveon_make_curve(double max,double mul,double filt)3086 short * CLASS foveon_make_curve (double max, double mul, double filt)
3087 {
3088 short *curve;
3089 unsigned i, size;
3090 double x;
3091
3092 if (!filt) filt = 0.8;
3093 size = (unsigned) (4*ptPI*max / filt);
3094 if (size == UINT_MAX) size--;
3095 curve = (short *) CALLOC (size+1, sizeof *curve);
3096 merror (curve, "foveon_make_curve()");
3097 curve[0] = size;
3098 for (i=0; i < size; i++) {
3099 x = i*filt/max/4;
3100 curve[i+1] = (short) ((cos(x)+1)/2 * tanh(i*filt/mul) * mul + 0.5);
3101 }
3102 return curve;
3103 }
3104
foveon_make_curves(short ** curvep,float dq[3],float div[3],float filt)3105 void CLASS foveon_make_curves
3106 (short **curvep, float dq[3], float div[3], float filt)
3107 {
3108 double mul[3], max=0;
3109 int c;
3110
3111 for (c=0; c<3; c++) mul[c] = dq[c]/div[c];
3112 for (c=0; c<3; c++) if (max < mul[c]) max = mul[c];
3113 for (c=0; c<3; c++) curvep[c] = foveon_make_curve (max, mul[c], filt);
3114 }
3115
foveon_apply_curve(short * l_Curve,int i)3116 int CLASS foveon_apply_curve (short *l_Curve, int i)
3117 {
3118 if (abs(i) >= l_Curve[0]) return 0;
3119 return i < 0 ? -l_Curve[1-i] : l_Curve[1+i];
3120 }
3121
3122 #define m_Image ((short (*)[4]) m_Image)
3123
foveon_interpolate()3124 void CLASS foveon_interpolate()
3125 {
3126 // Loop optimization causes an "undefined behaviour" compiler warning. I just disable
3127 // the warning here instead of fixing the problem because Photivo does not support
3128 // Foveon anyway, but I’m not positive that removing this function wouldn’t break
3129 // DCRaw in some way.
3130 #pragma GCC diagnostic push
3131 #pragma GCC diagnostic ignored "-Warray-bounds"
3132 #pragma GCC diagnostic ignored "-Waggressive-loop-optimizations"
3133 static const short hood[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 };
3134 short *pix, prev[3], *l_curve[8], (*shrink)[3];
3135 float cfilt=0, ddft[3][3][2], ppm[3][3][3];
3136 float cam_xyz[3][3], correct[3][3], last[3][3], trans[3][3];
3137 float chroma_dq[3], color_dq[3], diag[3][3], div[3];
3138 float (*black)[3], (*sgain)[3], (*sgrow)[3];
3139 float fsum[3], val, frow, num;
3140 int row, col, c, i, j, diff, sgx, irow, sum, min, max, limit;
3141 int dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3];
3142 int work[3][3], smlast, smred, smred_p=0, dev[3];
3143 int satlev[3], keep[4], active[4];
3144 unsigned dim[3], *badpix;
3145 double dsum=0, trsum[3];
3146 char str[128];
3147 const char* cp;
3148
3149 memset(cam_xyz, 0, sizeof(cam_xyz));
3150 memset(dscr, 0, sizeof(dscr));
3151 memset(dstb, 0, sizeof(dstb));
3152 memset(active, 0, sizeof(active));
3153 memset(keep, 0, sizeof(keep));
3154
3155 TRACEKEYVALS("Foveon interpolation","%s","");
3156
3157 foveon_load_camf();
3158 foveon_fixed (dscr, 4, "DarkShieldColRange");
3159 foveon_fixed (ppm[0][0], 27, "PostPolyMatrix");
3160 foveon_fixed (satlev, 3, "SaturationLevel");
3161 foveon_fixed (keep, 4, "KeepImageArea");
3162 foveon_fixed (active, 4, "ActiveImageArea");
3163 foveon_fixed (chroma_dq, 3, "ChromaDQ");
3164 foveon_fixed (color_dq, 3,
3165 foveon_camf_param ("IncludeBlocks", "ColorDQ") ?
3166 "ColorDQ" : "ColorDQCamRGB");
3167 if (foveon_camf_param ("IncludeBlocks", "ColumnFilter"))
3168 foveon_fixed (&cfilt, 1, "ColumnFilter");
3169
3170 memset (ddft, 0, sizeof ddft);
3171 if (!foveon_camf_param ("IncludeBlocks", "DarkDrift")
3172 || !foveon_fixed (ddft[1][0], 12, "DarkDrift"))
3173 for (i=0; i < 2; i++) {
3174 foveon_fixed (dstb, 4, i ? "DarkShieldBottom":"DarkShieldTop");
3175 for (row = dstb[1]; row <= dstb[3]; row++)
3176 for (col = dstb[0]; col <= dstb[2]; col++)
3177 for (c=0; c<3; c++) ddft[i+1][c][1] += (short) m_Image[row*m_Width+col][c];
3178 for (c=0; c<3; c++) ddft[i+1][c][1] /= (dstb[3]-dstb[1]+1) * (dstb[2]-dstb[0]+1);
3179 }
3180
3181 if (!(cp = foveon_camf_param ("WhiteBalanceIlluminants", m_CameraModelBis)))
3182 { fprintf (stderr,_("%s: Invalid white balance \"%s\"\n"), m_UserSetting_InputFileName, m_CameraModelBis);
3183 return; }
3184 foveon_fixed (cam_xyz, 9, cp);
3185 foveon_fixed (correct, 9,
3186 foveon_camf_param ("WhiteBalanceCorrections", m_CameraModelBis));
3187 memset (last, 0, sizeof last);
3188 for (i=0; i < 3; i++)
3189 for (j=0; j < 3; j++)
3190 for (c=0; c<3; c++) last[i][j] += correct[i][c] * cam_xyz[c][j];
3191
3192 #define LAST(x,y) last[(i+x)%3][(c+y)%3]
3193 for (i=0; i < 3; i++)
3194 for (c=0; c<3; c++) diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1);
3195 #undef LAST
3196 for (c=0; c<3; c++) div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583;
3197 sprintf (str, "%sRGBNeutral", m_CameraModelBis);
3198 if (foveon_camf_param ("IncludeBlocks", str))
3199 foveon_fixed (div, 3, str);
3200 num = 0;
3201 for (c=0; c<3; c++) if (num < div[c]) num = div[c];
3202 for (c=0; c<3; c++) div[c] /= num;
3203
3204 memset (trans, 0, sizeof trans);
3205 for (i=0; i < 3; i++)
3206 for (j=0; j < 3; j++)
3207 for (c=0; c<3; c++) trans[i][j] += m_MatrixCamRGBToSRGB[i][c] * last[c][j] * div[j];
3208 for (c=0; c<3; c++) trsum[c] = trans[c][0] + trans[c][1] + trans[c][2];
3209 dsum = (6*trsum[0] + 11*trsum[1] + 3*trsum[2]) / 20;
3210 for (i=0; i < 3; i++)
3211 for (c=0; c<3; c++) last[i][c] = trans[i][c] * dsum / trsum[i];
3212 memset (trans, 0, sizeof trans);
3213 for (i=0; i < 3; i++)
3214 for (j=0; j < 3; j++)
3215 for (c=0; c<3; c++) trans[i][j] += (i==c ? 32 : -1) * last[c][j] / 30;
3216
3217 foveon_make_curves (l_curve, color_dq, div, cfilt);
3218 for (c=0; c<3; c++) chroma_dq[c] /= 3;
3219 foveon_make_curves (l_curve+3, chroma_dq, div, cfilt);
3220 for (c=0; c<3; c++) dsum += chroma_dq[c] / div[c];
3221 l_curve[6] = foveon_make_curve (dsum, dsum, cfilt);
3222 l_curve[7] = foveon_make_curve (dsum*2, dsum*2, cfilt);
3223
3224 sgain = (float (*)[3]) foveon_camf_matrix (dim, "SpatialGain");
3225 if (!sgain) return;
3226 sgrow = (float (*)[3]) CALLOC (dim[1], sizeof *sgrow);
3227 sgx = (m_Width + dim[1]-2) / (dim[1]-1);
3228
3229 black = (float (*)[3]) CALLOC (m_Height, sizeof *black);
3230 for (row=0; row < m_Height; row++) {
3231 for (i=0; i < 6; i++)
3232 ddft[0][0][i] = ddft[1][0][i] +
3233 row / (m_Height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
3234 for (c=0; c<3; c++) black[row][c] =
3235 ( foveon_avg (m_Image[row*m_Width]+c, dscr[0], cfilt) +
3236 foveon_avg (m_Image[row*m_Width]+c, dscr[1], cfilt) * 3
3237 - ddft[0][c][0] ) / 4 - ddft[0][c][1];
3238 }
3239 memcpy (black, black+8, sizeof *black*8);
3240 memcpy (black+m_Height-11, black+m_Height-22, 11*sizeof *black);
3241 memcpy (last, black, sizeof last);
3242
3243 for (row=1; row < m_Height-1; row++) {
3244 for (c=0; c<3; c++) if (last[1][c] > last[0][c]) {
3245 if (last[1][c] > last[2][c])
3246 black[row][c] = (last[0][c] > last[2][c]) ? last[0][c]:last[2][c];
3247 } else
3248 if (last[1][c] < last[2][c])
3249 black[row][c] = (last[0][c] < last[2][c]) ? last[0][c]:last[2][c];
3250 memmove (last, last+1, 2*sizeof last[0]);
3251 memcpy (last[2], black[row+1], sizeof last[2]);
3252 }
3253 for (c=0; c<3; c++) black[row][c] = (last[0][c] + last[1][c])/2;
3254 for (c=0; c<3; c++) black[0][c] = (black[1][c] + black[3][c])/2;
3255
3256 val = 1 - exp(-1/24.0);
3257 memcpy (fsum, black, sizeof fsum);
3258 for (row=1; row < m_Height; row++)
3259 for (c=0; c<3; c++) fsum[c] += black[row][c] =
3260 (black[row][c] - black[row-1][c])*val + black[row-1][c];
3261 memcpy (last[0], black[m_Height-1], sizeof last[0]);
3262 for (c=0; c<3; c++) fsum[c] /= m_Height;
3263 for (row = m_Height; row--; )
3264 for (c=0; c<3; c++) last[0][c] = black[row][c] =
3265 (black[row][c] - fsum[c] - last[0][c])*val + last[0][c];
3266
3267 memset (total, 0, sizeof total);
3268 for (row=2; row < m_Height; row+=4)
3269 for (col=2; col < m_Width; col+=4) {
3270 for (c=0; c<3; c++) total[c] += (short) m_Image[row*m_Width+col][c];
3271 total[3]++;
3272 }
3273 for (row=0; row < m_Height; row++)
3274 for (c=0; c<3; c++) black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0);
3275
3276 for (row=0; row < m_Height; row++) {
3277 for (i=0; i < 6; i++)
3278 ddft[0][0][i] = ddft[1][0][i] +
3279 row / (m_Height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
3280 pix = m_Image[row*m_Width];
3281 memcpy (prev, pix, sizeof prev);
3282 frow = row / (m_Height-1.0) * (dim[2]-1);
3283 if ((unsigned)(irow = (int)(frow)) == dim[2]-1) irow--;
3284 frow -= irow;
3285 for (i=0; (unsigned) i < dim[1]; i++)
3286 for (c=0; c<3; c++) sgrow[i][c] = sgain[ irow *dim[1]+i][c] * (1-frow) +
3287 sgain[(irow+1)*dim[1]+i][c] * frow;
3288 for (col=0; col < m_Width; col++) {
3289 for (c=0; c<3; c++) {
3290 diff = pix[c] - prev[c];
3291 prev[c] = pix[c];
3292 ipix[c] = (int)(pix[c] + floor ((diff + (diff*diff >> 14)) * cfilt
3293 - ddft[0][c][1] - ddft[0][c][0] * ((float) col/m_Width - 0.5)
3294 - black[row][c] ));
3295 }
3296 for (c=0; c<3; c++) {
3297 work[0][c] = ipix[c] * ipix[c] >> 14;
3298 work[2][c] = ipix[c] * work[0][c] >> 14;
3299 work[1][2-c] = ipix[(c+1) % 3] * ipix[(c+2) % 3] >> 14;
3300 }
3301 for (c=0; c<3; c++) {
3302 for (val=i=0; i < 3; i++)
3303 for ( j=0; j < 3; j++)
3304 val += ppm[c][i][j] * work[i][j];
3305 ipix[c] = (int) (floor ((ipix[c] + floor(val)) *
3306 ( sgrow[col/sgx ][c] * (sgx - col%sgx) +
3307 sgrow[col/sgx+1][c] * (col%sgx) ) / sgx / div[c]));
3308 if (ipix[c] > 32000) ipix[c] = 32000;
3309 pix[c] = ipix[c];
3310 }
3311 pix += 4;
3312 }
3313 }
3314 FREE (black);
3315 FREE (sgrow);
3316 FREE (sgain);
3317
3318 if ((badpix = (unsigned int *) foveon_camf_matrix (dim, "BadPixels"))) {
3319 for (i=0; (unsigned) i < dim[0]; i++) {
3320 col = (badpix[i] >> 8 & 0xfff) - keep[0];
3321 row = (badpix[i] >> 20 ) - keep[1];
3322 if ((unsigned)(row-1) > (unsigned)(m_Height-3) || (unsigned)(col-1) > (unsigned)(m_Width-3))
3323 continue;
3324 memset (fsum, 0, sizeof fsum);
3325 for (sum=j=0; j < 8; j++)
3326 if (badpix[i] & (1 << j)) {
3327 for (c=0; c<3; c++) fsum[c] += (short)
3328 m_Image[(row+hood[j*2])*m_Width+col+hood[j*2+1]][c];
3329 sum++;
3330 }
3331 if (sum) for (c=0; c<3; c++) m_Image[row*m_Width+col][c] = (short) (fsum[c]/sum);
3332 }
3333 FREE (badpix);
3334 }
3335
3336 /* Array for 5x5 Gaussian averaging of red values */
3337 smrow[6] = (int (*)[3]) CALLOC (m_Width*5, sizeof **smrow);
3338 merror (smrow[6], "foveon_interpolate()");
3339 for (i=0; i < 5; i++)
3340 smrow[i] = smrow[6] + i*m_Width;
3341
3342 /* Sharpen the reds against these Gaussian averages */
3343 for (smlast=-1, row=2; row < m_Height-2; row++) {
3344 while (smlast < row+2) {
3345 for (i=0; i < 6; i++)
3346 smrow[(i+5) % 6] = smrow[i];
3347 pix = m_Image[++smlast*m_Width+2];
3348 for (col=2; col < m_Width-2; col++) {
3349 smrow[4][col][0] =
3350 (pix[0]*6 + (pix[-4]+pix[4])*4 + pix[-8]+pix[8] + 8) >> 4;
3351 pix += 4;
3352 }
3353 }
3354 pix = m_Image[row*m_Width+2];
3355 for (col=2; col < m_Width-2; col++) {
3356 smred = ( 6 * smrow[2][col][0]
3357 + 4 * (smrow[1][col][0] + smrow[3][col][0])
3358 + smrow[0][col][0] + smrow[4][col][0] + 8 ) >> 4;
3359 if (col == 2)
3360 smred_p = smred;
3361 i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 3);
3362 if (i > 32000) i = 32000;
3363 pix[0] = i;
3364 smred_p = smred;
3365 pix += 4;
3366 }
3367 }
3368
3369 /* Adjust the brighter pixels for better linearity */
3370 min = 0xffff;
3371 for (c=0; c<3; c++) {
3372 i = (int)(satlev[c] / div[c]);
3373 if (min > i) min = i;
3374 }
3375 limit = min * 9 >> 4;
3376 for (pix=m_Image[0]; pix < m_Image[m_Height*m_Width]; pix+=4) {
3377 if (pix[0] <= limit || pix[1] <= limit || pix[2] <= limit)
3378 continue;
3379 min = max = pix[0];
3380 for (c=1; c < 3; c++) {
3381 if (min > pix[c]) min = pix[c];
3382 if (max < pix[c]) max = pix[c];
3383 }
3384 if (min >= limit*2) {
3385 pix[0] = pix[1] = pix[2] = max;
3386 } else {
3387 i = 0x4000 - ((min - limit) << 14) / limit;
3388 i = 0x4000 - (i*i >> 14);
3389 i = i*i >> 14;
3390 for (c=0; c<3; c++) pix[c] += (max - pix[c]) * i >> 14;
3391 }
3392 }
3393 /*
3394 Because photons that miss one detector often hit another,
3395 the sum R+G+B is much less noisy than the individual colors.
3396 So smooth the hues without smoothing the total.
3397 */
3398 for (smlast=-1, row=2; row < m_Height-2; row++) {
3399 while (smlast < row+2) {
3400 for (i=0; i < 6; i++)
3401 smrow[(i+5) % 6] = smrow[i];
3402 pix = m_Image[++smlast*m_Width+2];
3403 for (col=2; col < m_Width-2; col++) {
3404 for (c=0; c<3; c++) smrow[4][col][c] = (pix[c-4]+2*pix[c]+pix[c+4]+2) >> 2;
3405 pix += 4;
3406 }
3407 }
3408 pix = m_Image[row*m_Width+2];
3409 for (col=2; col < m_Width-2; col++) {
3410 for (c=0; c<3; c++) dev[c] = -foveon_apply_curve (l_curve[7], pix[c] -
3411 ((smrow[1][col][c] + 2*smrow[2][col][c] + smrow[3][col][c]) >> 2));
3412 sum = (dev[0] + dev[1] + dev[2]) >> 3;
3413 for (c=0; c<3; c++) pix[c] += dev[c] - sum;
3414 pix += 4;
3415 }
3416 }
3417 for (smlast=-1, row=2; row < m_Height-2; row++) {
3418 while (smlast < row+2) {
3419 for (i=0; i < 6; i++)
3420 smrow[(i+5) % 6] = smrow[i];
3421 pix = m_Image[++smlast*m_Width+2];
3422 for (col=2; col < m_Width-2; col++) {
3423 for (c=0; c<3; c++) smrow[4][col][c] =
3424 (pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8]+2) >> 2;
3425 pix += 4;
3426 }
3427 }
3428 pix = m_Image[row*m_Width+2];
3429 for (col=2; col < m_Width-2; col++) {
3430 for (total[3]=375, sum=60, c=0; c < 3; c++) {
3431 for (total[c]=i=0; i < 5; i++)
3432 total[c] += smrow[i][col][c];
3433 total[3] += total[c];
3434 sum += pix[c];
3435 }
3436 if (sum < 0) sum = 0;
3437 j = total[3] > 375 ? (sum << 16) / total[3] : sum * 174;
3438 for (c=0; c<3; c++) pix[c] += foveon_apply_curve (l_curve[6],
3439 ((j*total[c] + 0x8000) >> 16) - pix[c]);
3440 pix += 4;
3441 }
3442 }
3443
3444 /* Transform the image to a different colorspace */
3445 for (pix=m_Image[0]; pix < m_Image[m_Height*m_Width]; pix+=4) {
3446 for (c=0; c<3; c++) pix[c] -= foveon_apply_curve (l_curve[c], pix[c]);
3447 sum = (pix[0]+pix[1]+pix[1]+pix[2]) >> 2;
3448 for (c=0; c<3; c++) pix[c] -= foveon_apply_curve (l_curve[c], pix[c]-sum);
3449 for (c=0; c<3; c++) {
3450 for (dsum=i=0; i < 3; i++)
3451 dsum += trans[c][i] * pix[i];
3452 if (dsum < 0) dsum = 0;
3453 if (dsum > 24000) dsum = 24000;
3454 ipix[c] = (int)(dsum + 0.5);
3455 }
3456 for (c=0; c<3; c++) pix[c] = ipix[c];
3457 }
3458
3459 /* Smooth the image bottom-to-top and save at 1/4 scale */
3460 shrink = (short (*)[3]) CALLOC ((m_Width/4) * (m_Height/4), sizeof *shrink);
3461 merror (shrink, "foveon_interpolate()");
3462 for (row = m_Height/4; row--; )
3463 for (col=0; col < m_Width/4; col++) {
3464 ipix[0] = ipix[1] = ipix[2] = 0;
3465 for (i=0; i < 4; i++)
3466 for (j=0; j < 4; j++)
3467 for (c=0; c<3; c++) ipix[c] += m_Image[(row*4+i)*m_Width+col*4+j][c];
3468 for (c=0; c<3; c++)
3469 if (row+2 > m_Height/4)
3470 shrink[row*(m_Width/4)+col][c] = ipix[c] >> 4;
3471 else
3472 shrink[row*(m_Width/4)+col][c] =
3473 (shrink[(row+1)*(m_Width/4)+col][c]*1840 + ipix[c]*141 + 2048) >> 12;
3474 }
3475 /* From the 1/4-scale image, smooth right-to-left */
3476 for (row=0; row < (m_Height & ~3); row++) {
3477 ipix[0] = ipix[1] = ipix[2] = 0;
3478 if ((row & 3) == 0)
3479 for (col = m_Width & ~3 ; col--; )
3480 for (c=0; c<3; c++) smrow[0][col][c] = ipix[c] =
3481 (shrink[(row/4)*(m_Width/4)+col/4][c]*1485 + ipix[c]*6707 + 4096) >> 13;
3482
3483 /* Then smooth left-to-right */
3484 ipix[0] = ipix[1] = ipix[2] = 0;
3485 for (col=0; col < (m_Width & ~3); col++)
3486 for (c=0; c<3; c++) smrow[1][col][c] = ipix[c] =
3487 (smrow[0][col][c]*1485 + ipix[c]*6707 + 4096) >> 13;
3488
3489 /* Smooth top-to-bottom */
3490 if (row == 0)
3491 memcpy (smrow[2], smrow[1], sizeof **smrow * m_Width);
3492 else
3493 for (col=0; col < (m_Width & ~3); col++)
3494 for (c=0; c<3; c++) smrow[2][col][c] =
3495 (smrow[2][col][c]*6707 + smrow[1][col][c]*1485 + 4096) >> 13;
3496
3497 /* Adjust the chroma toward the smooth values */
3498 for (col=0; col < (m_Width & ~3); col++) {
3499 for (i=j=30, c=0; c < 3; c++) {
3500 i += smrow[2][col][c];
3501 j += m_Image[row*m_Width+col][c];
3502 }
3503 j = (j << 16) / i;
3504 for (sum=c=0; c < 3; c++) {
3505 ipix[c] = foveon_apply_curve (l_curve[c+3],
3506 ((smrow[2][col][c] * j + 0x8000) >> 16) - m_Image[row*m_Width+col][c]);
3507 sum += ipix[c];
3508 }
3509 sum >>= 3;
3510 for (c=0; c<3; c++) {
3511 i = m_Image[row*m_Width+col][c] + ipix[c] - sum;
3512 if (i < 0) i = 0;
3513 m_Image[row*m_Width+col][c] = i;
3514 }
3515 }
3516 }
3517 FREE (shrink);
3518 FREE (smrow[6]);
3519 for (i=0; i < 8; i++)
3520 FREE (l_curve[i]);
3521
3522 /* Trim off the black border */
3523 active[1] -= keep[1];
3524 active[3] -= 2;
3525 i = active[2] - active[0];
3526 for (row=0; row < active[3]-active[1]; row++)
3527 memcpy (m_Image[row*i], m_Image[(row+active[1])*m_Width+active[0]],
3528 i * sizeof *m_Image);
3529 m_Width = i;
3530 m_Height = row;
3531 #pragma GCC diagnostic pop
3532 }
3533 #undef m_Image
3534
3535 /* RESTRICTED code ends here */
3536
crop_masked_pixels()3537 void CLASS crop_masked_pixels()
3538 {
3539 int row, col;
3540 unsigned r, c, m, mm_BlackLevel[8], zero, val;
3541
3542 if (m_LoadRawFunction == &CLASS phase_one_load_raw ||
3543 m_LoadRawFunction == &CLASS phase_one_load_raw_c)
3544 phase_one_correct();
3545 if (m_Fuji_Width) {
3546 for (row=0; row < m_RawHeight-m_TopMargin*2; row++) {
3547 for (col=0; col < m_Fuji_Width << !fuji_layout; col++) {
3548 if (fuji_layout) {
3549 r = m_Fuji_Width - 1 - col + (row >> 1);
3550 c = col + ((row+1) >> 1);
3551 } else {
3552 r = m_Fuji_Width - 1 + row - (col >> 1);
3553 c = row + ((col+1) >> 1);
3554 }
3555 if (r < m_Height && c < m_Width)
3556 BAYER(r,c) = RAW(row+m_TopMargin,col+m_LeftMargin);
3557 }
3558 }
3559 } else {
3560 for (row=0; row < m_Height; row++)
3561 for (col=0; col < m_Width; col++)
3562 BAYER2(row,col) = RAW(row+m_TopMargin,col+m_LeftMargin);
3563 }
3564 if (m_Mask[0][3]) goto mask_set;
3565 if (m_LoadRawFunction == &CLASS canon_load_raw ||
3566 m_LoadRawFunction == &CLASS lossless_jpeg_load_raw) {
3567 m_Mask[0][1] = m_Mask[1][1] = 2;
3568 m_Mask[0][3] = -2;
3569 goto sides;
3570 }
3571 if (m_LoadRawFunction == &CLASS canon_600_load_raw ||
3572 m_LoadRawFunction == &CLASS sony_load_raw ||
3573 (m_LoadRawFunction == &CLASS eight_bit_load_raw && strncmp(m_CameraModel,"DC2",3)) ||
3574 m_LoadRawFunction == &CLASS kodak_262_load_raw ||
3575 (m_LoadRawFunction == &CLASS packed_load_raw && (m_Load_Flags & 32))) {
3576 sides:
3577 m_Mask[0][0] = m_Mask[1][0] = m_TopMargin;
3578 m_Mask[0][2] = m_Mask[1][2] = m_TopMargin+m_Height;
3579 m_Mask[0][3] += m_LeftMargin;
3580 m_Mask[1][1] += m_LeftMargin+m_Width;
3581 m_Mask[1][3] += m_RawWidth;
3582 }
3583 if (m_LoadRawFunction == &CLASS nokia_load_raw) {
3584 m_Mask[0][2] = m_TopMargin;
3585 m_Mask[0][3] = m_Width;
3586 }
3587 mask_set:
3588 memset (mm_BlackLevel, 0, sizeof mm_BlackLevel);
3589 for (zero=m=0; m < 8; m++)
3590 for (row=m_Mask[m][0]; row < m_Mask[m][2]; row++)
3591 for (col=m_Mask[m][1]; col < m_Mask[m][3]; col++) {
3592 c = FC(row-m_TopMargin,col-m_LeftMargin);
3593 mm_BlackLevel[c] += val = RAW(row,col);
3594 mm_BlackLevel[4+c]++;
3595 zero += !val;
3596 }
3597 if (m_LoadRawFunction == &CLASS canon_600_load_raw && m_Width < m_RawWidth) {
3598 m_BlackLevel = (mm_BlackLevel[0]+mm_BlackLevel[1]+mm_BlackLevel[2]+mm_BlackLevel[3]) /
3599 (mm_BlackLevel[4]+mm_BlackLevel[5]+mm_BlackLevel[6]+mm_BlackLevel[7]) - 4;
3600 canon_600_correct();
3601 } else if (zero < mm_BlackLevel[4] && mm_BlackLevel[5] && mm_BlackLevel[6] && mm_BlackLevel[7])
3602 for (c=0; c<4; c++) m_CBlackLevel[c] = mm_BlackLevel[c] / mm_BlackLevel[4+c];
3603 }
3604
remove_zeroes()3605 void CLASS remove_zeroes()
3606 {
3607 unsigned row, col, tot, n, r, c;
3608
3609 for (row=0; row < m_Height; row++)
3610 for (col=0; col < m_Width; col++)
3611 if (BAYER(row,col) == 0) {
3612 tot = n = 0;
3613 for (r = row-2; r <= row+2; r++)
3614 for (c = col-2; c <= col+2; c++)
3615 if (r < m_Height && c < m_Width &&
3616 FC(r,c) == FC(row,col) && BAYER(r,c))
3617 tot += (n++,BAYER(r,c));
3618 if (n) BAYER(row,col) = tot/n;
3619 }
3620 }
3621
3622 /*
3623 Seach from the current directory up to the root looking for
3624 a ".badpixels" file, and fix those pixels now.
3625 */
bad_pixels(const char * cfname)3626 void CLASS bad_pixels (const char *cfname)
3627 {
3628 FILE *fp=0;
3629 char *cp, line[128];
3630 int /* len, */ time, row, col, r, c, rad, tot, n;
3631
3632 if (!m_Filters) return;
3633 if (cfname)
3634 fp = fopen (cfname, "r");
3635 /* MASK AWAY IN dcRaw
3636 else {
3637 for (len=32 ; ; len *= 2) {
3638 fname = (char *) MALLOC (len);
3639 if (!fname) return;
3640 if (getcwd (fname, len-16)) break;
3641 FREE (fname);
3642 if (errno != ERANGE) return;
3643 }
3644 #if defined(WIN32) || defined(DJGPP)
3645 if (fname[1] == ':')
3646 memmove (fname, fname+2, len-2);
3647 for (cp=fname; *cp; cp++)
3648 if (*cp == '\\') *cp = '/';
3649 #endif
3650 cp = fname + strlen(fname);
3651 if (cp[-1] == '/') cp--;
3652 while (*fname == '/') {
3653 strcpy (cp, "/.badpixels");
3654 if ((fp = fopen (fname, "r"))) break;
3655 if (cp == fname) break;
3656 while (*--cp != '/');
3657 }
3658 FREE (fname);
3659 }
3660 */
3661 if (!fp) return;
3662 while (fgets (line, 128, fp)) {
3663 cp = strchr (line, '#');
3664 if (cp) *cp = 0;
3665 if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue;
3666 if ((unsigned) col >= m_Width || (unsigned) row >= m_Height) continue;
3667 if (time > m_TimeStamp) continue;
3668 for (tot=n=0, rad=1; rad < 3 && n==0; rad++)
3669 for (r = row-rad; r <= row+rad; r++)
3670 for (c = col-rad; c <= col+rad; c++)
3671 if ((unsigned) r < m_Height && (unsigned) c < m_Width &&
3672 (r != row || c != col) && fcol(r,c) == fcol(row,col)) {
3673 tot += BAYER2(r,c);
3674 n++;
3675 }
3676 BAYER2(row,col) = tot/n;
3677 TRACEKEYVALS("Fixed dead pixel at column","%d",col);
3678 TRACEKEYVALS("Fixed dead pixel at row","%d",row);
3679 }
3680 FCLOSE (fp);
3681 }
3682
subtract(const char * fname)3683 void CLASS subtract (const char *fname)
3684 {
3685 FILE *fp;
3686 int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col;
3687 uint16_t *pixel;
3688
3689 if (!(fp = fopen (fname, "rb"))) {
3690 perror (fname); return;
3691 }
3692 if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1;
3693 while (!error && nd < 3 && (c = fgetc(fp)) != EOF) {
3694 if (c == '#') comment = 1;
3695 if (c == '\n') comment = 0;
3696 if (comment) continue;
3697 if (isdigit(c)) number = 1;
3698 if (number) {
3699 if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0';
3700 else if (isspace(c)) {
3701 number = 0; nd++;
3702 } else error = 1;
3703 }
3704 }
3705 if (error || nd < 3) {
3706 fprintf (stderr,_("%s is not a valid PGM file!\n"), fname);
3707 FCLOSE (fp); return;
3708 } else if (dim[0] != m_Width || dim[1] != m_Height || dim[2] != 65535) {
3709 fprintf (stderr,_("%s has the wrong dimensions!\n"), fname);
3710 FCLOSE (fp); return;
3711 }
3712 pixel = (uint16_t*) CALLOC (m_Width, sizeof *pixel);
3713 merror (pixel, "subtract()");
3714 for (row=0; row < m_Height; row++) {
3715 ptfread (pixel, 2, m_Width, fp);
3716 for (col=0; col < m_Width; col++)
3717 BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0);
3718 }
3719 FREE (pixel);
3720 FCLOSE (fp);
3721 memset (m_CBlackLevel, 0, sizeof m_CBlackLevel);
3722 m_BlackLevel = 0;
3723 }
3724
gamma_curve(double pwr,double ts,int mode,int imax)3725 void CLASS gamma_curve (double pwr, double ts, int mode, int imax)
3726 {
3727 int i;
3728 double g[6], bnd[2]={0,0}, r;
3729
3730 g[0] = pwr;
3731 g[1] = ts;
3732 g[2] = g[3] = g[4] = 0;
3733 bnd[g[1] >= 1] = 1;
3734 if (g[1] && (g[1]-1)*(g[0]-1) <= 0) {
3735 for (i=0; i < 48; i++) {
3736 g[2] = (bnd[0] + bnd[1])/2;
3737 if (g[0]) bnd[(pow(g[2]/g[1],-g[0]) - 1)/g[0] - 1/g[2] > -1] = g[2];
3738 else bnd[g[2]/exp(1-1/g[2]) < g[1]] = g[2];
3739 }
3740 g[3] = g[2] / g[1];
3741 if (g[0]) g[4] = g[2] * (1/g[0] - 1);
3742 }
3743 if (g[0]) g[5] = 1 / (g[1]*SQR(g[3])/2 - g[4]*(1 - g[3]) +
3744 (1 - pow(g[3],1+g[0]))*(1 + g[4])/(1 + g[0])) - 1;
3745 else g[5] = 1 / (g[1]*SQR(g[3])/2 + 1
3746 - g[2] - g[3] - g[2]*g[3]*(log(g[3]) - 1)) - 1;
3747 if (!mode--) {
3748 memcpy (m_Gamma, g, sizeof m_Gamma);
3749 return;
3750 }
3751 for (i=0; i < 0x10000; i++) {
3752 m_Curve[i] = 0xffff;
3753 if ((r = (double) i / imax) < 1)
3754 m_Curve[i] = 0x10000 * ( mode
3755 ? (r < g[3] ? r*g[1] : (g[0] ? pow( r,g[0])*(1+g[4])-g[4] : log(r)*g[2]+1))
3756 : (r < g[2] ? r/g[1] : (g[0] ? pow((r+g[4])/(1+g[4]),1/g[0]) : exp((r-1)/g[2]))));
3757 }
3758 }
3759
pseudoinverse(double (* in)[3],double (* out)[3],int size)3760 void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size)
3761 {
3762 double work[3][6], num;
3763 int i, j, k;
3764
3765 for (i=0; i < 3; i++) {
3766 for (j=0; j < 6; j++)
3767 work[i][j] = j == i+3;
3768 for (j=0; j < 3; j++)
3769 for (k=0; k < size; k++)
3770 work[i][j] += in[k][i] * in[k][j];
3771 }
3772 for (i=0; i < 3; i++) {
3773 num = work[i][i];
3774 for (j=0; j < 6; j++)
3775 work[i][j] /= num;
3776 for (k=0; k < 3; k++) {
3777 if (k==i) continue;
3778 num = work[k][i];
3779 for (j=0; j < 6; j++)
3780 work[k][j] -= work[i][j] * num;
3781 }
3782 }
3783 for (i=0; i < size; i++)
3784 for (j=0; j < 3; j++)
3785 for (out[i][j]=k=0; k < 3; k++)
3786 out[i][j] += work[j][k+3] * in[i][k];
3787 }
3788
cam_xyz_coeff(double MatrixXYZToCamRGB[4][3])3789 void CLASS cam_xyz_coeff (double MatrixXYZToCamRGB[4][3])
3790 {
3791 double MatrixSRGBToCamRGB[4][3], inverse[4][3], num;
3792 int i, j, k;
3793
3794 for (i=0; i < m_Colors; i++) /* Multiply out XYZ colorspace */
3795 for (j=0; j < 3; j++)
3796 for (MatrixSRGBToCamRGB[i][j] = k=0; k < 3; k++)
3797 MatrixSRGBToCamRGB[i][j] +=
3798 MatrixXYZToCamRGB[i][k] * MatrixRGBToXYZ[ptSpace_sRGB_D65][k][j];
3799
3800 // Normalize MatrixSRGBToCamRGB such that
3801 // (1,1,1) in SRGB maps onto (1,1,1,1) in CamRGB.
3802 for (i=0; i < m_Colors; i++) {
3803 for (num=j=0; j < 3; j++)
3804 num += MatrixSRGBToCamRGB[i][j];
3805 for (j=0; j < 3; j++)
3806 MatrixSRGBToCamRGB[i][j] /= num;
3807
3808 // TODO More profound explanation.
3809 // But somehow it is clear that the factors to bring
3810 // (1,1,1)=>(1,1,1,1) are the multipliers at the reference point D65.
3811 ASSIGN(m_D65Multipliers[i], 1 / num);
3812 }
3813
3814 pseudoinverse (MatrixSRGBToCamRGB, inverse, m_Colors);
3815 m_RawColorPhotivo = m_RawColor;
3816 for (m_RawColor = i=0; i < 3; i++)
3817 for (j=0; j < m_Colors; j++)
3818 m_MatrixCamRGBToSRGB[i][j] = inverse[j][i];
3819 }
3820
hat_transform(float * temp,float * base,int st,int size,int sc)3821 void CLASS hat_transform (float *temp, float *base, int st, int size, int sc)
3822 {
3823 int i;
3824 for (i=0; i < sc; i++)
3825 temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)];
3826 for (; i+sc < size; i++)
3827 temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)];
3828 for (; i < size; i++)
3829 temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))];
3830 }
3831
3832 ////////////////////////////////////////////////////////////////////////////////
3833 //
3834 // ptAdjustMaximum
3835 // This is modelled after the adjust_maximum of libraw.
3836 // It's purpose is false color suppression in the highlights.
3837 // Typically "Threshold" should be between 0.75 and 1.
3838 //
3839 ////////////////////////////////////////////////////////////////////////////////
3840
ptAdjustMaximum(double Threshold)3841 void CLASS ptAdjustMaximum(double Threshold) {
3842 m_WhiteLevel = LIM((int32_t)(Threshold*(double)m_WhiteLevel),0, 4095);
3843 }
3844
3845 ////////////////////////////////////////////////////////////////////////////////
3846 //
3847 // ptScaleColors
3848 // Be aware : ptWaveletDenoising has as side effect that
3849 // m_Blacklevel and m_Whitelevel change.
3850 //
3851 ////////////////////////////////////////////////////////////////////////////////
3852
ptScaleColors()3853 void CLASS ptScaleColors() {
3854 unsigned bottom, right, row, col, x, y, c, sum[8];
3855 int val;
3856 double dsum[8], dmin, dmax;
3857
3858
3859 // Use the UserSetting_Multipliers if they are defined.
3860 // Remark that they will be overwritten if we have a AutoWb on CameraWb on !
3861
3862 if (m_UserSetting_Multiplier[0]) {
3863 TRACEKEYVALS("Setting PreMultipliers due to UserSetting","%s","");
3864 ASSIGN(m_PreMultipliers[0],m_UserSetting_Multiplier[0]);
3865 ASSIGN(m_PreMultipliers[1],m_UserSetting_Multiplier[1]);
3866 ASSIGN(m_PreMultipliers[2],m_UserSetting_Multiplier[2]);
3867 ASSIGN(m_PreMultipliers[3],m_UserSetting_Multiplier[3]);
3868 }
3869
3870 // AutoWb calculation, also fallback if no CameraWb found and
3871 // CameraWb is on.
3872 // Also the GreyBox whitesetting is done here, so AutoWb should be on for
3873 // GreyBox calculation !
3874
3875 if ( m_UserSetting_AutoWb ||
3876 (m_UserSetting_CameraWb && VALUE(m_CameraMultipliers[0]) == -1)) {
3877 memset (dsum, 0, sizeof dsum);
3878 bottom = MIN (m_UserSetting_GreyBox[1]+m_UserSetting_GreyBox[3], (int32_t)m_Height);
3879 right = MIN (m_UserSetting_GreyBox[0]+m_UserSetting_GreyBox[2], (int32_t)m_Width);
3880 TRACEKEYVALS("AutoWB GreyBox[0]","%d",m_UserSetting_GreyBox[0]);
3881 TRACEKEYVALS("AutoWB GreyBox[1]","%d",m_UserSetting_GreyBox[1]);
3882 TRACEKEYVALS("AutoWB GreyBox[2]","%d",m_UserSetting_GreyBox[2]);
3883 TRACEKEYVALS("AutoWB GreyBox[3]","%d",m_UserSetting_GreyBox[3]);
3884 TRACEKEYVALS("AutoWB m_Width","%d",m_Width);
3885 TRACEKEYVALS("AutoWB m_Height","%d",m_Height);
3886 TRACEKEYVALS("AutoWB right","%d",right);
3887 TRACEKEYVALS("AutoWB bottom","%d",bottom);
3888 // Auto whitebalance done over the greybox but resulting
3889 // in the whole image if no greybox given.
3890 for (row=m_UserSetting_GreyBox[1]; row < bottom; row += 8)
3891 for (col=m_UserSetting_GreyBox[0]; col < right; col += 8) {
3892 // Apparently the image is scanned in 8*8 pixel blocks.
3893 memset (sum, 0, sizeof sum);
3894 for (y=row; y < row+8 && y < bottom; y++)
3895 for (x=col; x < col+8 && x < right; x++)
3896 for (c=0; c < 4; c++) {
3897 if (m_Filters) {
3898 c = fcol(y,x);
3899 val = BAYER2(y,x);
3900 } else
3901 val = m_Image[y*m_Width+x][c];
3902 if ((unsigned) val > m_WhiteLevel-25) goto skip_block;
3903 if ((val -= m_CBlackLevel[c]) < 0) val = 0;
3904 sum[c] += val;
3905 sum[c+4]++;
3906 if (m_Filters) break;
3907 }
3908 for (c=0; c < 8; c++) dsum[c] += sum[c];
3909 skip_block: ;
3910 }
3911 // How intenser the blocks , how smaller the multipliers.
3912 // In terms of ratio's it means they will be close to each other
3913 // (neutral color balance) if the image has equally distributed RGB
3914 // (that's grey :))
3915 for (c=0; c < 4; c++) if (dsum[c]) ASSIGN(m_PreMultipliers[c], dsum[c+4] / dsum[c]);
3916 TRACEKEYVALS("Setting PreMultipliers due to AutoWB","%s","");
3917
3918 }
3919
3920 if (m_UserSetting_CameraWb && VALUE(m_CameraMultipliers[0]) != -1) {
3921 memset (sum, 0, sizeof sum);
3922 for (row=0; row < 8; row++)
3923 for (col=0; col < 8; col++) {
3924 c = FC(row,col);
3925 if ((val = white[row][col] - m_CBlackLevel[c]) > 0)
3926 sum[c] += val;
3927 sum[c+4]++;
3928 }
3929 if (sum[0] && sum[1] && sum[2] && sum[3]) {
3930 for (c=0; c < 4; c++) ASSIGN(m_PreMultipliers[c], (float) sum[c+4] / sum[c]);
3931 TRACEKEYVALS("Setting PreMultipliers due to CameraWB","%s","");
3932 }
3933 else if (VALUE(m_CameraMultipliers[0]) && VALUE(m_CameraMultipliers[2])) {
3934 ASSIGN(m_PreMultipliers[0],VALUE(m_CameraMultipliers[0]));
3935 ASSIGN(m_PreMultipliers[1],VALUE(m_CameraMultipliers[1]));
3936 ASSIGN(m_PreMultipliers[2],VALUE(m_CameraMultipliers[2]));
3937 ASSIGN(m_PreMultipliers[3],VALUE(m_CameraMultipliers[3]));
3938 TRACEKEYVALS("Setting PreMultipliers due to CameraMultipliers","%s","");
3939 }
3940 else
3941 fprintf (stderr,_("%s: Cannot use camera white balance.\n"), m_UserSetting_InputFileName);
3942 }
3943
3944 if (VALUE(m_PreMultipliers[3]) == 0) {
3945 ASSIGN(m_PreMultipliers[3],
3946 (m_Colors < 4) ? VALUE(m_PreMultipliers[1]) : 1);
3947 }
3948
3949 // Denoising before color scaling and interpolation.
3950 // Remark m_BlackLevel and m_WhiteLevel migth be changed.
3951 if (m_UserSetting_DenoiseThreshold) ptWaveletDenoise();
3952
3953 for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) {
3954 if (dmin > VALUE(m_PreMultipliers[c]))
3955 dmin = VALUE(m_PreMultipliers[c]);
3956 if (dmax < VALUE(m_PreMultipliers[c]))
3957 dmax = VALUE(m_PreMultipliers[c]);
3958 }
3959
3960 TRACEKEYVALS("PreMult[0]","%f",VALUE(m_PreMultipliers[0]));
3961 TRACEKEYVALS("PreMult[1]","%f",VALUE(m_PreMultipliers[1]));
3962 TRACEKEYVALS("PreMult[2]","%f",VALUE(m_PreMultipliers[2]));
3963 TRACEKEYVALS("PreMult[3]","%f",VALUE(m_PreMultipliers[3]));
3964 #ifdef TRACE_ORIGIN
3965 TRACEKEYVALS("PreMult File","%s",m_PreMultipliers[0].File);
3966 TRACEKEYVALS("PreMult Line","%d",m_PreMultipliers[0].Line);
3967 #endif
3968
3969 for (c=0;c<4;c++) {
3970 if (m_UserSetting_MaxMultiplier==0)
3971 ASSIGN(m_PreMultipliers[c],VALUE(m_PreMultipliers[c]) / dmax);
3972 else
3973 ASSIGN(m_PreMultipliers[c],VALUE(m_PreMultipliers[c]) / dmin);
3974 ASSIGN(m_Multipliers[c],
3975 VALUE(m_PreMultipliers[c])*0xffff/(m_WhiteLevel-m_CBlackLevel[c]));
3976 }
3977 if (m_UserSetting_MaxMultiplier==0)
3978 m_MinPreMulti = dmin/dmax; // And the maximum is per construction 1.0
3979 else
3980 m_MinPreMulti = 1.0; // TODO Mike: max is not 1.0 anymore...
3981
3982 TRACEKEYVALS("dmax","%f",dmax);
3983 TRACEKEYVALS("dmin","%f",dmin);
3984 TRACEKEYVALS("m_MinPreMulti","%f",m_MinPreMulti);
3985 TRACEKEYVALS("PreMult[0]","%f",VALUE(m_PreMultipliers[0]));
3986 TRACEKEYVALS("PreMult[1]","%f",VALUE(m_PreMultipliers[1]));
3987 TRACEKEYVALS("PreMult[2]","%f",VALUE(m_PreMultipliers[2]));
3988 TRACEKEYVALS("PreMult[3]","%f",VALUE(m_PreMultipliers[3]));
3989 #ifdef TRACE_ORIGIN
3990 TRACEKEYVALS("PreMult File","%s",m_PreMultipliers[0].File);
3991 TRACEKEYVALS("PreMult Line","%d",m_PreMultipliers[0].Line);
3992 #endif
3993 TRACEKEYVALS("Mult[0]","%f",VALUE(m_Multipliers[0]));
3994 TRACEKEYVALS("Mult[1]","%f",VALUE(m_Multipliers[1]));
3995 TRACEKEYVALS("Mult[2]","%f",VALUE(m_Multipliers[2]));
3996 TRACEKEYVALS("Mult[3]","%f",VALUE(m_Multipliers[3]));
3997 #ifdef TRACE_ORIGIN
3998 TRACEKEYVALS("Mult File","%s",m_Multipliers[0].File);
3999 TRACEKEYVALS("Mult Line","%d",m_Multipliers[0].Line);
4000 #endif
4001
4002 TRACEKEYVALS("Scaling colors","%s","");
4003
4004 uint16_t LUT[0x10000][4];
4005 #pragma omp parallel for schedule(static)
4006 for (uint32_t i = 0; i < 0xffff; i++) {
4007 for (short c = 0; c < 4; c++) {
4008 LUT[i][c] = i>m_CBlackLevel[c]?
4009 MIN((int32_t)((i - m_CBlackLevel[c])*VALUE(m_Multipliers[c])),0xffff):0;
4010 }
4011 }
4012
4013 uint32_t Size = m_OutHeight*m_OutWidth;
4014 #pragma omp parallel for schedule(static)
4015 for (uint32_t i = 0; i < Size; i++) {
4016 for (short Color = 0; Color < 4; Color++) {
4017 m_Image[i][Color] = LUT[m_Image[i][Color]][Color];
4018 }
4019 }
4020 }
4021
4022 ////////////////////////////////////////////////////////////////////////////////
4023 //
4024 // ptHighlight
4025 // Clipping is determined by Clip... FIXME
4026 //
4027 ////////////////////////////////////////////////////////////////////////////////
4028
ptHighlight(const short ClipMode,const short ClipParameter)4029 void CLASS ptHighlight(const short ClipMode,
4030 const short ClipParameter) {
4031
4032 TRACEKEYVALS("ClipMode","%d",ClipMode);
4033 TRACEKEYVALS("ClipParameter","%d",ClipParameter);
4034
4035 TRACEKEYVALS("m_Multi[0]","%f",VALUE(m_Multipliers[0]));
4036 TRACEKEYVALS("m_Multi[1]","%f",VALUE(m_Multipliers[1]));
4037 TRACEKEYVALS("m_Multi[2]","%f",VALUE(m_Multipliers[2]));
4038 TRACEKEYVALS("m_Multi[3]","%f",VALUE(m_Multipliers[3]));
4039 #ifdef TRACE_ORIGIN
4040 TRACEKEYVALS("Mult File","%s",m_Multipliers[0].File);
4041 TRACEKEYVALS("Mult Line","%d",m_Multipliers[0].Line);
4042 #endif
4043
4044 TRACEKEYVALS("m_MinPreMulti","%f",m_MinPreMulti);
4045 short ColorRGB[4]={0,1,2,1};
4046 #pragma omp parallel for schedule(static) default(shared)
4047 for (uint16_t Row = 0; Row < m_OutHeight; Row++) {
4048 for (uint16_t Column = 0; Column < m_OutWidth; Column++) {
4049 uint32_t Pos = Row*m_OutWidth+Column;
4050
4051 // Do take into account however that we scaled the image here
4052 // already !
4053
4054 // Clip occurs if the sensor reached its max value. Full stop.
4055 // m_Image[Pos] stands for value after application of the
4056 // m_Multipliers, which are per construction so that the saturation
4057 // value of the sensor maps onto 0XFFFF. It is the unclipped pixel.
4058
4059 short Clipped = 0;
4060 for (short Color = 0; Color < m_Colors; Color++) {
4061 if (m_Image[Pos][Color] >=
4062 (uint16_t)
4063 ((m_WhiteLevel-m_CBlackLevel[ColorRGB[Color]])*VALUE(m_Multipliers[Color]))) {
4064 Clipped = 1;
4065 }
4066 }
4067
4068 if (Clipped) {
4069 // Here it becomes fun. The sensor reached a clipped value.
4070
4071 // 'ClippedPixel' stands for the pixel which is multiplied
4072 // by a value that guarantees the saturation value of the
4073 // least scaled channel maps onto 0XFFFF.
4074 // That value is obtained by observing that normally the
4075 // least scaled channel maps on saturation*minimum_multiplier
4076 // So since maximum_multipliers brings us per definition on 0XFFFF
4077 // upscaling with maximum_multiplier/minimum_multipier is that
4078 // value. Via the equivalence with the pre_multipliers where the
4079 // maximum is per construction 1 , it means that we have to upscale
4080 // with 1/m_MinPreMulti.
4081 // That way all saturated pixels are definitely mapped onto 0xFFFF
4082 uint16_t ClippedPixel[4];
4083 for (short Color = 0; Color < m_Colors; Color++) {
4084 // This ensures that the channel with the smallest multiplier
4085 // is clipped at its saturation level.
4086 ClippedPixel[Color] =
4087 MIN(0xFFFF,
4088 (int32_t)(m_Image[Pos][Color]/m_MinPreMulti));
4089 // And now we correct it back for the increased exposure.
4090 // (but clipped stays clipped !)
4091 ClippedPixel[Color] = (uint16_t)(ClippedPixel[Color]* m_MinPreMulti);
4092 }
4093
4094 // From here on there are now different strategies with respect
4095 // to clipping.
4096
4097 // Try to remove purple highlights
4098 if (0)
4099 if (m_Image[Pos][2]>m_Image[Pos][1] && m_Image[Pos][0]==0xffff) m_Image[Pos][2]=m_Image[Pos][1];
4100
4101 // Simply use the clipped value.
4102 if (ptClipMode_Clip == ClipMode) {
4103 for (short Color = 0; Color < m_Colors; Color++) {
4104 m_Image[Pos][Color] = ClippedPixel[Color];
4105 }
4106
4107 // Or use a value starting from Unclipped->Clipped ,
4108 // defined by the ClipParameter.
4109 } else if (ptClipMode_NoClip == ClipMode) {
4110 for (short Color = 0; Color < m_Colors; Color++) {
4111 m_Image[Pos][Color] =
4112 m_Image[Pos][Color] +
4113 (uint16_t) (ClipParameter/100.0*
4114 (ClippedPixel[Color]-m_Image[Pos][Color]));
4115 }
4116
4117 // Or restore via Lab, which is basically the same as
4118 // used in ufraw (and a simplification of Cyril Guyots LCH blending.
4119 } else if (ptClipMode_Lab == ClipMode) {
4120 double ClippedLab[3];
4121 double UnclippedLab[3];
4122 double FinalLab[3];
4123 CamToLab(ClippedPixel,ClippedLab);
4124 CamToLab(m_Image[Pos],UnclippedLab);
4125 // FIXME / TODO : Clarify and explain.
4126 // This is a bit bizar in fact (but also in ufraw ...)
4127 // The result seems to be better when taking the clipped
4128 // alternatives for ab and unclipped for L.
4129 // Wouldn't we expect it the other way around ?
4130 FinalLab[0] = UnclippedLab[0] +
4131 ClipParameter/100.0*
4132 (ClippedLab[0]-UnclippedLab[0]);
4133 FinalLab[1] = ClippedLab[1];
4134 FinalLab[2] = ClippedLab[2];
4135 LabToCam(FinalLab,m_Image[Pos]);
4136
4137 // Or restore via HSV, as in ufraw.
4138 } else if (ptClipMode_HSV == ClipMode) {
4139 // FIXME / TODO : can this not break in some 4 colour modes ?
4140 short MaxChannel,MidChannel,MinChannel;
4141 if (m_Image[Pos][0] > m_Image[Pos][1] &&
4142 m_Image[Pos][0] > m_Image[Pos][2]) {
4143 MaxChannel = 0;
4144 if (m_Image[Pos][1] > m_Image[Pos][2]) {
4145 MidChannel = 1;
4146 MinChannel = 2;
4147 } else {
4148 MidChannel = 2;
4149 MinChannel = 1;
4150 }
4151 } else if (m_Image[Pos][1] > m_Image[Pos][2]) {
4152 MaxChannel = 1;
4153 if (m_Image[Pos][0] > m_Image[Pos][2]) {
4154 MidChannel = 0;
4155 MinChannel = 2;
4156 } else {
4157 MidChannel = 2;
4158 MinChannel = 0;
4159 }
4160 } else {
4161 MaxChannel = 2;
4162 if (m_Image[Pos][0] > m_Image[Pos][1]) {
4163 MidChannel = 0;
4164 MinChannel = 1;
4165 } else {
4166 MidChannel = 1;
4167 MinChannel = 0;
4168 }
4169 }
4170
4171 uint16_t UnclippedLuminance = m_Image[Pos][MaxChannel];
4172 uint16_t ClippedLuminance = ClippedPixel[MaxChannel];
4173 double ClippedSaturation;
4174 if ( ClippedPixel[MaxChannel]<ClippedPixel[MinChannel] ||
4175 ClippedPixel[MaxChannel]==0) {
4176 ClippedSaturation = 0;
4177 } else {
4178 ClippedSaturation =
4179 1.0 - (double)ClippedPixel[MinChannel] / ClippedPixel[MaxChannel];
4180 }
4181 //warning: variable 'ClippedHue' set but not used [-Wunused-but-set-variable]
4182 // double ClippedHue;
4183 // if ( ClippedPixel[MaxChannel]==ClippedPixel[MinChannel] ) {
4184 // ClippedHue = 0;
4185 // } else {
4186 // ClippedHue =
4187 // ((double)ClippedPixel[MidChannel]-ClippedPixel[MinChannel]) /
4188 // ((double)ClippedPixel[MaxChannel]-ClippedPixel[MinChannel]);
4189 // }
4190 double UnclippedHue;
4191 if ( m_Image[Pos][MaxChannel]==m_Image[Pos][MinChannel] ) {
4192 UnclippedHue = 0;
4193 } else {
4194 UnclippedHue =
4195 ((double)m_Image[Pos][MidChannel]-m_Image[Pos][MinChannel]) /
4196 ((double)m_Image[Pos][MaxChannel]-m_Image[Pos][MinChannel]);
4197 }
4198 uint16_t Luminance =
4199 UnclippedLuminance +
4200 (uint16_t)(ClipParameter/100.0 *
4201 (ClippedLuminance-UnclippedLuminance));
4202 double Saturation = ClippedSaturation;
4203 double Hue = UnclippedHue;
4204 m_Image[Pos][MaxChannel] = Luminance;
4205 m_Image[Pos][MinChannel] = (uint16_t)(Luminance * (1-Saturation));
4206 m_Image[Pos][MidChannel] =
4207 (uint16_t)(Luminance * (1-Saturation + Saturation*Hue));
4208
4209 } else if (ptClipMode_Blend == ClipMode) {
4210 // Do nothing at this stage, keep the unclipped image.
4211 ;
4212 } else if (ptClipMode_Rebuild == ClipMode) {
4213 // Do nothing at this stage, keep the unclipped image.
4214 ;
4215 } else {
4216 assert(0); // should not occur.
4217 }
4218 }
4219 }
4220 }
4221
4222 if (ptClipMode_Rebuild == ClipMode) {
4223 ptRebuildHighlights(ClipParameter);
4224 }
4225 if (ptClipMode_Blend == ClipMode) {
4226 ptBlendHighlights();
4227 }
4228 }
4229
pre_interpolate()4230 void CLASS pre_interpolate()
4231 {
4232 int row, col;
4233
4234 TRACEKEYVALS("pre_interpolate","%s","");
4235
4236 if (m_Shrink) {
4237 if (m_UserSetting_HalfSize) {
4238 // No interpolation will be needed as
4239 // m_Shrink has caused a 2X2 Bayer area mapped onto one pixel.
4240 m_Height = m_OutHeight;
4241 m_Width = m_OutWidth;
4242 } else {
4243 // in photivo we assume that m_Shrink is only set due
4244 // to m_UserSetting_HalfSize.
4245 assert(0);
4246 }
4247 }
4248 if (m_Filters > 1000 && m_Colors == 3) {
4249 if (m_MixGreen) { // 4 color demosaicer will follow
4250 m_Colors++;
4251 // Change from dcraw 1.445 to 1.447 wanted "m_MixGreen = !m_UserSetting_HalfSize;"
4252 // but this doesn't work in Photivo, since we don't run the full pipe of dcraw,
4253 // since most of the time we start with phase2
4254 } else {
4255 // RG1BG2 -> RGB
4256 #pragma omp parallel for schedule(static) default(shared) private(row, col)
4257 for (row = FC(1,0) >> 1; row < m_Height; row+=2)
4258 for (col = FC(row,1) & 1; col < m_Width; col+=2)
4259 m_Image[row*m_Width+col][1] = m_Image[row*m_Width+col][3];
4260 m_Filters &= ~((m_Filters & 0x55555555) << 1);
4261 }
4262 }
4263
4264 // If m_UserSetting_HalfSize is set no interpolation will
4265 // be needed. This is registered by m_Filters = 0.
4266 // (no Bayer array anymore, this means)
4267 if (m_UserSetting_HalfSize && m_Filters != 2) {
4268 m_Filters = 0;
4269 }
4270 }
4271
border_interpolate(int border)4272 void CLASS border_interpolate (int border)
4273 {
4274 unsigned row, col, y, x, f, c, sum[8];
4275
4276 for (row=0; row < m_Height; row++)
4277 for (col=0; col < m_Width; col++) {
4278 if (col==(unsigned) border && row >= (unsigned) border && row < (unsigned) (m_Height-border))
4279 col = m_Width-border;
4280 memset (sum, 0, sizeof sum);
4281 for (y=row-1; y != row+2; y++)
4282 for (x=col-1; x != col+2; x++)
4283 if (y < m_Height && x < m_Width) {
4284 f = fcol(y,x);
4285 sum[f] += m_Image[y*m_Width+x][f];
4286 sum[f+4]++;
4287 }
4288 f = fcol(row,col);
4289 for (c=0; c < (unsigned) m_Colors; c++) if (c != f && sum[c+4])
4290 m_Image[row*m_Width+col][c] = sum[c] / sum[c+4];
4291 }
4292 }
4293
4294
lin_interpolate()4295 void CLASS lin_interpolate()
4296 {
4297 int code[16][16][32], size=16, *ip, sum[4];
4298 int f, c, i, x, y, row, col, shift, color;
4299 uint16_t *pix;
4300
4301 TRACEKEYVALS("Bilinear interpolation","%s","");
4302 if (m_Filters == 2) size = 6;
4303 border_interpolate(1);
4304 for (row=0; row < size; row++)
4305 for (col=0; col < size; col++) {
4306 ip = code[row][col]+1;
4307 f = fcol(row,col);
4308 memset (sum, 0, sizeof sum);
4309 for (y=-1; y <= 1; y++)
4310 for (x=-1; x <= 1; x++) {
4311 shift = (y==0) + (x==0);
4312 color = fcol(row+y,col+x);
4313 if (color == f) continue;
4314 *ip++ = (m_Width*y + x)*4 + color;
4315 *ip++ = shift;
4316 *ip++ = color;
4317 sum[color] += 1 << shift;
4318 }
4319 code[row][col][0] = (ip - code[row][col]) / 3;
4320 for (c=0; c < m_Colors; c++)
4321 if (c != f) {
4322 *ip++ = c;
4323 *ip++ = 256 / sum[c];
4324 }
4325 }
4326 #pragma omp parallel for schedule(static) default(shared) private(row,col,pix,ip,sum,i)
4327 for (row=1; row < m_Height-1; row++)
4328 for (col=1; col < m_Width-1; col++) {
4329 pix = m_Image[row*m_Width+col];
4330 ip = code[row % size][col % size];
4331 memset (sum, 0, sizeof sum);
4332 for (i=*ip++; i--; ip+=3)
4333 sum[ip[2]] += pix[ip[0]] << ip[1];
4334 for (i=m_Colors; --i; ip+=2)
4335 pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
4336 }
4337 }
4338
4339 /*
4340 This algorithm is officially called:
4341
4342 "Interpolation using a Threshold-based variable number of gradients"
4343
4344 described in http://scien.stanford.edu/pages/labsite/1999/psych221/projects/99/tingchen/algodep/vargra.html
4345
4346 I've extended the basic idea to work with non-Bayer filter arrays.
4347 Gradients are numbered clockwise from NW=0 to W=7.
4348 */
vng_interpolate()4349 void CLASS vng_interpolate()
4350 {
4351 static const int16_t *cp, terms[] = {
4352 -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
4353 -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
4354 -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
4355 -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
4356 -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
4357 -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
4358 -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
4359 -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
4360 -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
4361 -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
4362 -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
4363 -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
4364 -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
4365 +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
4366 +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
4367 +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
4368 +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
4369 +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
4370 +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
4371 +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
4372 +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
4373 +1,+0,+2,+1,0,0x10
4374 }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
4375 uint16_t (*brow[5])[4], *pix;
4376 int prow=8, pcol=2, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
4377 int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
4378 int g, diff, thold, num, c;
4379
4380 lin_interpolate();
4381
4382 TRACEKEYVALS("VNG interpolation","%s","");
4383
4384 if (m_Filters == 1) prow = pcol = 16;
4385 if (m_Filters == 2) prow = pcol = 6;
4386 ip = (int *) CALLOC (prow*pcol, 1280);
4387 merror (ip, "vng_interpolate()");
4388 for (row=0; row < prow; row++) /* Precalculate for VNG */
4389 for (col=0; col < pcol; col++) {
4390 code[row][col] = ip;
4391 for (cp=terms, t=0; t < 64; t++) {
4392 y1 = *cp++; x1 = *cp++;
4393 y2 = *cp++; x2 = *cp++;
4394 weight = *cp++;
4395 grads = *cp++;
4396 color = fcol(row+y1,col+x1);
4397 if (fcol(row+y2,col+x2) != color) continue;
4398 diag = (fcol(row,col+1) == color && fcol(row+1,col) == color) ? 2:1;
4399 if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
4400 *ip++ = (y1*m_Width + x1)*4 + color;
4401 *ip++ = (y2*m_Width + x2)*4 + color;
4402 *ip++ = weight;
4403 for (g=0; g < 8; g++)
4404 if (grads & 1<<g) *ip++ = g;
4405 *ip++ = -1;
4406 }
4407 *ip++ = INT_MAX;
4408 for (cp=chood, g=0; g < 8; g++) {
4409 y = *cp++; x = *cp++;
4410 *ip++ = (y*m_Width + x) * 4;
4411 color = fcol(row,col);
4412 if (fcol(row+y,col+x) != color && fcol(row+y*2,col+x*2) == color)
4413 *ip++ = (y*m_Width + x) * 8 + color;
4414 else
4415 *ip++ = 0;
4416 }
4417 }
4418
4419 brow[4] = (uint16_t (*)[4]) CALLOC (m_Width*3, sizeof **brow);
4420 merror (brow[4], "vng_interpolate()");
4421 for (row=0; row < 3; row++)
4422 brow[row] = brow[4] + row*m_Width;
4423
4424 for (row=2; row < m_Height-2; row++) { /* Do VNG interpolation */
4425 for (col=2; col < m_Width-2; col++) {
4426 pix = m_Image[row*m_Width+col];
4427 ip = code[row % prow][col % pcol];
4428 memset (gval, 0, sizeof gval);
4429 while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */
4430 diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
4431 gval[ip[3]] += diff;
4432 ip += 5;
4433 if ((g = ip[-1]) == -1) continue;
4434 gval[g] += diff;
4435 while ((g = *ip++) != -1)
4436 gval[g] += diff;
4437 }
4438 ip++;
4439 gmin = gmax = gval[0]; /* Choose a threshold */
4440 for (g=1; g < 8; g++) {
4441 if (gmin > gval[g]) gmin = gval[g];
4442 if (gmax < gval[g]) gmax = gval[g];
4443 }
4444 if (gmax == 0) {
4445 memcpy (brow[2][col], pix, sizeof *m_Image);
4446 continue;
4447 }
4448 thold = gmin + (gmax >> 1);
4449 memset (sum, 0, sizeof sum);
4450 color = fcol(row,col);
4451 for (num=g=0; g < 8; g++,ip+=2) { /* Average the neighbors */
4452 if (gval[g] <= thold) {
4453 for (c=0; c < m_Colors; c++)
4454 if (c == color && ip[1])
4455 sum[c] += (pix[c] + pix[ip[1]]) >> 1;
4456 else
4457 sum[c] += pix[ip[0] + c];
4458 num++;
4459 }
4460 }
4461 for (c=0; c < m_Colors; c++) { /* Save to buffer */
4462 t = pix[color];
4463 if (c != color)
4464 t += (sum[c] - sum[color]) / num;
4465 brow[2][col][c] = CLIP(t);
4466 }
4467 }
4468 if (row > 3) /* Write buffer to image */
4469 memcpy (m_Image[(row-2)*m_Width+2], brow[0]+2, (m_Width-4)*sizeof *m_Image);
4470 for (g=0; g < 4; g++)
4471 brow[(g-1) & 3] = brow[g];
4472 }
4473 memcpy (m_Image[(row-2)*m_Width+2], brow[0]+2, (m_Width-4)*sizeof *m_Image);
4474 memcpy (m_Image[(row-1)*m_Width+2], brow[1]+2, (m_Width-4)*sizeof *m_Image);
4475 FREE (brow[4]);
4476 FREE (code[0][0]);
4477 }
4478
4479 /*
4480 Patterned Pixel Grouping Interpolation by Alain Desbiolles
4481 */
ppg_interpolate()4482 void CLASS ppg_interpolate()
4483 {
4484 const int dir[5] = { 1, m_Width, -1, -m_Width, 1 };
4485 int row, col, diff[2], guess[2], c, d, i;
4486 uint16_t (*pix)[4];
4487
4488 border_interpolate(3);
4489
4490 TRACEKEYVALS("PPG interpolation","%s","");
4491
4492 #pragma omp parallel private(row,c,col,i,guess,diff,d,pix)
4493 /* Fill in the green layer with gradients and pattern recognition: */
4494 #pragma omp for
4495 for (row=3; row < m_Height-3; row++)
4496 for (col=3+(FC(row,3) & 1), c=FC(row,col); col < m_Width-3; col+=2) {
4497 pix = m_Image + row*m_Width+col;
4498 for (i=0; i<2; i++) {
4499 d = dir[i];
4500 guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
4501 - pix[-2*d][c] - pix[2*d][c];
4502 diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) +
4503 ABS(pix[ 2*d][c] - pix[ 0][c]) +
4504 ABS(pix[ -d][1] - pix[ d][1]) ) * 3 +
4505 ( ABS(pix[ 3*d][1] - pix[ d][1]) +
4506 ABS(pix[-3*d][1] - pix[-d][1]) ) * 2;
4507 }
4508 d = dir[i = diff[0] > diff[1]];
4509 pix[0][1] = ULIM(guess[i] >> 2, (int32_t)pix[d][1], (int32_t)pix[-d][1]);
4510 }
4511 /* Calculate red and blue for each green pixel: */
4512 #pragma omp for
4513 for (row=1; row < m_Height-1; row++)
4514 for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < m_Width-1; col+=2) {
4515 pix = m_Image + row*m_Width+col;
4516 for (i=0; (d=dir[i]) > 0; c=2-c, i++)
4517 pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1]
4518 - pix[-d][1] - pix[d][1]) >> 1);
4519 }
4520 /* Calculate blue for red pixels and vice versa: */
4521 #pragma omp for
4522 for (row=1; row < m_Height-1; row++)
4523 for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < m_Width-1; col+=2) {
4524 pix = m_Image + row*m_Width+col;
4525 for (i=0; i < 2; i++) {
4526 d = dir[i]+dir[i+1];
4527 diff[i] = ABS(pix[-d][c] - pix[d][c]) +
4528 ABS(pix[-d][1] - pix[0][1]) +
4529 ABS(pix[ d][1] - pix[0][1]);
4530 guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1]
4531 - pix[-d][1] - pix[d][1];
4532 }
4533 if (diff[0] != diff[1])
4534 pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1);
4535 else
4536 pix[0][c] = CLIP((guess[0]+guess[1]) >> 2);
4537 }
4538 }
4539
4540 /*
4541 Adaptive Homogeneity-Directed interpolation is based on
4542 the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
4543 */
4544 #define TS 256 /* Tile Size */
4545
ahd_interpolate()4546 void CLASS ahd_interpolate()
4547 {
4548 int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
4549 uint16_t (*pix)[4], (*rix)[3];
4550 static const int dir[4] = { -1, 1, -TS, TS };
4551 unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
4552 float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
4553 uint16_t (*rgb)[TS][TS][3];
4554 short (*lab)[TS][TS][3], (*lix)[3];
4555 char (*homo)[TS][TS], *buffer;
4556
4557 TRACEKEYVALS("AHD interpolation","%s","");
4558
4559 for (i=0; i < 0x10000; i++) {
4560 r = i / 65535.0;
4561 cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0;
4562 }
4563 for (i=0; i < 3; i++)
4564 for (j=0; j < m_Colors; j++)
4565 for (xyz_cam[i][j] = k=0; k < 3; k++)
4566 xyz_cam[i][j] += MatrixRGBToXYZ[ptSpace_sRGB_D65][i][k] * m_MatrixCamRGBToSRGB[k][j] / D65Reference[i];
4567
4568 border_interpolate(5);
4569
4570 #pragma omp parallel private(buffer,rgb,lab,homo,top,left,row,c,col,pix,val,d,rix,xyz,lix,tc,tr,ldiff,abdiff,leps,abeps,hm,i,j) firstprivate(cbrt) shared(xyz_cam)
4571 {
4572 buffer = (char *) MALLOC (26*TS*TS); /* 1664 kB */
4573 merror (buffer, "ahd_interpolate()");
4574 rgb = (uint16_t(*)[TS][TS][3]) buffer;
4575 lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
4576 homo = (char (*)[TS][TS]) (buffer + 24*TS*TS);
4577
4578 #pragma omp for schedule(static)
4579 for (top=2; top < m_Height-5; top += TS-6)
4580 for (left=2; left < m_Width-5; left += TS-6) {
4581
4582 /* Interpolate green horizontally and vertically: */
4583 for (row = top; row < top+TS && row < m_Height-2; row++) {
4584 col = left + (FC(row,left) & 1);
4585 for (c = FC(row,col); col < left+TS && col < m_Width-2; col+=2) {
4586 pix = m_Image + row*m_Width+col;
4587 val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
4588 - pix[-2][c] - pix[2][c]) >> 2;
4589 rgb[0][row-top][col-left][1] = ULIM(val,(int32_t)pix[-1][1],(int32_t)pix[1][1]);
4590 val = ((pix[-m_Width][1] + pix[0][c] + pix[m_Width][1]) * 2
4591 - pix[-2*m_Width][c] - pix[2*m_Width][c]) >> 2;
4592 rgb[1][row-top][col-left][1] = ULIM(val,(int32_t)pix[-m_Width][1],(int32_t)pix[m_Width][1]);
4593 }
4594 }
4595 /* Interpolate red and blue, and convert to CIELab: */
4596 for (d=0; d < 2; d++)
4597 for (row=top+1; row < top+TS-1 && row < m_Height-3; row++)
4598 for (col=left+1; col < left+TS-1 && col < m_Width-3; col++) {
4599 pix = m_Image + row*m_Width+col;
4600 rix = &rgb[d][row-top][col-left];
4601 lix = &lab[d][row-top][col-left];
4602 if ((c = 2 - FC(row,col)) == 1) {
4603 c = FC(row+1,col);
4604 val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
4605 - rix[-1][1] - rix[1][1] ) >> 1);
4606 rix[0][2-c] = CLIP(val);
4607 val = pix[0][1] + (( pix[-m_Width][c] + pix[m_Width][c]
4608 - rix[-TS][1] - rix[TS][1] ) >> 1);
4609 } else
4610 val = rix[0][1] + (( pix[-m_Width-1][c] + pix[-m_Width+1][c]
4611 + pix[+m_Width-1][c] + pix[+m_Width+1][c]
4612 - rix[-TS-1][1] - rix[-TS+1][1]
4613 - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
4614 rix[0][c] = CLIP(val);
4615 c = FC(row,col);
4616 rix[0][c] = pix[0][c];
4617 xyz[0] = xyz[1] = xyz[2] = 0.5;
4618 for (c=0; c < m_Colors; c++) {
4619 xyz[0] += xyz_cam[0][c] * rix[0][c];
4620 xyz[1] += xyz_cam[1][c] * rix[0][c];
4621 xyz[2] += xyz_cam[2][c] * rix[0][c];
4622 }
4623 xyz[0] = cbrt[CLIP((int) xyz[0])];
4624 xyz[1] = cbrt[CLIP((int) xyz[1])];
4625 xyz[2] = cbrt[CLIP((int) xyz[2])];
4626 lix[0][0] = (short) (64 * (116 * xyz[1] - 16));
4627 lix[0][1] = (short) (64 * 500 * (xyz[0] - xyz[1]));
4628 lix[0][2] = (short) (64 * 200 * (xyz[1] - xyz[2]));
4629 }
4630 /* Build homogeneity maps from the CIELab images: */
4631 memset (homo, 0, 2*TS*TS);
4632 for (row=top+2; row < top+TS-2 && row < m_Height-4; row++) {
4633 tr = row-top;
4634 for (col=left+2; col < left+TS-2 && col < m_Width-4; col++) {
4635 tc = col-left;
4636 for (d=0; d < 2; d++) {
4637 lix = &lab[d][tr][tc];
4638 for (i=0; i < 4; i++) {
4639 ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
4640 abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
4641 + SQR(lix[0][2]-lix[dir[i]][2]);
4642 }
4643 }
4644 leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
4645 MAX(ldiff[1][2],ldiff[1][3]));
4646 abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
4647 MAX(abdiff[1][2],abdiff[1][3]));
4648 for (d=0; d < 2; d++)
4649 for (i=0; i < 4; i++)
4650 if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
4651 homo[d][tr][tc]++;
4652 }
4653 }
4654 /* Combine the most homogenous pixels for the final result: */
4655 for (row=top+3; row < top+TS-3 && row < m_Height-5; row++) {
4656 tr = row-top;
4657 for (col=left+3; col < left+TS-3 && col < m_Width-5; col++) {
4658 tc = col-left;
4659 for (d=0; d < 2; d++)
4660 for (hm[d]=0, i=tr-1; i <= tr+1; i++)
4661 for (j=tc-1; j <= tc+1; j++)
4662 hm[d] += homo[d][i][j];
4663 if (hm[0] != hm[1])
4664 for (c=0; c<3; c++) m_Image[row*m_Width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
4665 else
4666 for (c=0; c<3; c++) m_Image[row*m_Width+col][c] =
4667 (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
4668 }
4669 }
4670 }
4671 FREE (buffer);
4672 }
4673 }
4674 #undef TS
4675
tiff_get(unsigned base,unsigned * tag,unsigned * type,unsigned * len,unsigned * save)4676 void CLASS tiff_get (unsigned base,
4677 unsigned *tag, unsigned *type, unsigned *len, unsigned *save)
4678 {
4679 *tag = get2();
4680 *type = get2();
4681 *len = get4();
4682 *save = ftell(m_InputFile) + 4;
4683 if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4)
4684 fseek (m_InputFile, get4()+base, SEEK_SET);
4685 }
4686
parse_thumb_note(int base,unsigned toff,unsigned tlen)4687 void CLASS parse_thumb_note (int base, unsigned toff, unsigned tlen)
4688 {
4689 unsigned entries, tag, type, len, save;
4690
4691 entries = get2();
4692 while (entries--) {
4693 tiff_get (base, &tag, &type, &len, &save);
4694 if (tag == toff) m_ThumbOffset = get4()+base;
4695 if (tag == tlen) m_ThumbLength = get4();
4696 fseek (m_InputFile, save, SEEK_SET);
4697 }
4698 }
4699
4700 //int CLASS parse_tiff_ifd (int base);
4701
parse_makernote(int base,int uptag)4702 void CLASS parse_makernote (int base, int uptag)
4703 {
4704 static const uint8_t xlat[2][256] = {
4705 { 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
4706 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
4707 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
4708 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
4709 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
4710 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
4711 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
4712 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
4713 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
4714 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
4715 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
4716 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
4717 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
4718 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
4719 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
4720 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 },
4721 { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
4722 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
4723 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
4724 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
4725 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
4726 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
4727 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
4728 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
4729 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
4730 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
4731 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
4732 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
4733 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
4734 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
4735 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
4736 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } };
4737 unsigned offset=0, entries, tag, type, len, save, c;
4738 unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0};
4739 uint8_t buf97[324], ci, cj, ck;
4740 short mm_ByteOrder, sm_ByteOrder=m_ByteOrder;
4741 char buf[10];
4742 /*
4743 The MakerNote might have its own TIFF header (possibly with
4744 its own byte-order!), or it might just be a table.
4745 */
4746 if (!strcmp(m_CameraMake,"Nokia")) return;
4747 ptfread (buf, 1, 10, m_InputFile);
4748 if (!strncmp (buf,"KDK" ,3) || /* these aren't TIFF tables */
4749 !strncmp (buf,"VER" ,3) ||
4750 !strncmp (buf,"IIII",4) ||
4751 !strncmp (buf,"MMMM",4)) return;
4752 if (!strncmp (buf,"KC" ,2) || /* Konica KD-400Z, KD-510Z */
4753 !strncmp (buf,"MLY" ,3)) { /* Minolta DiMAGE G series */
4754 m_ByteOrder = 0x4d4d;
4755 while ((i=ftell(m_InputFile)) < (unsigned) m_Data_Offset && i < (unsigned) 16384) {
4756 wb[0] = wb[2]; wb[2] = wb[1]; wb[1] = wb[3];
4757 wb[3] = get2();
4758 if (wb[1] == 256 && wb[3] == 256 &&
4759 wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640)
4760 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c], wb[c]);
4761 }
4762 goto quit;
4763 }
4764 if (!strcmp (buf,"Nikon")) {
4765 base = ftell(m_InputFile);
4766 m_ByteOrder = get2();
4767 if (get2() != 42) goto quit;
4768 offset = get4();
4769 fseek (m_InputFile, offset-8, SEEK_CUR);
4770 } else if (!strcmp (buf,"OLYMPUS")) {
4771 base = ftell(m_InputFile)-10;
4772 fseek (m_InputFile, -2, SEEK_CUR);
4773 m_ByteOrder = get2(); get2();
4774 } else if (!strncmp (buf,"SONY",4) ||
4775 !strcmp (buf,"Panasonic")) {
4776 goto nf;
4777 } else if (!strncmp (buf,"FUJIFILM",8)) {
4778 base = ftell(m_InputFile)-10;
4779 nf: m_ByteOrder = 0x4949;
4780 fseek (m_InputFile, 2, SEEK_CUR);
4781 } else if (!strcmp (buf,"OLYMP") ||
4782 !strcmp (buf,"LEICA") ||
4783 !strcmp (buf,"Ricoh") ||
4784 !strcmp (buf,"EPSON"))
4785 fseek (m_InputFile, -2, SEEK_CUR);
4786 else if (!strcmp (buf,"AOC") ||
4787 !strcmp (buf,"QVC"))
4788 fseek (m_InputFile, -4, SEEK_CUR);
4789 else {
4790 fseek (m_InputFile, -10, SEEK_CUR);
4791 if (!strncmp(m_CameraMake,"SAMSUNG",7))
4792 base = ftell(m_InputFile);
4793 }
4794 entries = get2();
4795 if (entries > 1000) return;
4796 mm_ByteOrder = m_ByteOrder;
4797 while (entries--) {
4798 m_ByteOrder = mm_ByteOrder;
4799 tiff_get (base, &tag, &type, &len, &save);
4800 tag |= uptag << 16;
4801 if (tag == 2 && strstr(m_CameraMake,"NIKON") && !m_IsoSpeed)
4802 m_IsoSpeed = (get2(),get2());
4803 if (tag == 4 && len > 26 && len < 35) {
4804 if ((i=(get4(),get2())) != 0x7fff && !m_IsoSpeed)
4805 m_IsoSpeed = 50 * pow (2, i/32.0 - 4);
4806 if ((i=(get2(),get2())) != 0x7fff && !m_Aperture)
4807 m_Aperture = pow (2, i/64.0);
4808 if ((i=get2()) != 0xffff && !m_Shutter)
4809 m_Shutter = pow (2, (short) i/-32.0);
4810 wbi = (get2(),get2());
4811 m_ShotOrder = (get2(),get2());
4812 }
4813 if ((tag == 4 || tag == 0x114) && !strncmp(m_CameraMake,"KONICA",6)) {
4814 fseek (m_InputFile, tag == 4 ? 140:160, SEEK_CUR);
4815 switch (get2()) {
4816 case 72: m_Flip = 0; break;
4817 case 76: m_Flip = 6; break;
4818 case 82: m_Flip = 5; break;
4819 }
4820 }
4821 if (tag == 7 && type == 2 && len > 20)
4822 ptfgets (m_CameraModelBis, 64, m_InputFile);
4823 if (tag == 8 && type == 4)
4824 m_ShotOrder = get4();
4825 if (tag == 9 && !strcmp(m_CameraMake,"Canon"))
4826 ptfread (m_Artist, 64, 1, m_InputFile);
4827 if (tag == 0xc && len == 4) {
4828 ASSIGN(m_CameraMultipliers[0], getreal(type));
4829 ASSIGN(m_CameraMultipliers[2], getreal(type));
4830 }
4831 if (tag == 0xd && type == 7 && get2() == 0xaaaa) {
4832 for (c=i=2; (uint16_t) c != 0xbbbb && i < len; i++)
4833 c = c << 8 | fgetc(m_InputFile);
4834 while ((i+=4) < len-5)
4835 if (get4() == 257 && (i=len) && (c = (get4(),fgetc(m_InputFile))) < 3)
4836 m_Flip = "065"[c]-'0';
4837 }
4838 if (tag == 0x10 && type == 4)
4839 unique_id = get4();
4840 if (tag == 0x11 && m_IsRaw && !strncmp(m_CameraMake,"NIKON",5)) {
4841 fseek (m_InputFile, get4()+base, SEEK_SET);
4842 parse_tiff_ifd (base);
4843 }
4844 if (tag == 0x14 && type == 7) {
4845 if (len == 2560) {
4846 fseek (m_InputFile, 1248, SEEK_CUR);
4847 goto get2_256;
4848 }
4849 ptfread (buf, 1, 10, m_InputFile);
4850 if (!strncmp(buf,"NRW ",4)) {
4851 fseek (m_InputFile, strcmp(buf+4,"0100") ? 46:1546, SEEK_CUR);
4852 ASSIGN(m_CameraMultipliers[0], get4() << 2);
4853 ASSIGN(m_CameraMultipliers[1], get4() + get4());
4854 ASSIGN(m_CameraMultipliers[2], get4() << 2);
4855 }
4856 }
4857 if (tag == 0x15 && type == 2 && m_IsRaw)
4858 ptfread (m_CameraModel, 64, 1, m_InputFile);
4859 if (strstr(m_CameraMake,"PENTAX")) {
4860 if (tag == 0x1b) tag = 0x1018;
4861 if (tag == 0x1c) tag = 0x1017;
4862 }
4863 if (tag == 0x1d)
4864 while ((c = fgetc(m_InputFile)) && c != (unsigned) EOF)
4865 serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
4866 if (tag == 0x81 && type == 4) {
4867 m_Data_Offset = get4();
4868 fseek (m_InputFile, m_Data_Offset + 41, SEEK_SET);
4869 m_RawHeight = get2() * 2;
4870 m_RawWidth = get2();
4871 m_Filters = 0x61616161;
4872 }
4873 if (tag == 0x29 && type == 1) {
4874 c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
4875 fseek (m_InputFile, 8 + c*32, SEEK_CUR);
4876 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1) ^ 1], get4());
4877 }
4878 if ((tag == 0x81 && type == 7) ||
4879 (tag == 0x100 && type == 7) ||
4880 (tag == 0x280 && type == 1)) {
4881 m_ThumbOffset = ftell(m_InputFile);
4882 m_ThumbLength = len;
4883 }
4884 if (tag == 0x88 && type == 4 && (m_ThumbOffset = get4()))
4885 m_ThumbOffset += base;
4886 if (tag == 0x89 && type == 4)
4887 m_ThumbLength = get4();
4888 if (tag == 0x8c || tag == 0x96)
4889 meta_offset = ftell(m_InputFile);
4890 if (tag == 0x97) {
4891 for (i=0; i < 4; i++)
4892 ver97 = ver97 * 10 + fgetc(m_InputFile)-'0';
4893 switch (ver97) {
4894 case 100:
4895 fseek (m_InputFile, 68, SEEK_CUR);
4896 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[(c >> 1) | ((c & 1) << 1)], get2());
4897 break;
4898 case 102:
4899 fseek (m_InputFile, 6, SEEK_CUR);
4900 goto get2_rggb;
4901 case 103:
4902 fseek (m_InputFile, 16, SEEK_CUR);
4903 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c], get2());
4904 }
4905 if (ver97 >= 200) {
4906 if (ver97 != 205) fseek (m_InputFile, 280, SEEK_CUR);
4907 ptfread (buf97, 324, 1, m_InputFile);
4908 }
4909 }
4910 if (tag == 0xa1 && type == 7) {
4911 type = m_ByteOrder;
4912 m_ByteOrder = 0x4949;
4913 fseek (m_InputFile, 140, SEEK_CUR);
4914 for (c=0; c < 3; c++) ASSIGN(m_CameraMultipliers[c], get4());
4915 m_ByteOrder = type;
4916 }
4917 if (tag == 0xa4 && type == 3) {
4918 fseek (m_InputFile, wbi*48, SEEK_CUR);
4919 for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], get2());
4920 }
4921 if (tag == 0xa7 && (unsigned) (ver97-200) < 12 && !VALUE(m_CameraMultipliers[0])) {
4922 ci = xlat[0][serial & 0xff];
4923 cj = xlat[1][fgetc(m_InputFile)^fgetc(m_InputFile)^fgetc(m_InputFile)^fgetc(m_InputFile)];
4924 ck = 0x60;
4925 for (i=0; i < 324; i++)
4926 buf97[i] ^= (cj += ci * ck++);
4927 i = "66666>666;6A;:;55"[ver97-200] - '0';
4928 for (c=0; c < 4; c++)
4929 ASSIGN(m_CameraMultipliers[c ^ (c >> 1) ^ (i &1)],
4930 sget2 (buf97 + (i & -2) + c*2));
4931 }
4932 if (tag == 0x200 && len == 3)
4933 m_ShotOrder = (get4(),get4());
4934 if (tag == 0x200 && len == 4)
4935 for (c=0; c<4; c++) m_CBlackLevel[c ^ c >> 1] = get2();
4936 if (tag == 0x201 && len == 4)
4937 goto get2_rggb;
4938 if (tag == 0x220 && type == 7)
4939 meta_offset = ftell(m_InputFile);
4940 if (tag == 0x401 && type == 4 && len == 4) {
4941 for (c=0; c<4; c++) m_CBlackLevel[c ^ c >> 1] = get4();
4942 }
4943 if (tag == 0xe01) { /* Nikon Capture Note */
4944 type = m_ByteOrder;
4945 m_ByteOrder = 0x4949;
4946 fseek (m_InputFile, 22, SEEK_CUR);
4947 for (offset=22; offset+22 < len; offset += 22+i) {
4948 tag = get4();
4949 fseek (m_InputFile, 14, SEEK_CUR);
4950 i = get4()-4;
4951 if (tag == 0x76a43207) m_Flip = get2();
4952 else fseek (m_InputFile, i, SEEK_CUR);
4953 }
4954 m_ByteOrder = type;
4955 }
4956 if (tag == 0xe80 && len == 256 && type == 7) {
4957 fseek (m_InputFile, 48, SEEK_CUR);
4958 ASSIGN(m_CameraMultipliers[0], get2() * 508 * 1.078 / 0x10000);
4959 ASSIGN(m_CameraMultipliers[2], get2() * 382 * 1.173 / 0x10000);
4960 }
4961 if (tag == 0xf00 && type == 7) {
4962 if (len == 614)
4963 fseek (m_InputFile, 176, SEEK_CUR);
4964 else if (len == 734 || len == 1502)
4965 fseek (m_InputFile, 148, SEEK_CUR);
4966 else goto next;
4967 goto get2_256;
4968 }
4969 if ((tag == 0x1011 && len == 9) || tag == 0x20400200)
4970 for (i=0; i < 3; i++)
4971 for (c=0; c<3; c++) m_cmatrix[i][c] = ((short) get2()) / 256.0;
4972 if ((tag == 0x1012 || tag == 0x20400600) && len == 4)
4973 for (c=0; c<4; c++) m_CBlackLevel[c ^ c >> 1] = get2();
4974 if (tag == 0x1017 || tag == 0x20400100)
4975 ASSIGN(m_CameraMultipliers[0], get2() / 256.0);
4976 if (tag == 0x1018 || tag == 0x20400100)
4977 ASSIGN(m_CameraMultipliers[2], get2() / 256.0);
4978 if (tag == 0x2011 && len == 2) {
4979 get2_256:
4980 m_ByteOrder = 0x4d4d;
4981 ASSIGN(m_CameraMultipliers[0], get2() / 256.0);
4982 ASSIGN(m_CameraMultipliers[2], get2() / 256.0);
4983 }
4984 if ((tag | 0x70) == 0x2070 && type == 4)
4985 fseek (m_InputFile, get4()+base, SEEK_SET);
4986 if (tag == 0x2010 && type != 7)
4987 m_LoadRawFunction = &CLASS olympus_load_raw;
4988 if (tag == 0x2020)
4989 parse_thumb_note (base, 257, 258);
4990 if (tag == 0x2040)
4991 parse_makernote (base, 0x2040);
4992 if (tag == 0xb028) {
4993 fseek (m_InputFile, get4()+base, SEEK_SET);
4994 parse_thumb_note (base, 136, 137);
4995 }
4996 if (tag == 0x4001 && len > 500) {
4997 i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126;
4998 fseek (m_InputFile, i, SEEK_CUR);
4999 get2_rggb:
5000 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], get2());
5001 i = len >> 3 == 164 ? 112:22;
5002 fseek (m_InputFile, i, SEEK_CUR);
5003 for (c=0; c < 4; c++) sraw_mul[c ^ (c >> 1)] = get2();
5004 }
5005 if (tag == 0xa021)
5006 for (c=0; c<4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], get4());
5007 if (tag == 0xa028)
5008 for (c=0; c<4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], m_CameraMultipliers[c ^ (c >> 1)] - get4());
5009 next:
5010 fseek (m_InputFile, save, SEEK_SET);
5011 }
5012 quit:
5013 m_ByteOrder = sm_ByteOrder;
5014 }
5015
5016 /*
5017 Since the TIFF DateTime string has no timezone information,
5018 assume that the camera's clock was set to Universal Time.
5019 */
get_timestamp(int reversed)5020 void CLASS get_timestamp (int reversed)
5021 {
5022 struct tm t;
5023 char str[20];
5024 int i;
5025
5026 str[19] = 0;
5027 if (reversed)
5028 for (i=19; i--; ) str[i] = fgetc(m_InputFile);
5029 else
5030 ptfread (str, 19, 1, m_InputFile);
5031 memset (&t, 0, sizeof t);
5032 if (sscanf (str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
5033 &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
5034 return;
5035 t.tm_year -= 1900;
5036 t.tm_mon -= 1;
5037 t.tm_isdst = -1;
5038 if (mktime(&t) > 0)
5039 m_TimeStamp = mktime(&t);
5040 }
5041
parse_exif(int base)5042 void CLASS parse_exif (int base)
5043 {
5044 unsigned kodak, entries, tag, type, len, save, c;
5045 double expo;
5046
5047 kodak = !strncmp(m_CameraMake,"EASTMAN",7) && m_Tiff_NrIFDs < 3;
5048 entries = get2();
5049 while (entries--) {
5050 tiff_get (base, &tag, &type, &len, &save);
5051 switch (tag) {
5052 case 33434: m_Shutter = getreal(type); break;
5053 case 33437: m_Aperture = getreal(type); break;
5054 case 34855: m_IsoSpeed = get2(); break;
5055 case 36867:
5056 case 36868: get_timestamp(0); break;
5057 case 37377: if ((expo = -getreal(type)) < 128)
5058 m_Shutter = pow (2, expo); break;
5059 case 37378: m_Aperture = pow (2, getreal(type)/2); break;
5060 case 37386: m_FocalLength = getreal(type); break;
5061 case 37500: parse_makernote (base, 0); break;
5062 case 40962: if (kodak) m_RawWidth = get4(); break;
5063 case 40963: if (kodak) m_RawHeight = get4(); break;
5064 case 41730:
5065 if (get4() == 0x20002)
5066 for (exif_cfa=c=0; c < 8; c+=2)
5067 exif_cfa |= fgetc(m_InputFile) * 0x01010101 << c;
5068 }
5069 fseek (m_InputFile, save, SEEK_SET);
5070 }
5071 }
5072
romm_coeff(float romm_cam[3][3])5073 void CLASS romm_coeff (float romm_cam[3][3])
5074 {
5075 static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */
5076 { { 2.034193, -0.727420, -0.306766 },
5077 { -0.228811, 1.231729, -0.002922 },
5078 { -0.008565, -0.153273, 1.161839 } };
5079 int i, j, k;
5080
5081 for (i=0; i < 3; i++)
5082 for (j=0; j < 3; j++)
5083 for (m_cmatrix[i][j] = k=0; k < 3; k++)
5084 m_cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j];
5085 }
5086
parse_mos(int offset)5087 void CLASS parse_mos (int offset)
5088 {
5089 char data[40];
5090 int skip, from, i, c, neut[4], planes=0, frot=0;
5091 static const char *mod[] =
5092 { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22",
5093 "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65",
5094 "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7",
5095 "","","","","","","","","","","","","","","","","","AFi-II 12" };
5096 float romm_cam[3][3];
5097
5098 fseek (m_InputFile, offset, SEEK_SET);
5099 while (1) {
5100 if (get4() != 0x504b5453) break;
5101 get4();
5102 ptfread (data, 1, 40, m_InputFile);
5103 skip = get4();
5104 from = ftell(m_InputFile);
5105 if (!strcmp(data,"JPEG_preview_data")) {
5106 m_ThumbOffset = from;
5107 m_ThumbLength = skip;
5108 }
5109 if (!strcmp(data,"icc_camera_profile")) {
5110 m_ProfileOffset = from;
5111 m_ProfileLength = skip;
5112 }
5113 if (!strcmp(data,"ShootObj_back_type")) {
5114 ptfscanf (m_InputFile, "%d", &i);
5115 if ((unsigned) i < sizeof mod / sizeof (*mod))
5116 strcpy (m_CameraModel, mod[i]);
5117 }
5118 if (!strcmp(data,"icc_camera_to_tone_matrix")) {
5119 for (i=0; i < 9; i++)
5120 romm_cam[0][i] = int_to_float(get4());
5121 romm_coeff (romm_cam);
5122 }
5123 if (!strcmp(data,"CaptProf_color_matrix")) {
5124 for (i=0; i < 9; i++)
5125 ptfscanf (m_InputFile, "%f", &romm_cam[0][i]);
5126 romm_coeff (romm_cam);
5127 }
5128 if (!strcmp(data,"CaptProf_number_of_planes"))
5129 ptfscanf (m_InputFile, "%d", &planes);
5130 if (!strcmp(data,"CaptProf_raw_data_rotation"))
5131 ptfscanf (m_InputFile, "%d", &m_Flip);
5132 if (!strcmp(data,"CaptProf_mosaic_pattern"))
5133 for (c=0; c < 4; c++) {
5134 ptfscanf (m_InputFile, "%d", &i);
5135 if (i == 1) frot = c ^ (c >> 1);
5136 }
5137 if (!strcmp(data,"ImgProf_rotation_angle")) {
5138 ptfscanf (m_InputFile, "%d", &i);
5139 m_Flip = i - m_Flip;
5140 }
5141 if (!strcmp(data,"NeutObj_neutrals") && !VALUE(m_CameraMultipliers[0])) {
5142 for (c=0; c < 4; c++) ptfscanf (m_InputFile, "%d", neut+c);
5143 for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], (float) neut[0] / neut[c+1]);
5144 }
5145 if (!strcmp(data,"Rows_data"))
5146 m_Load_Flags = get4();
5147 parse_mos (from);
5148 fseek (m_InputFile, skip+from, SEEK_SET);
5149 }
5150 if (planes)
5151 m_Filters = (planes == 1) * 0x01010101 *
5152 (uint8_t) "\x94\x61\x16\x49"[(m_Flip/90 + frot) & 3];
5153 }
5154
linear_table(unsigned len)5155 void CLASS linear_table (unsigned len)
5156 {
5157 int i;
5158 if (len > 0x1000) len = 0x1000;
5159 read_shorts (m_Curve, len);
5160 for (i=len; i < 0x1000; i++)
5161 m_Curve[i] = m_Curve[i-1];
5162 m_WhiteLevel = m_Curve[0xfff];
5163 }
5164
parse_kodak_ifd(int base)5165 void CLASS parse_kodak_ifd (int base)
5166 {
5167 unsigned entries, tag, type, len, save;
5168 int i, c, wbi=-2, wbtemp=6500;
5169 float mul[3] = {1,1,1}, num = 0;
5170 static const int wbtag[] = { 64037,64040,64039,64041,-1,-1,64042 };
5171
5172 entries = get2();
5173 if (entries > 1024) return;
5174 while (entries--) {
5175 tiff_get (base, &tag, &type, &len, &save);
5176 if (tag == 1020) wbi = getint(type);
5177 if (tag == 1021 && len == 72) { /* WB set in software */
5178 fseek (m_InputFile, 40, SEEK_CUR);
5179 for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], 2048.0 / get2());
5180 wbi = -2;
5181 }
5182 if (tag == 2118) wbtemp = getint(type);
5183 if (tag == (unsigned)(2130 + wbi))
5184 for (c=0; c<3; c++) mul[c] = getreal(type);
5185 if (tag == (unsigned)(2140 + wbi) && wbi >= 0)
5186 for (c=0; c<3; c++) {
5187 for (num=i=0; i < 4; i++)
5188 num += getreal(type) * pow (wbtemp/100.0, i);
5189 ASSIGN(m_CameraMultipliers[c], 2048 / (num * mul[c]));
5190 }
5191 if (tag == 2317) linear_table (len);
5192 if (tag == 6020) m_IsoSpeed = getint(type);
5193 if (tag == 64013) wbi = fgetc(m_InputFile);
5194 if (wbi < 7 && (int) tag == wbtag[wbi])
5195 for(c=0;c<3;c++) ASSIGN(m_CameraMultipliers[c],get4());
5196 if (tag == 64019) m_Width = getint(type);
5197 if (tag == 64020) m_Height = (getint(type)+1) & -2;
5198
5199 fseek (m_InputFile, save, SEEK_SET);
5200 }
5201 }
5202
5203 //void CLASS parse_minolta (int base);
5204
parse_tiff_ifd(int l_Base)5205 int CLASS parse_tiff_ifd (int l_Base) {
5206 unsigned l_Entries;
5207 unsigned l_Tag;
5208 unsigned l_Type;
5209 unsigned l_Length;
5210 unsigned l_plen=16;
5211 unsigned l_Save;
5212 int l_ifd;
5213 int l_use_cm=0;
5214 int l_cfa;
5215 int i, j, c;
5216 int l_ImageLength=0;
5217 int blrr=1, blrc=1, dblack[] = { 0,0,0,0 };
5218 char l_Software[64];
5219 char *l_cbuf;
5220 char *cp;
5221 uint8_t l_cfa_pat[16];
5222 uint8_t l_cfa_pc[] = { 0,1,2,3 };
5223 uint8_t l_tab[256];
5224 double l_cc[4][4];
5225 double l_cm[4][3];
5226 double l_cam_xyz[4][3];
5227 double l_num;
5228 double l_ab[]={ 1,1,1,1 };
5229 double l_asn[] = { 0,0,0,0 };
5230 double l_xyz[] = { 1,1,1 };
5231 unsigned l_sony_curve[] = { 0,0,0,0,0,4095 };
5232 unsigned* l_buf;
5233 unsigned l_sony_offset=0;
5234 unsigned l_sony_length=0;
5235 unsigned l_sony_key=0;
5236 FILE* l_sfp;
5237
5238 struct jhead l_JHead;
5239
5240 if (m_Tiff_NrIFDs >= sizeof m_Tiff_IFD / sizeof m_Tiff_IFD[0])
5241 return 1;
5242 l_ifd = m_Tiff_NrIFDs++;
5243 for (j=0; j < 4; j++)
5244 for (i=0; i < 4; i++)
5245 l_cc[j][i] = (i == j);
5246 l_Entries = get2();
5247 if (l_Entries > 512) return 1;
5248 while (l_Entries--) {
5249 tiff_get (l_Base, &l_Tag, &l_Type, &l_Length, &l_Save);
5250 switch (l_Tag) {
5251 case 5: m_Width = get2(); break;
5252 case 6: m_Height = get2(); break;
5253 case 7: m_Width += get2(); break;
5254 case 9: m_Filters = get2(); break;
5255 case 14: case 15: case 16:
5256 m_WhiteLevel = get2();
5257 break;
5258 case 17: case 18:
5259 if (l_Type == 3 && l_Length == 1)
5260 ASSIGN(m_CameraMultipliers[(l_Tag-17)*2], get2() / 256.0);
5261 break;
5262 case 23:
5263 if (l_Type == 3) m_IsoSpeed = get2();
5264 break;
5265 case 36: case 37: case 38:
5266 ASSIGN(m_CameraMultipliers[l_Tag-0x24], get2());
5267 break;
5268 case 39:
5269 if (l_Length < 50 || VALUE(m_CameraMultipliers[0])) break;
5270 fseek (m_InputFile, 12, SEEK_CUR);
5271 for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], get2());
5272 break;
5273 case 46:
5274 if (l_Type != 7 || fgetc(m_InputFile) != 0xff || fgetc(m_InputFile) != 0xd8) break;
5275 m_ThumbOffset = ftell(m_InputFile) - 2;
5276 m_ThumbLength = l_Length;
5277 break;
5278 case 61440: /* Fuji HS10 table */
5279 parse_tiff_ifd (l_Base);
5280 break;
5281 case 2: case 256: case 61441: /* ImageWidth */
5282 m_Tiff_IFD[l_ifd].width = getint(l_Type);
5283 break;
5284 case 3: case 257: case 61442: /* ImageHeight */
5285 m_Tiff_IFD[l_ifd].height = getint(l_Type);
5286 break;
5287 case 258: /* BitsPerSample */
5288 case 61443:
5289 m_Tiff_IFD[l_ifd].samples = l_Length & 7;
5290 m_Tiff_IFD[l_ifd].bps = getint(l_Type);
5291 break;
5292 case 61446:
5293 m_RawHeight = 0;
5294 m_LoadRawFunction = &CLASS packed_load_raw;
5295 m_Load_Flags = get4() && (m_Filters=0x16161616) ? 24:80;
5296 break;
5297 case 259: /* Compression */
5298 m_Tiff_IFD[l_ifd].comp = getint(l_Type);
5299 break;
5300 case 262: /* PhotometricInterpretation */
5301 m_Tiff_IFD[l_ifd].phint = get2();
5302 break;
5303 case 270: /* ImageDescription */
5304 ptfread (m_Description, 512, 1, m_InputFile);
5305 break;
5306 case 271: /* Make */
5307 ptfgets (m_CameraMake, 64, m_InputFile);
5308 break;
5309 case 272: /* Model */
5310 ptfgets (m_CameraModel, 64, m_InputFile);
5311 break;
5312 case 280: /* Panasonic RW2 offset */
5313 if (l_Type != 4) break;
5314 m_LoadRawFunction = &CLASS panasonic_load_raw;
5315 m_Load_Flags = 0x2008;
5316
5317 case 273: /* StripOffset */
5318 case 513: /* JpegIFOffset */
5319 case 61447:
5320 m_Tiff_IFD[l_ifd].offset = get4()+l_Base;
5321 if (!m_Tiff_IFD[l_ifd].bps && m_Tiff_IFD[l_ifd].offset > 0) {
5322 fseek (m_InputFile, m_Tiff_IFD[l_ifd].offset, SEEK_SET);
5323 if (ljpeg_start (&l_JHead, 1)) {
5324 m_Tiff_IFD[l_ifd].comp = 6;
5325 m_Tiff_IFD[l_ifd].width = l_JHead.wide;
5326 m_Tiff_IFD[l_ifd].height = l_JHead.high;
5327 m_Tiff_IFD[l_ifd].bps = l_JHead.bits;
5328 m_Tiff_IFD[l_ifd].samples = l_JHead.clrs;
5329 if (!(l_JHead.sraw || (l_JHead.clrs & 1)))
5330 m_Tiff_IFD[l_ifd].width *= l_JHead.clrs;
5331 i = m_ByteOrder;
5332 parse_tiff (m_Tiff_IFD[l_ifd].offset + 12);
5333 m_ByteOrder = i;
5334 }
5335 }
5336 break;
5337 case 274: /* Orientation */
5338 m_Tiff_IFD[l_ifd].flip = "50132467"[get2() & 7]-'0';
5339 break;
5340 case 277: /* SamplesPerPixel */
5341 m_Tiff_IFD[l_ifd].samples = getint(l_Type) & 7;
5342 break;
5343 case 279: /* StripByteCounts */
5344 case 514:
5345 case 61448:
5346 m_Tiff_IFD[l_ifd].bytes = get4();
5347 break;
5348 case 61454:
5349 for (c=0; c < 3; c++) ASSIGN(m_CameraMultipliers[(4-c) % 3],getint(l_Type));
5350 break;
5351 case 305: case 11: /* Software */
5352 ptfgets (l_Software, 64, m_InputFile);
5353 if (!strncmp(l_Software,"Adobe",5) ||
5354 !strncmp(l_Software,"dcraw",5) ||
5355 !strncmp(l_Software,"UFRaw",5) ||
5356 !strncmp(l_Software,"Bibble",6) ||
5357 !strncmp(l_Software,"Nikon Scan",10) ||
5358 !strcmp (l_Software,"Digital Photo Professional"))
5359 m_IsRaw = 0;
5360 break;
5361 case 306: /* DateTime */
5362 get_timestamp(0);
5363 break;
5364 case 315: /* Artist */
5365 ptfread (m_Artist, 64, 1, m_InputFile);
5366 break;
5367 case 322: /* TileWidth */
5368 m_Tiff_IFD[l_ifd].tile_width = getint(l_Type);
5369 break;
5370 case 323: /* TileLength */
5371 m_Tiff_IFD[l_ifd].tile_length = getint(l_Type);
5372 break;
5373 case 324: /* TileOffsets */
5374 m_Tiff_IFD[l_ifd].offset = l_Length > 1 ? ftell(m_InputFile) : get4();
5375 if (l_Length == 4) {
5376 m_LoadRawFunction = &CLASS sinar_4shot_load_raw;
5377 m_IsRaw = 5;
5378 }
5379 break;
5380 case 330: /* SubIFDs */
5381 if (!strcmp(m_CameraModel,"DSLR-A100") && m_Tiff_IFD[l_ifd].width == 3872) {
5382 m_LoadRawFunction = &CLASS sony_arw_load_raw;
5383 m_Data_Offset = get4()+l_Base;
5384 l_ifd++; break;
5385 }
5386 while (l_Length--) {
5387 i = ftell(m_InputFile);
5388 fseek (m_InputFile, get4()+l_Base, SEEK_SET);
5389 if (parse_tiff_ifd (l_Base)) break;
5390 fseek (m_InputFile, i+4, SEEK_SET);
5391 }
5392 break;
5393 case 400:
5394 strcpy (m_CameraMake, "Sarnoff");
5395 m_WhiteLevel = 0xfff;
5396 break;
5397 case 28688:
5398 for (c=0; c < 4; c++) l_sony_curve[c+1] = get2() >> 2 & 0xfff;
5399 for (i=0; i < 5; i++)
5400 for (j = l_sony_curve[i]+1; (unsigned) j <= l_sony_curve[i+1]; j++)
5401 m_Curve[j] = m_Curve[j-1] + (1 << i);
5402 break;
5403 case 29184: l_sony_offset = get4(); break;
5404 case 29185: l_sony_length = get4(); break;
5405 case 29217: l_sony_key = get4(); break;
5406 case 29264:
5407 parse_minolta (ftell(m_InputFile));
5408 m_RawWidth = 0;
5409 break;
5410 case 29443:
5411 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c < 2)], get2());
5412 break;
5413 case 29459:
5414 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c], get2());
5415 i = (m_CameraMultipliers[1] == 1024 && m_CameraMultipliers[2] == 1024) << 1;
5416 SWAP (m_CameraMultipliers[i],m_CameraMultipliers[i+1])
5417 break;
5418 case 33405: /* Model2 */
5419 ptfgets (m_CameraModelBis, 64, m_InputFile);
5420 break;
5421 case 33422: /* CFAPattern */
5422 case 64777: /* Kodak P-series */
5423 if ((l_plen=l_Length) > 16) l_plen = 16;
5424 ptfread (l_cfa_pat, 1, l_plen, m_InputFile);
5425 for (m_Colors=l_cfa=i=0; (unsigned) i < l_plen; i++) {
5426 m_Colors += !(l_cfa & (1 << l_cfa_pat[i]));
5427 l_cfa |= 1 << l_cfa_pat[i];
5428 }
5429 if (l_cfa == 070) memcpy (l_cfa_pc,"\003\004\005",3); /* CMY */
5430 if (l_cfa == 072) memcpy (l_cfa_pc,"\005\003\004\001",4); /* GMCY */
5431 goto guess_l_cfa_pc;
5432 case 33424:
5433 case 65024:
5434 fseek (m_InputFile, get4()+l_Base, SEEK_SET);
5435 parse_kodak_ifd (l_Base);
5436 break;
5437 case 33434: /* ExposureTime */
5438 m_Shutter = getreal(l_Type);
5439 break;
5440 case 33437: /* FNumber */
5441 m_Aperture = getreal(l_Type);
5442 break;
5443 case 34306: /* Leaf white balance */
5444 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ 1], 4096.0 / get2());
5445 break;
5446 case 34307: /* Leaf CatchLight color matrix */
5447 ptfread (l_Software, 1, 7, m_InputFile);
5448 if (strncmp(l_Software,"MATRIX",6)) break;
5449 m_Colors = 4;
5450 for (m_RawColor = i=0; i < 3; i++) {
5451 for (c=0; c < 4; c++) ptfscanf (m_InputFile, "%f", &m_MatrixCamRGBToSRGB[i][c^1]);
5452 if (!m_UserSetting_CameraWb) continue;
5453 l_num = 0;
5454 for (c=0; c < 4; c++) l_num += m_MatrixCamRGBToSRGB[i][c];
5455 for (c=0; c < 4; c++) m_MatrixCamRGBToSRGB[i][c] /= l_num;
5456 }
5457 break;
5458 case 34310: /* Leaf metadata */
5459 parse_mos (ftell(m_InputFile));
5460 case 34303:
5461 strcpy (m_CameraMake, "Leaf");
5462 break;
5463 case 34665: /* EXIF tag */
5464 fseek (m_InputFile, get4()+l_Base, SEEK_SET);
5465 parse_exif (l_Base);
5466 break;
5467 case 34675: /* InterColorProfile */
5468 case 50831: /* AsShotICCProfile */
5469 m_ProfileOffset = ftell(m_InputFile);
5470 m_ProfileLength = l_Length;
5471 break;
5472 case 37122: /* CompressedBitsPerPixel */
5473 m_Kodak_cbpp = get4();
5474 break;
5475 case 37386: /* FocalLength */
5476 m_FocalLength = getreal(l_Type);
5477 break;
5478 case 37393: /* ImageNumber */
5479 m_ShotOrder = getint(l_Type);
5480 break;
5481 case 37400: /* old Kodak KDC tag */
5482 for (m_RawColor = i=0; i < 3; i++) {
5483 getreal(l_Type);
5484 for (c=0; c<3; c++) m_MatrixCamRGBToSRGB[i][c] = getreal(l_Type);
5485 }
5486 break;
5487 case 46275: /* Imacon tags */
5488 strcpy (m_CameraMake, "Imacon");
5489 m_Data_Offset = ftell(m_InputFile);
5490 l_ImageLength = l_Length;
5491 break;
5492 case 46279:
5493 if (l_ImageLength) break;
5494 fseek (m_InputFile, 38, SEEK_CUR);
5495 case 46274:
5496 fseek (m_InputFile, 40, SEEK_CUR);
5497 m_RawWidth = get4();
5498 m_RawHeight = get4();
5499 m_LeftMargin = get4() & 7;
5500 m_Width = m_RawWidth - m_LeftMargin - (get4() & 7);
5501 m_TopMargin = get4() & 7;
5502 m_Height = m_RawHeight - m_TopMargin - (get4() & 7);
5503 if (m_RawWidth == 7262) {
5504 m_Height = 5444;
5505 m_Width = 7244;
5506 m_LeftMargin = 7;
5507 }
5508 fseek (m_InputFile, 52, SEEK_CUR);
5509 for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], getreal(11));
5510 fseek (m_InputFile, 114, SEEK_CUR);
5511 m_Flip = (get2() >> 7) * 90;
5512 if (m_Width * m_Height * 6 == l_ImageLength) {
5513 if (m_Flip % 180 == 90) SWAP(m_Width,m_Height);
5514 m_RawWidth = m_Width;
5515 m_RawHeight = m_Height;
5516 m_LeftMargin = m_TopMargin = m_Filters = m_Flip = 0;
5517 }
5518 sprintf (m_CameraModel, "Ixpress %d-Mp", m_Height*m_Width/1000000);
5519 m_LoadRawFunction = &CLASS imacon_full_load_raw;
5520 if (m_Filters) {
5521 if (m_LeftMargin & 1) m_Filters = 0x61616161;
5522 m_LoadRawFunction = &CLASS unpacked_load_raw;
5523 }
5524 m_WhiteLevel = 0xffff;
5525 break;
5526 case 50454: /* Sinar tag */
5527 case 50455:
5528 if (!(l_cbuf = (char *) MALLOC(l_Length))) break;
5529 ptfread (l_cbuf, 1, l_Length, m_InputFile);
5530 for (cp = l_cbuf-1; cp && cp < l_cbuf+l_Length; cp = strchr(cp,'\n'))
5531 if (!strncmp (++cp,"Neutral ",8))
5532 sscanf (cp+8, "%f %f %f",
5533 &VALUE(m_CameraMultipliers[0]),
5534 &VALUE(m_CameraMultipliers[1]),
5535 &VALUE(m_CameraMultipliers[2]));
5536 FREE (l_cbuf);
5537 break;
5538 case 50458:
5539 if(!m_CameraMake[0]) strcpy(m_CameraMake,"Hasselblad");
5540 break;
5541 case 50459: /* Hasselblad tag */
5542 i = m_ByteOrder;
5543 j = ftell(m_InputFile);
5544 c = m_Tiff_NrIFDs;
5545 m_ByteOrder = get2();
5546 fseek (m_InputFile, j+(get2(),get4()), SEEK_SET);
5547 parse_tiff_ifd (j);
5548 m_WhiteLevel = 0xffff;
5549 m_Tiff_NrIFDs = c;
5550 m_ByteOrder = i;
5551 break;
5552 case 50706: /* DNGVersion */
5553 for (c=0; c < 4; c++) m_DNG_Version = (m_DNG_Version << 8) + fgetc(m_InputFile);
5554 if (!m_CameraMake[0]) strcpy (m_CameraMake,"DNG");
5555 m_IsRaw = 1;
5556 break;
5557 case 50710: /* CFAPlaneColor */
5558 if (l_Length > 4) l_Length = 4;
5559 m_Colors = l_Length;
5560 ptfread (l_cfa_pc, 1, m_Colors, m_InputFile);
5561 guess_l_cfa_pc:
5562 for (c=0; c < m_Colors; c++) l_tab[l_cfa_pc[c]] = c;
5563 m_ColorDescriptor[c] = 0;
5564 for (i=16; i--; )
5565 m_Filters = m_Filters << 2 | l_tab[l_cfa_pat[i % l_plen]];
5566 break;
5567 case 50711: /* CFALayout */
5568 if (get2() == 2) {
5569 m_Fuji_Width = 1;
5570 m_Filters = 0x49494949;
5571 }
5572 break;
5573 case 291:
5574 case 50712: /* LinearizationTable */
5575 linear_table (l_Length);
5576 break;
5577 case 50713: /* BlackLevelRepeatDim */
5578 blrr = get2();
5579 blrc = get2();
5580 break;
5581 case 61450:
5582 blrr = blrc = 2;
5583 case 50714: /* BlackLevel */
5584 m_BlackLevel = getreal(l_Type);
5585 if (!m_Filters || !~m_Filters) break;
5586 dblack[0] = m_BlackLevel;
5587 dblack[1] = (blrc == 2) ? getreal(l_Type):dblack[0];
5588 dblack[2] = (blrr == 2) ? getreal(l_Type):dblack[0];
5589 dblack[3] = (blrc == 2 && blrr == 2) ? getreal(l_Type):dblack[1];
5590 if (m_Colors == 3)
5591 m_Filters |= ((m_Filters >> 2 & 0x22222222) |
5592 (m_Filters << 2 & 0x88888888)) & m_Filters << 1;
5593 for (c=0; c<4; c++) m_CBlackLevel[m_Filters >> (c << 1) & 3] = dblack[c];
5594 m_BlackLevel = 0;
5595 break;
5596 case 50715: /* BlackLevelDeltaH */
5597 case 50716: /* BlackLevelDeltaV */
5598 for (l_num=i=0; (unsigned)i < l_Length; i++)
5599 l_num += getreal(l_Type);
5600 m_BlackLevel += l_num/l_Length + 0.5;
5601 break;
5602 case 50717: /* WhiteLevel */
5603 m_WhiteLevel = getint(l_Type);
5604 break;
5605 case 50718: /* DefaultScale */
5606 m_PixelAspect = getreal(l_Type);
5607 m_PixelAspect /= getreal(l_Type);
5608 break;
5609 case 50721: /* ColorMatrix1 */
5610 case 50722: /* ColorMatrix2 */
5611 for (c=0; c < m_Colors; c++) for (j=0; j < 3; j++)
5612 l_cm[c][j] = getreal(l_Type);
5613 l_use_cm = 1;
5614 break;
5615 case 50723: /* CameraCalibration1 */
5616 case 50724: /* CameraCalibration2 */
5617 for (i=0; i < m_Colors; i++)
5618 for (c=0; c < m_Colors; c++) l_cc[i][c] = getreal(l_Type);
5619 break;
5620 case 50727: /* AnalogBalance */
5621 for (c=0; c < m_Colors; c++) l_ab[c] = getreal(l_Type);
5622 break;
5623 case 50728: /* AsShotNeutral */
5624 for (c=0; c < m_Colors; c++) l_asn[c] = getreal(l_Type);
5625 break;
5626 case 50729: /* AsShotWhiteXY */
5627 l_xyz[0] = getreal(l_Type);
5628 l_xyz[1] = getreal(l_Type);
5629 l_xyz[2] = 1 - l_xyz[0] - l_xyz[1];
5630 for (c=0; c<3; c++) l_xyz[c] /= D65Reference[c];
5631 break;
5632 case 50740: /* DNGPrivateData */
5633 if (m_DNG_Version) break;
5634 parse_minolta (j = get4()+l_Base);
5635 fseek (m_InputFile, j, SEEK_SET);
5636 parse_tiff_ifd (l_Base);
5637 break;
5638 case 50752:
5639 read_shorts (cr2_slice, 3);
5640 break;
5641 case 50829: /* ActiveArea */
5642 m_TopMargin = getint(l_Type);
5643 m_LeftMargin = getint(l_Type);
5644 m_Height = getint(l_Type) - m_TopMargin;
5645 m_Width = getint(l_Type) - m_LeftMargin;
5646 break;
5647 case 50830: /* MaskedAreas */
5648 for (i=0; i < (int32_t)l_Length && i < 32; i++)
5649 m_Mask[0][i] = getint(l_Type);
5650 m_BlackLevel = 0;
5651 break;
5652 case 51009: /* OpcodeList2 */
5653 meta_offset = ftell(m_InputFile);
5654 break;
5655 case 64772: /* Kodak P-series */
5656 if (l_Length < 13) break;
5657 fseek (m_InputFile, 16, SEEK_CUR);
5658 m_Data_Offset = get4();
5659 fseek (m_InputFile, 28, SEEK_CUR);
5660 m_Data_Offset += get4();
5661 m_LoadRawFunction = &CLASS packed_load_raw;
5662 break;
5663 case 65026:
5664 if (l_Type == 2) ptfgets(m_CameraModelBis,64,m_InputFile);
5665 }
5666 fseek (m_InputFile, l_Save, SEEK_SET);
5667 }
5668 if (l_sony_length && (l_buf = (unsigned *) MALLOC(l_sony_length))) {
5669 fseek (m_InputFile, l_sony_offset, SEEK_SET);
5670 ptfread (l_buf, l_sony_length, 1, m_InputFile);
5671 sony_decrypt (l_buf, l_sony_length/4, 1, l_sony_key);
5672 l_sfp = m_InputFile;
5673 if ((m_InputFile = tmpfile())) {
5674 ptfwrite (l_buf, l_sony_length, 1, m_InputFile);
5675 fseek (m_InputFile, 0, SEEK_SET);
5676 parse_tiff_ifd (-l_sony_offset);
5677 FCLOSE (m_InputFile);
5678 }
5679 m_InputFile = l_sfp;
5680 FREE (l_buf);
5681 }
5682 for (i=0; i < m_Colors; i++)
5683 for (c=0; c < m_Colors; c++) l_cc[i][c] *= l_ab[i];
5684 if (l_use_cm) {
5685 for (c=0; c < m_Colors; c++) for (i=0; i < 3; i++)
5686 for (l_cam_xyz[c][i]=j=0; j < m_Colors; j++)
5687 l_cam_xyz[c][i] += l_cc[c][j] * l_cm[j][i] * l_xyz[i];
5688 cam_xyz_coeff (l_cam_xyz);
5689 }
5690 if (l_asn[0]) {
5691 ASSIGN(m_CameraMultipliers[3], 0);
5692 for (c=0; c < m_Colors; c++) ASSIGN(m_CameraMultipliers[c], 1 / l_asn[c]);
5693 }
5694
5695 if (!l_use_cm)
5696 for (c=0; c < m_Colors; c++)
5697 ASSIGN(m_D65Multipliers[c],VALUE(m_D65Multipliers[c]) / l_cc[c][c]);
5698
5699 return 0;
5700 }
5701
5702 // To get out of the mess what is global and what is local
5703 // I started here with l_ tagging of the variables.
5704 // (but the most simple like i or c which are evidently , hopefully , local)
5705 // What remains must be a global.
5706 // (jpta) This is what my EOS400D would do.
5707
parse_tiff(int l_Base)5708 int CLASS parse_tiff (int l_Base) {
5709 // Set to start of tiff
5710 fseek (m_InputFile, l_Base, SEEK_SET);
5711
5712 // Check byte order and return if not OK
5713 m_ByteOrder = get2();
5714 if (m_ByteOrder != 0x4949 && m_ByteOrder != 0x4d4d) return 0;
5715
5716 get2();
5717
5718 int l_doff;
5719 while ((l_doff = get4())) {
5720 fseek (m_InputFile, l_doff+l_Base, SEEK_SET);
5721 if (parse_tiff_ifd (l_Base)) break;
5722 }
5723 return 1;
5724 }
5725
apply_tiff()5726 void CLASS apply_tiff()
5727 {
5728 int l_MaxSample=0;
5729 int l_Raw=-1;
5730 int l_Thumb=-1;
5731 int i;
5732
5733 struct jhead l_Jhead;
5734
5735 m_ThumbMisc = 16;
5736 if (m_ThumbOffset) {
5737 fseek (m_InputFile,m_ThumbOffset,SEEK_SET);
5738 if (ljpeg_start (&l_Jhead, 1)) {
5739 m_ThumbMisc = l_Jhead.bits;
5740 m_ThumbWidth = l_Jhead.wide;
5741 m_ThumbHeight = l_Jhead.high;
5742 }
5743 }
5744
5745 for (i=0; (unsigned) i < m_Tiff_NrIFDs; i++) {
5746 if (l_MaxSample < m_Tiff_IFD[i].samples)
5747 l_MaxSample = m_Tiff_IFD[i].samples;
5748 if (l_MaxSample > 3) l_MaxSample = 3;
5749 if ((m_Tiff_IFD[i].comp != 6 || m_Tiff_IFD[i].samples != 3) &&
5750 (m_Tiff_IFD[i].width | m_Tiff_IFD[i].height) < 0x10000 &&
5751 m_Tiff_IFD[i].width*m_Tiff_IFD[i].height > m_RawWidth*m_RawHeight) {
5752 m_RawWidth = m_Tiff_IFD[i].width;
5753 m_RawHeight = m_Tiff_IFD[i].height;
5754 m_Tiff_bps = m_Tiff_IFD[i].bps;
5755 m_Tiff_Compress = m_Tiff_IFD[i].comp;
5756 m_Data_Offset = m_Tiff_IFD[i].offset;
5757 m_Tiff_Flip = m_Tiff_IFD[i].flip;
5758 m_Tiff_Samples = m_Tiff_IFD[i].samples;
5759 m_TileWidth = m_Tiff_IFD[i].tile_width;
5760 m_TileLength = m_Tiff_IFD[i].tile_length;
5761 l_Raw = i;
5762 }
5763 }
5764 if (!m_TileWidth ) m_TileWidth = INT_MAX;
5765 if (!m_TileLength) m_TileLength = INT_MAX;
5766 for (i=m_Tiff_NrIFDs; i--; )
5767 if (m_Tiff_IFD[i].flip) m_Tiff_Flip = m_Tiff_IFD[i].flip;
5768
5769 if (l_Raw >= 0 && !m_LoadRawFunction)
5770 switch (m_Tiff_Compress) {
5771 case 32767:
5772 if (m_Tiff_IFD[l_Raw].bytes == m_RawWidth*m_RawHeight) {
5773 m_Tiff_bps = 12;
5774 m_LoadRawFunction = &CLASS sony_arw2_load_raw;
5775 break;
5776 }
5777 if (m_Tiff_IFD[l_Raw].bytes*8U != m_RawWidth*m_RawHeight*m_Tiff_bps) {
5778 m_RawHeight += 8;
5779 m_LoadRawFunction = &CLASS sony_arw_load_raw;
5780 break;
5781 }
5782 m_Load_Flags = 79;
5783 case 32769:
5784 m_Load_Flags++;
5785 case 32770:
5786 case 32773: goto slr;
5787 case 0: case 1:
5788 if (m_Tiff_IFD[l_Raw].bytes*5 == m_RawWidth*m_RawHeight*8) {
5789 m_Load_Flags = 81;
5790 m_Tiff_bps = 12;
5791 } slr:
5792 switch (m_Tiff_bps) {
5793 case 8: m_LoadRawFunction = &CLASS eight_bit_load_raw; break;
5794 case 12: if (m_Tiff_IFD[l_Raw].phint == 2)
5795 m_Load_Flags = 6;
5796 m_LoadRawFunction = &CLASS packed_load_raw; break;
5797 case 14: m_Load_Flags = 0;
5798 case 16: m_LoadRawFunction = &CLASS unpacked_load_raw; break;
5799 }
5800 break;
5801 case 6: case 7: case 99:
5802 m_LoadRawFunction = &CLASS lossless_jpeg_load_raw; break;
5803 case 262:
5804 m_LoadRawFunction = &CLASS kodak_262_load_raw; break;
5805 case 34713:
5806 if ((m_RawWidth+9)/10*16*m_RawHeight == m_Tiff_IFD[l_Raw].bytes) {
5807 m_LoadRawFunction = &CLASS packed_load_raw;
5808 m_Load_Flags = 1;
5809 } else if (m_RawWidth*m_RawHeight*2 == m_Tiff_IFD[l_Raw].bytes) {
5810 m_LoadRawFunction = &CLASS unpacked_load_raw;
5811 m_Load_Flags = 4;
5812 m_ByteOrder = 0x4d4d;
5813 } else
5814 m_LoadRawFunction = &CLASS nikon_load_raw; break;
5815 case 34892:
5816 m_LoadRawFunction = &CLASS lossy_dng_load_raw; break;
5817 case 65535:
5818 m_LoadRawFunction = &CLASS pentax_load_raw;
5819 break;
5820 case 65000:
5821 switch (m_Tiff_IFD[l_Raw].phint) {
5822 case 2: m_LoadRawFunction = &CLASS kodak_rgb_load_raw;
5823 m_Filters = 0;
5824 break;
5825 case 6: m_LoadRawFunction = &CLASS kodak_ycbcr_load_raw;
5826 m_Filters = 0;
5827 break;
5828 case 32803: m_LoadRawFunction = &CLASS kodak_65000_load_raw;
5829 }
5830 case 32867: break;
5831 default: m_IsRaw = 0;
5832 }
5833 if (!m_DNG_Version)
5834 if ( (m_Tiff_Samples == 3 && m_Tiff_IFD[l_Raw].bytes &&
5835 m_Tiff_bps != 14 && m_Tiff_bps != 2048 &&
5836 m_Tiff_Compress != 32769 && m_Tiff_Compress != 32770)
5837 || (m_Tiff_bps == 8 && !strstr(m_CameraMake,"KODAK") &&
5838 !strstr(m_CameraMake,"Kodak") &&
5839 !strstr(m_CameraModelBis,"DEBUG RAW")))
5840 m_IsRaw = 0;
5841
5842 for (i=0; (unsigned) i < m_Tiff_NrIFDs; i++) {
5843 auto l_denom1 = SQR(m_Tiff_IFD[i].bps+1);
5844 auto l_denom2 = SQR(m_ThumbMisc+1);
5845 if (l_denom1 == 0 || l_denom2 == 0)
5846 continue; // prevent divide by zero crash
5847
5848 if (i != l_Raw &&
5849 m_Tiff_IFD[i].samples == l_MaxSample &&
5850 (unsigned)(m_Tiff_IFD[i].width * m_Tiff_IFD[i].height / l_denom1) >
5851 m_ThumbWidth * m_ThumbHeight / l_denom2 &&
5852 m_Tiff_IFD[i].comp != 34892)
5853 {
5854 m_ThumbWidth = m_Tiff_IFD[i].width;
5855 m_ThumbHeight = m_Tiff_IFD[i].height;
5856 m_ThumbOffset = m_Tiff_IFD[i].offset;
5857 m_ThumbLength = m_Tiff_IFD[i].bytes;
5858 m_ThumbMisc = m_Tiff_IFD[i].bps;
5859 l_Thumb = i;
5860 }
5861 }
5862
5863 if (l_Thumb >= 0) {
5864 m_ThumbMisc |= m_Tiff_IFD[l_Thumb].samples << 5;
5865 switch (m_Tiff_IFD[l_Thumb].comp) {
5866 case 0:
5867 m_WriteThumb = &CLASS layer_thumb;
5868 break;
5869 case 1:
5870 if (m_Tiff_IFD[l_Thumb].bps <= 8)
5871 m_WriteThumb = &CLASS ppm_thumb;
5872 else if (!strcmp(m_CameraMake,"Imacon"))
5873 m_WriteThumb = &CLASS ppm16_thumb;
5874 else
5875 m_ThumbLoadRawFunction = &CLASS kodak_thumb_load_raw;
5876 break;
5877 case 65000:
5878 m_ThumbLoadRawFunction = m_Tiff_IFD[l_Thumb].phint == 6 ?
5879 &CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw;
5880 }
5881 }
5882 }
5883
parse_minolta(int base)5884 void CLASS parse_minolta (int base)
5885 {
5886 int save, tag, len, offset, high=0, wide=0, i, c;
5887 short sorder=m_ByteOrder;
5888
5889 fseek (m_InputFile, base, SEEK_SET);
5890 if (fgetc(m_InputFile) || fgetc(m_InputFile)-'M' || fgetc(m_InputFile)-'R') return;
5891 m_ByteOrder = fgetc(m_InputFile) * 0x101;
5892 offset = base + get4() + 8;
5893 while ((save=ftell(m_InputFile)) < offset) {
5894 for (tag=i=0; i < 4; i++)
5895 tag = tag << 8 | fgetc(m_InputFile);
5896 len = get4();
5897 switch (tag) {
5898 case 0x505244: /* PRD */
5899 fseek (m_InputFile, 8, SEEK_CUR);
5900 high = get2();
5901 wide = get2();
5902 break;
5903 case 0x574247: /* WBG */
5904 get4();
5905 i = strcmp(m_CameraModel,"DiMAGE A200") ? 0:3;
5906 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1) ^ i], get2());
5907 break;
5908 case 0x545457: /* TTW */
5909 parse_tiff (ftell(m_InputFile));
5910 m_Data_Offset = offset;
5911 }
5912 fseek (m_InputFile, save+len+8, SEEK_SET);
5913 }
5914 m_RawHeight = high;
5915 m_RawWidth = wide;
5916 m_ByteOrder = sorder;
5917 }
5918
5919 /*
5920 Many cameras have a "debug mode" that writes JPEG and raw
5921 at the same time. The raw file has no header, so try to
5922 to open the matching JPEG file and read its metadata.
5923 */
parse_external_jpeg()5924 void CLASS parse_external_jpeg()
5925 {
5926 const char *file, *ext;
5927 char *jname, *jfile, *jext;
5928 FILE *save=m_InputFile;
5929
5930 ext = strrchr (m_UserSetting_InputFileName, '.');
5931 file = strrchr (m_UserSetting_InputFileName, '/');
5932 if (!file) file = strrchr (m_UserSetting_InputFileName, '\\');
5933 if (!file) file = m_UserSetting_InputFileName-1;
5934 file++;
5935 if (!ext || strlen(ext) != 4 || ext-file != 8) return;
5936 jname = (char *) MALLOC (strlen(m_UserSetting_InputFileName) + 1);
5937 merror (jname, "parse_external_jpeg()");
5938 strcpy (jname, m_UserSetting_InputFileName);
5939 jfile = file - m_UserSetting_InputFileName + jname;
5940 jext = ext - m_UserSetting_InputFileName + jname;
5941 if (strcasecmp (ext, ".jpg")) {
5942 strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
5943 if (isdigit(*file)) {
5944 memcpy (jfile, file+4, 4);
5945 memcpy (jfile+4, file, 4);
5946 }
5947 } else
5948 while (isdigit(*--jext)) {
5949 if (*jext != '9') {
5950 (*jext)++;
5951 break;
5952 }
5953 *jext = '0';
5954 }
5955 if (strcmp (jname, m_UserSetting_InputFileName)) {
5956 if ((m_InputFile = fopen (jname, "rb"))) {
5957 TRACEKEYVALS("Reading metadata from","%s",jname);
5958 parse_tiff (12);
5959 m_ThumbOffset = 0;
5960 m_IsRaw = 1;
5961 FCLOSE (m_InputFile);
5962 }
5963 }
5964 if (!m_TimeStamp)
5965 fprintf (stderr,_("Failed to read metadata from %s\n"), jname);
5966 FREE (jname);
5967 m_InputFile = save;
5968 }
5969
5970 /*
5971 CIFF block 0x1030 contains an 8x8 white sample.
5972 Load this into white[][] for use in scale_colors().
5973 */
ciff_block_1030()5974 void CLASS ciff_block_1030()
5975 {
5976 static const uint16_t key[] = { 0x410, 0x45f3 };
5977 int i, bpp, row, col, vbits=0;
5978 unsigned long bitbuf=0;
5979
5980 if ((get2(),get4()) != 0x80008 || !get4()) return;
5981 bpp = get2();
5982 if (bpp != 10 && bpp != 12) return;
5983 for (i=row=0; row < 8; row++)
5984 for (col=0; col < 8; col++) {
5985 if (vbits < bpp) {
5986 bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
5987 vbits += 16;
5988 }
5989 white[row][col] =
5990 bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp);
5991 vbits -= bpp;
5992 }
5993 }
5994
5995 /*
5996 Parse a CIFF file, better known as Canon CRW format.
5997 */
parse_ciff(int offset,int length)5998 void CLASS parse_ciff (int offset, int length)
5999 {
6000 int tboff, nrecs, c, type, len, save, wbi=-1;
6001 uint16_t key[] = { 0x410, 0x45f3 };
6002
6003 fseek (m_InputFile, offset+length-4, SEEK_SET);
6004 tboff = get4() + offset;
6005 fseek (m_InputFile, tboff, SEEK_SET);
6006 nrecs = get2();
6007 if (nrecs > 100) return;
6008 while (nrecs--) {
6009 type = get2();
6010 len = get4();
6011 save = ftell(m_InputFile) + 4;
6012 fseek (m_InputFile, offset+get4(), SEEK_SET);
6013 if ((((type >> 8) + 8) | 8) == 0x38)
6014 parse_ciff (ftell(m_InputFile), len); /* Parse a sub-table */
6015
6016 if (type == 0x0810)
6017 ptfread (m_Artist, 64, 1, m_InputFile);
6018 if (type == 0x080a) {
6019 ptfread (m_CameraMake, 64, 1, m_InputFile);
6020 fseek (m_InputFile, strlen(m_CameraMake) - 63, SEEK_CUR);
6021 ptfread (m_CameraModel, 64, 1, m_InputFile);
6022 }
6023 if (type == 0x1810) {
6024 fseek (m_InputFile, 12, SEEK_CUR);
6025 m_Flip = get4();
6026 }
6027 if (type == 0x1835) /* Get the decoder table */
6028 m_Tiff_Compress = get4();
6029 if (type == 0x2007) {
6030 m_ThumbOffset = ftell(m_InputFile);
6031 m_ThumbLength = len;
6032 }
6033 if (type == 0x1818) {
6034 m_Shutter = pow (2, -int_to_float((get4(),get4())));
6035 m_Aperture = pow (2, int_to_float(get4())/2);
6036 }
6037 if (type == 0x102a) {
6038 m_IsoSpeed = pow (2, (get4(),get2())/32.0 - 4) * 50;
6039 m_Aperture = pow (2, (get2(),(short)get2())/64.0);
6040 m_Shutter = pow (2,-((short)get2())/32.0);
6041 wbi = (get2(),get2());
6042 if (wbi > 17) wbi = 0;
6043 fseek (m_InputFile, 32, SEEK_CUR);
6044 if (m_Shutter > 1e6) m_Shutter = get2()/10.0;
6045 }
6046 if (type == 0x102c) {
6047 if (get2() > 512) { /* Pro90, G1 */
6048 fseek (m_InputFile, 118, SEEK_CUR);
6049 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ 2], get2());
6050 } else { /* G2, S30, S40 */
6051 fseek (m_InputFile, 98, SEEK_CUR);
6052 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1) ^ 1], get2());
6053 }
6054 }
6055 if (type == 0x0032) {
6056 if (len == 768) { /* EOS D30 */
6057 fseek (m_InputFile, 72, SEEK_CUR);
6058 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], 1024.0 / get2());
6059 if (!wbi) ASSIGN(m_CameraMultipliers[0], -1); /* use my auto white balance */
6060 } else if (!VALUE(m_CameraMultipliers[0])) {
6061 if (get2() == key[0]) /* Pro1, G6, S60, S70 */
6062 c = (strstr(m_CameraModel,"Pro1") ?
6063 "012346000000000000":"01345:000000006008")[wbi]-'0'+ 2;
6064 else { /* G3, G5, S45, S50 */
6065 c = "023457000000006000"[wbi]-'0';
6066 key[0] = key[1] = 0;
6067 }
6068 fseek (m_InputFile, 78 + c*8, SEEK_CUR);
6069 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1) ^ 1], get2() ^ key[c & 1]);
6070 if (!wbi) ASSIGN(m_CameraMultipliers[0], -1);
6071 }
6072 }
6073 if (type == 0x10a9) { /* D60, 10D, 300D, and clones */
6074 if (len > 66) wbi = "0134567028"[wbi]-'0';
6075 fseek (m_InputFile, 2 + wbi*8, SEEK_CUR);
6076 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], get2());
6077 }
6078 if (type == 0x1030 && (0x18040 >> wbi & 1))
6079 ciff_block_1030(); /* all that don't have 0x10a9 */
6080 if (type == 0x1031) {
6081 m_RawWidth = (get2(),get2());
6082 m_RawHeight = get2();
6083 }
6084 if (type == 0x5029) {
6085 m_FocalLength = len >> 16;
6086 if ((len & 0xffff) == 2) m_FocalLength /= 32;
6087 }
6088 if (type == 0x5813) flash_used = int_to_float(len);
6089 if (type == 0x5814) canon_ev = int_to_float(len);
6090 if (type == 0x5817) m_ShotOrder = len;
6091 if (type == 0x5834) unique_id = len;
6092 if (type == 0x580e) m_TimeStamp = len;
6093 if (type == 0x180e) m_TimeStamp = get4();
6094 #ifdef LOCALTIME
6095 if ((type | 0x4000) == 0x580e)
6096 m_TimeStamp = mktime (gmtime (&m_TimeStamp));
6097 #endif
6098 fseek (m_InputFile, save, SEEK_SET);
6099 }
6100 }
6101
parse_rollei()6102 void CLASS parse_rollei()
6103 {
6104 char line[128], *val;
6105 struct tm t;
6106
6107 fseek (m_InputFile, 0, SEEK_SET);
6108 memset (&t, 0, sizeof t);
6109 do {
6110 ptfgets (line, 128, m_InputFile);
6111 if ((val = strchr(line,'=')))
6112 *val++ = 0;
6113 else
6114 val = line + strlen(line);
6115 if (!strcmp(line,"DAT"))
6116 sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
6117 if (!strcmp(line,"TIM"))
6118 sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
6119 if (!strcmp(line,"HDR"))
6120 m_ThumbOffset = atoi(val);
6121 if (!strcmp(line,"X "))
6122 m_RawWidth = atoi(val);
6123 if (!strcmp(line,"Y "))
6124 m_RawHeight = atoi(val);
6125 if (!strcmp(line,"TX "))
6126 m_ThumbWidth = atoi(val);
6127 if (!strcmp(line,"TY "))
6128 m_ThumbHeight = atoi(val);
6129 } while (strncmp(line,"EOHD",4));
6130 m_Data_Offset = m_ThumbOffset + m_ThumbWidth * m_ThumbHeight * 2;
6131 t.tm_year -= 1900;
6132 t.tm_mon -= 1;
6133 if (mktime(&t) > 0)
6134 m_TimeStamp = mktime(&t);
6135 strcpy (m_CameraMake, "Rollei");
6136 strcpy (m_CameraModel,"d530flex");
6137 m_WriteThumb = &CLASS rollei_thumb;
6138 }
6139
parse_sinar_ia()6140 void CLASS parse_sinar_ia()
6141 {
6142 int entries, off;
6143 char str[8], *cp;
6144
6145 m_ByteOrder = 0x4949;
6146 fseek (m_InputFile, 4, SEEK_SET);
6147 entries = get4();
6148 fseek (m_InputFile, get4(), SEEK_SET);
6149 while (entries--) {
6150 off = get4(); get4();
6151 ptfread (str, 8, 1, m_InputFile);
6152 if (!strcmp(str,"META")) meta_offset = off;
6153 if (!strcmp(str,"THUMB")) m_ThumbOffset = off;
6154 if (!strcmp(str,"RAW0")) m_Data_Offset = off;
6155 }
6156 fseek (m_InputFile, meta_offset+20, SEEK_SET);
6157 ptfread (m_CameraMake, 64, 1, m_InputFile);
6158 m_CameraMake[63] = 0;
6159 if ((cp = strchr(m_CameraMake,' '))) {
6160 strcpy (m_CameraModel, cp+1);
6161 *cp = 0;
6162 }
6163 m_RawWidth = get2();
6164 m_RawHeight = get2();
6165 m_LoadRawFunction = &CLASS unpacked_load_raw;
6166 m_ThumbWidth = (get4(),get2());
6167 m_ThumbHeight = get2();
6168 m_WriteThumb = &CLASS ppm_thumb;
6169 m_WhiteLevel = 0x3fff;
6170 }
6171
parse_phase_one(int base)6172 void CLASS parse_phase_one (int base)
6173 {
6174 //warning: variable 'type' set but not used [-Wunused-but-set-variable]
6175 unsigned entries, tag, /*type,*/ len, data, save, i, c;
6176 float romm_cam[3][3];
6177 char *cp;
6178
6179 memset (&ph1, 0, sizeof ph1);
6180 fseek (m_InputFile, base, SEEK_SET);
6181 m_ByteOrder = get4() & 0xffff;
6182 if (get4() >> 8 != 0x526177) return; /* "Raw" */
6183 fseek (m_InputFile, get4()+base, SEEK_SET);
6184 entries = get4();
6185 get4();
6186 while (entries--) {
6187 tag = get4();
6188 // type = get4();
6189 len = get4();
6190 data = get4();
6191 save = ftell(m_InputFile);
6192 fseek (m_InputFile, base+data, SEEK_SET);
6193 switch (tag) {
6194 case 0x100: m_Flip = "0653"[data & 3]-'0'; break;
6195 case 0x106:
6196 for (i=0; i < 3; i++)
6197 for (short j=0; j<3; j++)
6198 romm_cam[i][j] = getreal(11);
6199 romm_coeff (romm_cam);
6200 break;
6201 case 0x107:
6202 for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], getreal(11));
6203 break;
6204 case 0x108: m_RawWidth = data; break;
6205 case 0x109: m_RawHeight = data; break;
6206 case 0x10a: m_LeftMargin = data; break;
6207 case 0x10b: m_TopMargin = data; break;
6208 case 0x10c: m_Width = data; break;
6209 case 0x10d: m_Height = data; break;
6210 case 0x10e: ph1.format = data; break;
6211 case 0x10f: m_Data_Offset = data+base; break;
6212 case 0x110: meta_offset = data+base;
6213 m_MetaLength = len; break;
6214 case 0x112: ph1.key_off = save - 4; break;
6215 case 0x210: ph1.tag_210 = int_to_float(data); break;
6216 case 0x21a: ph1.tag_21a = data; break;
6217 case 0x21c: strip_offset = data+base; break;
6218 case 0x21d: ph1.black = data; break;
6219 case 0x222: ph1.split_col = data; break;
6220 case 0x223: ph1.black_off = data+base; break;
6221 case 0x301:
6222 m_CameraModel[63] = 0;
6223 ptfread (m_CameraModel, 1, 63, m_InputFile);
6224 if ((cp = strstr(m_CameraModel," camera"))) *cp = 0;
6225 }
6226 fseek (m_InputFile, save, SEEK_SET);
6227 }
6228 m_LoadRawFunction = ph1.format < 3 ?
6229 &CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c;
6230 m_WhiteLevel = 0xffff;
6231 strcpy (m_CameraMake, "Phase One");
6232 if (m_CameraModel[0]) return;
6233 switch (m_RawHeight) {
6234 case 2060: strcpy (m_CameraModel,"LightPhase"); break;
6235 case 2682: strcpy (m_CameraModel,"H 10"); break;
6236 case 4128: strcpy (m_CameraModel,"H 20"); break;
6237 case 5488: strcpy (m_CameraModel,"H 25"); break;
6238 }
6239 }
6240
parse_fuji(int offset)6241 void CLASS parse_fuji (int offset)
6242 {
6243 unsigned entries, tag, len, save, c;
6244
6245 fseek (m_InputFile, offset, SEEK_SET);
6246 entries = get4();
6247 if (entries > 255) return;
6248 while (entries--) {
6249 tag = get2();
6250 len = get2();
6251 save = ftell(m_InputFile);
6252 if (tag == 0x100) {
6253 m_RawHeight = get2();
6254 m_RawWidth = get2();
6255 } else if (tag == 0x121) {
6256 m_Height = get2();
6257 if ((m_Width = get2()) == 4284) m_Width += 3;
6258 } else if (tag == 0x130) {
6259 fuji_layout = fgetc(m_InputFile) >> 7;
6260 m_Fuji_Width = !(fgetc(m_InputFile) & 8);
6261 } else if (tag == 0x2ff0) {
6262 for (c=0; c<4; c++) m_CameraMultipliers[c ^ 1] = get2();
6263 } else if (tag == 0xc000) {
6264 c = m_ByteOrder;
6265 m_ByteOrder = 0x4949;
6266 if ((m_Width = get4()) > 10000) m_Width = get4();
6267 m_Height = get4();
6268 m_ByteOrder = c;
6269 }
6270 fseek (m_InputFile, save+len, SEEK_SET);
6271
6272 }
6273 if (!m_RawHeight) {
6274 m_Filters = 0x16161616;
6275 m_LoadRawFunction = &CLASS packed_load_raw;
6276 m_Load_Flags = 24;
6277 }
6278 m_Height <<= fuji_layout;
6279 m_Width >>= fuji_layout;
6280 }
6281
parse_jpeg(int offset)6282 int CLASS parse_jpeg (int offset)
6283 {
6284 int len, save, hlen, mark;
6285
6286 fseek (m_InputFile, offset, SEEK_SET);
6287 if (fgetc(m_InputFile) != 0xff || fgetc(m_InputFile) != 0xd8) return 0;
6288
6289 while (fgetc(m_InputFile) == 0xff && (mark = fgetc(m_InputFile)) != 0xda) {
6290 m_ByteOrder = 0x4d4d;
6291 len = get2() - 2;
6292 save = ftell(m_InputFile);
6293 if (mark == 0xc0 || mark == 0xc3) {
6294 fgetc(m_InputFile);
6295 m_RawHeight = get2();
6296 m_RawWidth = get2();
6297 }
6298 m_ByteOrder = get2();
6299 hlen = get4();
6300 if (get4() == 0x48454150) /* "HEAP" */
6301 parse_ciff (save+hlen, len-hlen);
6302 if (parse_tiff (save+6)) apply_tiff();
6303 fseek (m_InputFile, save+len, SEEK_SET);
6304 }
6305 return 1;
6306 }
6307
parse_riff()6308 void CLASS parse_riff()
6309 {
6310 unsigned i, size, end;
6311 char tag[4], date[64], month[64];
6312 static const char mon[12][4] =
6313 { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
6314 struct tm t;
6315
6316 m_ByteOrder = 0x4949;
6317 ptfread (tag, 4, 1, m_InputFile);
6318 size = get4();
6319 end = ftell(m_InputFile) + size;
6320 if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) {
6321 get4();
6322 while (ftell(m_InputFile)+7 < (long) end)
6323 parse_riff();
6324 } else if (!memcmp(tag,"nctg",4)) {
6325 while ((unsigned) ftell(m_InputFile)+7 < end) {
6326 i = get2();
6327 size = get2();
6328 if ((i+1) >> 1 == 10 && size == 20)
6329 get_timestamp(0);
6330 else fseek (m_InputFile, size, SEEK_CUR);
6331 }
6332 } else if (!memcmp(tag,"IDIT",4) && size < 64) {
6333 ptfread (date, 64, 1, m_InputFile);
6334 date[size] = 0;
6335 memset (&t, 0, sizeof t);
6336 if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday,
6337 &t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) {
6338 for (i=0; i < 12 && strcasecmp(mon[i],month); i++) {};
6339 t.tm_mon = i;
6340 t.tm_year -= 1900;
6341 if (mktime(&t) > 0)
6342 m_TimeStamp = mktime(&t);
6343 }
6344 } else
6345 fseek (m_InputFile, size, SEEK_CUR);
6346 }
6347
parse_smal(int offset,int fsize)6348 void CLASS parse_smal (int offset, int fsize)
6349 {
6350 int ver;
6351
6352 fseek (m_InputFile, offset+2, SEEK_SET);
6353 m_ByteOrder = 0x4949;
6354 ver = fgetc(m_InputFile);
6355 if (ver == 6)
6356 fseek (m_InputFile, 5, SEEK_CUR);
6357 if (get4() != (unsigned) fsize) return;
6358 if (ver > 6) m_Data_Offset = get4();
6359 m_RawHeight = m_Height = get2();
6360 m_RawWidth = m_Width = get2();
6361 strcpy (m_CameraMake, "SMaL");
6362 sprintf (m_CameraModel, "v%d %dx%d", ver, m_Width, m_Height);
6363 if (ver == 6) m_LoadRawFunction = &CLASS smal_v6_load_raw;
6364 if (ver == 9) m_LoadRawFunction = &CLASS smal_v9_load_raw;
6365 }
6366
parse_cine()6367 void CLASS parse_cine()
6368 {
6369 unsigned off_head, off_setup, off_image, i;
6370
6371 m_ByteOrder = 0x4949;
6372 fseek (m_InputFile, 4, SEEK_SET);
6373 m_IsRaw = get2() == 2;
6374 fseek (m_InputFile, 14, SEEK_CUR);
6375 m_IsRaw *= get4();
6376 off_head = get4();
6377 off_setup = get4();
6378 off_image = get4();
6379 m_TimeStamp = get4();
6380 if ((i = get4())) m_TimeStamp = i;
6381 fseek (m_InputFile, off_head+4, SEEK_SET);
6382 m_RawWidth = get4();
6383 m_RawHeight = get4();
6384 switch (get2(),get2()) {
6385 case 8: m_LoadRawFunction = &CLASS eight_bit_load_raw; break;
6386 case 16: m_LoadRawFunction = &CLASS unpacked_load_raw;
6387 }
6388 fseek (m_InputFile, off_setup+792, SEEK_SET);
6389 strcpy (m_CameraMake, "CINE");
6390 sprintf (m_CameraModel, "%d", get4());
6391 fseek (m_InputFile, 12, SEEK_CUR);
6392 switch ((i=get4()) & 0xffffff) {
6393 case 3: m_Filters = 0x94949494; break;
6394 case 4: m_Filters = 0x49494949; break;
6395 default: m_IsRaw = 0;
6396 }
6397 fseek (m_InputFile, 72, SEEK_CUR);
6398 switch ((get4()+3600) % 360) {
6399 case 270: m_Flip = 4; break;
6400 case 180: m_Flip = 1; break;
6401 case 90: m_Flip = 7; break;
6402 case 0: m_Flip = 2;
6403 }
6404 ASSIGN(m_CameraMultipliers[0], getreal(11));
6405 ASSIGN(m_CameraMultipliers[2], getreal(11));
6406 m_WhiteLevel = ~(-1 << get4());
6407 fseek (m_InputFile, 668, SEEK_CUR);
6408 m_Shutter = get4()/1000000000.0;
6409 fseek (m_InputFile, off_image, SEEK_SET);
6410 if (m_UserSetting_ShotSelect < m_IsRaw)
6411 fseek (m_InputFile, m_UserSetting_ShotSelect*8, SEEK_CUR);
6412 m_Data_Offset = (int64_t) get4() + 8;
6413 m_Data_Offset += (int64_t) get4() << 32;
6414 }
6415
parse_redcine()6416 void CLASS parse_redcine()
6417 {
6418 unsigned i, len, rdvo;
6419
6420 m_ByteOrder = 0x4d4d;
6421 m_IsRaw = 0;
6422 fseek (m_InputFile, 52, SEEK_SET);
6423 m_Width = get4();
6424 m_Height = get4();
6425 fseek (m_InputFile, 0, SEEK_END);
6426 fseek (m_InputFile, -(i = ftell(m_InputFile) & 511), SEEK_CUR);
6427 if (get4() != i || get4() != 0x52454f42) {
6428 fprintf (stderr,_("%s: Tail is missing, parsing from head...\n"), m_UserSetting_InputFileName);
6429 fseek (m_InputFile, 0, SEEK_SET);
6430 while ((int)(len = get4()) != EOF) {
6431 if (get4() == 0x52454456)
6432 if (m_IsRaw++ == m_UserSetting_ShotSelect)
6433 m_Data_Offset = ftell(m_InputFile) - 8;
6434 fseek (m_InputFile, len-8, SEEK_CUR);
6435 }
6436 } else {
6437 rdvo = get4();
6438 fseek (m_InputFile, 12, SEEK_CUR);
6439 m_IsRaw = get4();
6440 fseek (m_InputFile, rdvo+8 + m_UserSetting_ShotSelect*4, SEEK_SET);
6441 m_Data_Offset = get4();
6442 }
6443 }
6444
foveon_gets(int offset,char * str,int len)6445 char * CLASS foveon_gets (int offset, char *str, int len)
6446 {
6447 int i;
6448 fseek (m_InputFile, offset, SEEK_SET);
6449 for (i=0; i < len-1; i++)
6450 if ((str[i] = get2()) == 0) break;
6451 str[i] = 0;
6452 return str;
6453 }
6454
parse_foveon()6455 void CLASS parse_foveon()
6456 {
6457 int entries, img=0, off, len, tag, save, i, wide, high, pent, poff[256][2];
6458 char name[64], value[64];
6459
6460 m_ByteOrder = 0x4949; /* Little-endian */
6461 fseek (m_InputFile, 36, SEEK_SET);
6462 m_Flip = get4();
6463 fseek (m_InputFile, -4, SEEK_END);
6464 fseek (m_InputFile, get4(), SEEK_SET);
6465 if (get4() != 0x64434553) return; /* SECd */
6466 entries = (get4(),get4());
6467 while (entries--) {
6468 off = get4();
6469 len = get4();
6470 tag = get4();
6471 save = ftell(m_InputFile);
6472 fseek (m_InputFile, off, SEEK_SET);
6473 if (get4() != (unsigned)(0x20434553 | (tag << 24))) return;
6474 switch (tag) {
6475 case 0x47414d49: /* IMAG */
6476 case 0x32414d49: /* IMA2 */
6477 fseek (m_InputFile, 8, SEEK_CUR);
6478 pent = get4();
6479 wide = get4();
6480 high = get4();
6481 if (wide > m_RawWidth && high > m_RawHeight) {
6482 switch (pent) {
6483 case 5: m_Load_Flags = 1;
6484 case 6: m_LoadRawFunction = &CLASS foveon_sd_load_raw; break;
6485 case 30: m_LoadRawFunction = &CLASS foveon_dp_load_raw; break;
6486 default: m_LoadRawFunction = 0;
6487 }
6488 m_RawWidth = wide;
6489 m_RawHeight = high;
6490 m_Data_Offset = off+28;
6491 }
6492 fseek (m_InputFile, off+28, SEEK_SET);
6493 if (fgetc(m_InputFile) == 0xff && fgetc(m_InputFile) == 0xd8
6494 && m_ThumbLength < (unsigned)(len-28)) {
6495 m_ThumbOffset = off+28;
6496 m_ThumbLength = len-28;
6497 m_WriteThumb = &CLASS jpeg_thumb;
6498 }
6499 if (++img == 2 && !m_ThumbLength) {
6500 m_ThumbOffset = off+24;
6501 m_ThumbWidth = wide;
6502 m_ThumbHeight = high;
6503 m_WriteThumb = &CLASS foveon_thumb;
6504 }
6505 break;
6506 case 0x464d4143: /* CAMF */
6507 meta_offset = off+8;
6508 m_MetaLength = len-28;
6509 break;
6510 case 0x504f5250: /* PROP */
6511 pent = (get4(),get4());
6512 fseek (m_InputFile, 12, SEEK_CUR);
6513 off += pent*8 + 24;
6514 if ((unsigned) pent > 256) pent=256;
6515 for (i=0; i < pent*2; i++)
6516 poff[0][i] = off + get4()*2;
6517 for (i=0; i < pent; i++) {
6518 foveon_gets (poff[i][0], name, 64);
6519 foveon_gets (poff[i][1], value, 64);
6520 if (!strcmp (name, "ISO"))
6521 m_IsoSpeed = atoi(value);
6522 if (!strcmp (name, "CAMMANUF"))
6523 strcpy (m_CameraMake, value);
6524 if (!strcmp (name, "CAMMODEL"))
6525 strcpy (m_CameraModel, value);
6526 if (!strcmp (name, "WB_DESC"))
6527 strcpy (m_CameraModelBis, value);
6528 if (!strcmp (name, "TIME"))
6529 m_TimeStamp = atoi(value);
6530 if (!strcmp (name, "EXPTIME"))
6531 m_Shutter = atoi(value) / 1000000.0;
6532 if (!strcmp (name, "APERTURE"))
6533 m_Aperture = atof(value);
6534 if (!strcmp (name, "FLENGTH"))
6535 m_FocalLength = atof(value);
6536 }
6537 #ifdef LOCALTIME
6538 m_TimeStamp = mktime (gmtime (&m_TimeStamp));
6539 #endif
6540 }
6541 fseek (m_InputFile, save, SEEK_SET);
6542 }
6543 m_IsFoveon = 1;
6544 }
6545
6546 /*
6547 Thanks to Adobe for providing these excellent CAM -> XYZ matrices!
6548 All matrices are from Adobe DNG Converter unless otherwise noted.
6549
6550 */
6551
6552 #include "ptAdobeTable.h"
6553
adobe_coeff(const char * make,const char * model)6554 void CLASS adobe_coeff (const char *make, const char *model) {
6555 double MatrixXYZToCamRGB[4][3];
6556 char name[130];
6557 unsigned i;
6558 sprintf (name, "%s %s", make , model);
6559 for (i=0; i < sizeof AdobeTable / sizeof *AdobeTable; i++)
6560 if (!strncmp (name,
6561 AdobeTable[i].Identification,
6562 strlen(AdobeTable[i].Identification))) {
6563 strcpy(m_CameraAdobeIdentification,AdobeTable[i].Identification);
6564 if (AdobeTable[i].Blackpoint) {
6565 m_BlackLevel = (uint16_t) AdobeTable[i].Blackpoint;
6566 }
6567 if (AdobeTable[i].Whitepoint) {
6568 m_WhiteLevel = (uint16_t) AdobeTable[i].Whitepoint;
6569 }
6570 if (AdobeTable[i].XYZToCam[0]) {
6571 for (short j=0; j < 4; j++) {
6572 for (short k=0; k<3; k++) {
6573 MatrixXYZToCamRGB[j][k] = AdobeTable[i].XYZToCam[j*3+k] / 10000.0;
6574 }
6575 }
6576 cam_xyz_coeff (MatrixXYZToCamRGB);
6577 }
6578 break;
6579 }
6580 }
6581
simple_coeff(int index)6582 void CLASS simple_coeff (int index)
6583 {
6584 static const float table[][12] = {
6585 /* index 0 -- all Foveon cameras */
6586 { 1.4032,-0.2231,-0.1016,-0.5263,1.4816,0.017,-0.0112,0.0183,0.9113 },
6587 /* index 1 -- Kodak DC20 and DC25 */
6588 { 2.25,0.75,-1.75,-0.25,-0.25,0.75,0.75,-0.25,-0.25,-1.75,0.75,2.25 },
6589 /* index 2 -- Logitech Fotoman Pixtura */
6590 { 1.893,-0.418,-0.476,-0.495,1.773,-0.278,-1.017,-0.655,2.672 },
6591 /* index 3 -- Nikon E880, E900, and E990 */
6592 { -1.936280, 1.800443, -1.448486, 2.584324,
6593 1.405365, -0.524955, -0.289090, 0.408680,
6594 -1.204965, 1.082304, 2.941367, -1.818705 }
6595 };
6596 int i, c;
6597
6598 for (m_RawColor = i=0; i < 3; i++)
6599 for (c=0; c < m_Colors; c++) m_MatrixCamRGBToSRGB[i][c] = table[index][i*m_Colors+c];
6600 }
6601
guess_byte_order(int words)6602 short CLASS guess_byte_order (int words)
6603 {
6604 uint8_t test[4][2];
6605 int t=2, msb;
6606 double diff, sum[2] = {0,0};
6607
6608 ptfread (test[0], 2, 2, m_InputFile);
6609 for (words-=2; words--; ) {
6610 ptfread (test[t], 2, 1, m_InputFile);
6611 for (msb=0; msb < 2; msb++) {
6612 diff = (test[t^2][msb] << 8 | test[t^2][!msb])
6613 - (test[t ][msb] << 8 | test[t ][!msb]);
6614 sum[msb] += diff*diff;
6615 }
6616 t = (t+1) & 3;
6617 }
6618 return sum[0] < sum[1] ? 0x4d4d : 0x4949;
6619 }
6620
find_green(int bps,int bite,int off0,int off1)6621 float CLASS find_green (int bps, int bite, int off0, int off1)
6622 {
6623 uint64_t bitbuf=0;
6624 int vbits, col, i, c;
6625 uint16_t img[2][2064];
6626 double sum[]={0,0};
6627
6628 for (c=0;c<2;c++) {
6629 fseek (m_InputFile, c ? off1:off0, SEEK_SET);
6630 for (vbits=col=0; col < m_Width; col++) {
6631 for (vbits -= bps; vbits < 0; vbits += bite) {
6632 bitbuf <<= bite;
6633 for (i=0; i < bite; i+=8)
6634 bitbuf |= (unsigned) (fgetc(m_InputFile) << i);
6635 }
6636 img[c][col] = bitbuf << (64-bps-vbits) >> (64-bps);
6637 }
6638 }
6639 for (c=0;c<(m_Width-1);c++) {
6640 sum[ c & 1] += ABS(img[0][c]-img[1][c+1]);
6641 sum[~c & 1] += ABS(img[1][c]-img[0][c+1]);
6642 }
6643 return 100 * log(sum[0]/sum[1]);
6644 }
6645
6646 /*
6647 Identify which camera created this file, and set global variables
6648 accordingly.
6649 */
6650
identify()6651 void CLASS identify() {
6652 char l_Head[32];
6653 char* l_CharPointer;
6654 unsigned l_HLen;
6655 unsigned l_FLen;
6656 unsigned l_FileSize;
6657 int zero_fsize = 1;
6658 unsigned l_IsCanon;
6659 struct jhead l_JHead;
6660 unsigned i,c;
6661 short pana[][6] = {
6662 { 3130, 1743, 4, 0, -6, 0 },
6663 { 3130, 2055, 4, 0, -6, 0 },
6664 { 3130, 2319, 4, 0, -6, 0 },
6665 { 3170, 2103, 18, 0,-42, 20 },
6666 { 3170, 2367, 18, 13,-42,-21 },
6667 { 3177, 2367, 0, 0, -1, 0 },
6668 { 3304, 2458, 0, 0, -1, 0 },
6669 { 3330, 2463, 9, 0, -5, 0 },
6670 { 3330, 2479, 9, 0,-17, 4 },
6671 { 3370, 1899, 15, 0,-44, 20 },
6672 { 3370, 2235, 15, 0,-44, 20 },
6673 { 3370, 2511, 15, 10,-44,-21 },
6674 { 3690, 2751, 3, 0, -8, -3 },
6675 { 3710, 2751, 0, 0, -3, 0 },
6676 { 3724, 2450, 0, 0, 0, -2 },
6677 { 3770, 2487, 17, 0,-44, 19 },
6678 { 3770, 2799, 17, 15,-44,-19 },
6679 { 3880, 2170, 6, 0, -6, 0 },
6680 { 4060, 3018, 0, 0, 0, -2 },
6681 { 4290, 2391, 3, 0, -8, -1 },
6682 { 4330, 2439, 17, 15,-44,-19 },
6683 { 4508, 2962, 0, 0, -3, -4 },
6684 { 4508, 3330, 0, 0, -3, -6 } };
6685
6686 static const struct {
6687 int fsize;
6688 char make[12], model[19], withjpeg;
6689 } l_Table[] = {
6690 { 62464, "Kodak", "DC20" ,0 },
6691 { 124928, "Kodak", "DC20" ,0 },
6692 { 1652736, "Kodak", "DCS200" ,0 },
6693 { 4159302, "Kodak", "C330" ,0 },
6694 { 4162462, "Kodak", "C330" ,0 },
6695 { 460800, "Kodak", "C603v" ,0 },
6696 { 614400, "Kodak", "C603v" ,0 },
6697 { 6163328, "Kodak", "C603" ,0 },
6698 { 6166488, "Kodak", "C603" ,0 },
6699 { 9116448, "Kodak", "C603y" ,0 },
6700 { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */
6701 { 787456, "Creative", "PC-CAM 600" ,0 },
6702 { 1138688, "Minolta", "RD175" ,0 },
6703 { 3840000, "Foculus", "531C" ,0 },
6704 { 307200, "Generic", "640x480" ,0 },
6705 { 786432, "AVT", "F-080C" ,0 },
6706 { 1447680, "AVT", "F-145C" ,0 },
6707 { 1920000, "AVT", "F-201C" ,0 },
6708 { 5067304, "AVT", "F-510C" ,0 },
6709 { 5067316, "AVT", "F-510C" ,0 },
6710 { 10134608, "AVT", "F-510C" ,0 },
6711 { 10134620, "AVT", "F-510C" ,0 },
6712 { 16157136, "AVT", "F-810C" ,0 },
6713 { 1409024, "Sony", "XCD-SX910CR" ,0 },
6714 { 2818048, "Sony", "XCD-SX910CR" ,0 },
6715 { 3884928, "Micron", "2010" ,0 },
6716 { 6624000, "Pixelink", "A782" ,0 },
6717 { 13248000, "Pixelink", "A782" ,0 },
6718 { 6291456, "RoverShot","3320AF" ,0 },
6719 { 6553440, "Canon", "PowerShot A460" ,0 },
6720 { 6653280, "Canon", "PowerShot A530" ,0 },
6721 { 6573120, "Canon", "PowerShot A610" ,0 },
6722 { 9219600, "Canon", "PowerShot A620" ,0 },
6723 { 9243240, "Canon", "PowerShot A470" ,0 },
6724 { 10341600, "Canon", "PowerShot A720 IS" ,0 },
6725 { 10383120, "Canon", "PowerShot A630" ,0 },
6726 { 12945240, "Canon", "PowerShot A640" ,0 },
6727 { 15636240, "Canon", "PowerShot A650" ,0 },
6728 { 5298000, "Canon", "PowerShot SD300" ,0 },
6729 { 7710960, "Canon", "PowerShot S3 IS" ,0 },
6730 { 15467760, "Canon", "PowerShot SX110 IS",0 },
6731 { 15534576, "Canon", "PowerShot SX120 IS",0 },
6732 { 18653760, "Canon", "PowerShot SX20 IS",0 },
6733 { 19131120, "Canon", "PowerShot SX220 HS",0 },
6734 { 21936096, "Canon", "PowerShot SX30 IS",0 },
6735 { 5939200, "OLYMPUS", "C770UZ" ,0 },
6736 { 1581060, "NIKON", "E900" ,1 }, /* or E900s,E910 */
6737 { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */
6738 { 2940928, "NIKON", "E2100" ,1 }, /* or E2500 */
6739 { 4771840, "NIKON", "E990" ,1 }, /* or E995, Oly C3030Z */
6740 { 4775936, "NIKON", "E3700" ,1 }, /* or Optio 33WR */
6741 { 5869568, "NIKON", "E4300" ,1 }, /* or DiMAGE Z2 */
6742 { 5865472, "NIKON", "E4500" ,1 },
6743 { 7438336, "NIKON", "E5000" ,1 }, /* or E5700 */
6744 { 8998912, "NIKON", "COOLPIX S6" ,1 },
6745 { 1976352, "CASIO", "QV-2000UX" ,1 },
6746 { 3217760, "CASIO", "QV-3*00EX" ,1 },
6747 { 6218368, "CASIO", "QV-5700" ,1 },
6748 { 6054400, "CASIO", "QV-R41" ,1 },
6749 { 7530816, "CASIO", "QV-R51" ,1 },
6750 { 7684000, "CASIO", "QV-4000" ,1 },
6751 { 2937856, "CASIO", "EX-S20" ,1 },
6752 { 4948608, "CASIO", "EX-S100" ,1 },
6753 { 7542528, "CASIO", "EX-Z50" ,1 },
6754 { 7562048, "CASIO", "EX-Z500" ,1 },
6755 { 7753344, "CASIO", "EX-Z55" ,1 },
6756 { 7816704, "CASIO", "EX-Z60" ,1 },
6757 { 10843712, "CASIO", "EX-Z75" ,1 },
6758 { 10834368, "CASIO", "EX-Z750" ,1 },
6759 { 12310144, "CASIO", "EX-Z850" ,1 },
6760 { 12489984, "CASIO", "EX-Z8" ,1 },
6761 { 15499264, "CASIO", "EX-Z1050" ,1 },
6762 { 18702336, "CASIO", "EX-ZR100" ,1 },
6763 { 7426656, "CASIO", "EX-P505" ,1 },
6764 { 9313536, "CASIO", "EX-P600" ,1 },
6765 { 10979200, "CASIO", "EX-P700" ,1 },
6766 { 3178560, "PENTAX", "Optio S" ,1 },
6767 { 4841984, "PENTAX", "Optio S" ,1 },
6768 { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i, CASIO EX-Z4 */
6769 { 10702848, "PENTAX", "Optio 750Z" ,1 },
6770 { 15980544, "AGFAPHOTO","DC-833m" ,1 },
6771 { 16098048, "SAMSUNG", "S85" ,1 },
6772 { 16215552, "SAMSUNG", "S85" ,1 },
6773 { 20487168, "SAMSUNG", "WB550" ,1 },
6774 { 24000000, "SAMSUNG", "WB550" ,1 },
6775 { 12582980, "Sinar", "" ,0 },
6776 { 33292868, "Sinar", "" ,0 },
6777 { 44390468, "Sinar", "" ,0 } };
6778
6779 static const char *l_Corporation[] =
6780 { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX",
6781 "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One",
6782 "SAMSUNG", "Mamiya", "MOTOROLA", "LEICA" };
6783
6784 // Byte order of input file.
6785 memset (m_Mask, 0, sizeof m_Mask);
6786 m_ByteOrder = get2();
6787
6788 // Length of header.
6789 l_HLen = get4();
6790
6791 /* m_BlackLevel = 0;
6792 for (int k=0; k<4; k++) m_CBlackLevel[k]=0; TODO Mike */
6793
6794 // Length of file.
6795 fseek (m_InputFile, 0, SEEK_SET);
6796 ptfread (l_Head, 1, 32, m_InputFile);
6797 fseek (m_InputFile, 0, SEEK_END);
6798 l_FLen = l_FileSize = ftell(m_InputFile);
6799
6800 #pragma GCC diagnostic push
6801 #pragma GCC diagnostic ignored "-Wwrite-strings"
6802 if ((l_CharPointer = (char *) memmem (l_Head, 32, "MMMM", 4)) ||
6803 (l_CharPointer = (char *) memmem (l_Head, 32, "IIII", 4))) {
6804 #pragma GCC diagnostic pop
6805 parse_phase_one (l_CharPointer-l_Head);
6806 if ((l_CharPointer-l_Head) && parse_tiff(0)) apply_tiff();
6807 } else if (m_ByteOrder == 0x4949 || m_ByteOrder == 0x4d4d) {
6808 if (!memcmp (l_Head+6,"HEAPCCDR",8)) {
6809 m_Data_Offset = l_HLen;
6810 parse_ciff (l_HLen, l_FLen - l_HLen);
6811 } else if (parse_tiff(0)) apply_tiff();
6812 } else if (!memcmp (l_Head,"\xff\xd8\xff\xe1",4) &&
6813 !memcmp (l_Head+6,"Exif",4)) {
6814 fseek (m_InputFile, 4, SEEK_SET);
6815 m_Data_Offset = 4 + get2();
6816 fseek (m_InputFile, m_Data_Offset, SEEK_SET);
6817 if (fgetc(m_InputFile) != 0xff)
6818 parse_tiff(12);
6819 m_ThumbOffset = 0;
6820 } else if (!memcmp (l_Head+25,"ARECOYK",7)) {
6821 strcpy (m_CameraMake, "Contax");
6822 strcpy (m_CameraModel,"N Digital");
6823 fseek (m_InputFile, 33, SEEK_SET);
6824 get_timestamp(1);
6825 fseek (m_InputFile, 60, SEEK_SET);
6826 for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], get4());
6827 } else if (!strcmp (l_Head, "PXN")) {
6828 strcpy (m_CameraMake, "Logitech");
6829 strcpy (m_CameraModel,"Fotoman Pixtura");
6830 } else if (!strcmp (l_Head, "qktk")) {
6831 strcpy (m_CameraMake, "Apple");
6832 strcpy (m_CameraModel,"QuickTake 100");
6833 m_LoadRawFunction = &CLASS quicktake_100_load_raw;
6834 } else if (!strcmp (l_Head, "qktn")) {
6835 strcpy (m_CameraMake, "Apple");
6836 strcpy (m_CameraModel,"QuickTake 150");
6837 m_LoadRawFunction = &CLASS kodak_radc_load_raw;
6838 } else if (!memcmp (l_Head,"FUJIFILM",8)) {
6839 fseek (m_InputFile, 84, SEEK_SET);
6840 m_ThumbOffset = get4();
6841 m_ThumbLength = get4();
6842 fseek (m_InputFile, 92, SEEK_SET);
6843 parse_fuji (get4());
6844 if (m_ThumbOffset > 120) {
6845 fseek (m_InputFile, 120, SEEK_SET);
6846 m_IsRaw += (i = get4());
6847 if (m_IsRaw == 2 && m_UserSetting_ShotSelect)
6848 parse_fuji (i);
6849 }
6850 m_LoadRawFunction = &CLASS unpacked_load_raw;
6851 fseek (m_InputFile, 100+28*(m_UserSetting_ShotSelect > 0), SEEK_SET);
6852 parse_tiff (m_Data_Offset = get4());
6853 parse_tiff (m_ThumbOffset+12);
6854 apply_tiff();
6855 } else if (!memcmp (l_Head,"RIFF",4)) {
6856 fseek (m_InputFile, 0, SEEK_SET);
6857 parse_riff();
6858 } else if (!memcmp (l_Head,"\0\001\0\001\0@",6)) {
6859 fseek (m_InputFile, 6, SEEK_SET);
6860 ptfread (m_CameraMake, 1, 8, m_InputFile);
6861 ptfread (m_CameraModel, 1, 8, m_InputFile);
6862 ptfread (m_CameraModelBis, 1, 16, m_InputFile);
6863 m_Data_Offset = get2();
6864 get2();
6865 m_RawWidth = get2();
6866 m_RawHeight = get2();
6867 m_LoadRawFunction = &CLASS nokia_load_raw;
6868 m_Filters = 0x61616161;
6869 } else if (!memcmp (l_Head,"NOKIARAW",8)) {
6870 strcpy (m_CameraMake, "NOKIA");
6871 strcpy (m_CameraModel, "X2");
6872 m_ByteOrder = 0x4949;
6873 fseek (m_InputFile, 300, SEEK_SET);
6874 m_Data_Offset = get4();
6875 i = get4();
6876 m_Width = get2();
6877 m_Height = get2();
6878 m_Data_Offset += i - m_Width * 5 / 4 * m_Height;
6879 m_LoadRawFunction = &CLASS nokia_load_raw;
6880 m_Filters = 0x61616161;
6881 } else if (!memcmp (l_Head,"ARRI",4)) {
6882 m_ByteOrder = 0x4949;
6883 fseek (m_InputFile, 20, SEEK_SET);
6884 m_Width = get4();
6885 m_Height = get4();
6886 strcpy (m_CameraMake, "ARRI");
6887 fseek (m_InputFile, 668, SEEK_SET);
6888 ptfread (m_CameraModel, 1, 64, m_InputFile);
6889 m_Data_Offset = 4096;
6890 m_LoadRawFunction = &CLASS packed_load_raw;
6891 m_Load_Flags = 88;
6892 m_Filters = 0x61616161;
6893 } else if (!memcmp (l_Head+4,"RED1",4)) {
6894 strcpy (m_CameraMake, "RED");
6895 strcpy (m_CameraModel,"ONE");
6896 parse_redcine();
6897 m_LoadRawFunction = &CLASS redcine_load_raw;
6898 gamma_curve (1/2.4, 12.92, 1, 4095);
6899 m_Filters = 0x49494949;
6900 } else if (!memcmp (l_Head,"DSC-Image",9))
6901 parse_rollei();
6902 else if (!memcmp (l_Head,"PWAD",4))
6903 parse_sinar_ia();
6904 else if (!memcmp (l_Head,"\0MRM",4))
6905 parse_minolta(0);
6906 else if (!memcmp (l_Head,"FOVb",4))
6907 parse_foveon();
6908 else if (!memcmp (l_Head,"CI",2))
6909 parse_cine();
6910 else {
6911 for (zero_fsize=i=0; i < sizeof l_Table / sizeof *l_Table; i++)
6912 if (l_FileSize == (unsigned) l_Table[i].fsize) {
6913 strcpy (m_CameraMake, l_Table[i].make );
6914 strcpy (m_CameraModel, l_Table[i].model);
6915 if (l_Table[i].withjpeg)
6916 parse_external_jpeg();
6917 }
6918 }
6919 if (zero_fsize) l_FileSize = 0;
6920 if (m_CameraMake[0] == 0) parse_smal (0, l_FLen);
6921 if (m_CameraMake[0] == 0) parse_jpeg (m_IsRaw = 0);
6922
6923 for (i=0; i < sizeof l_Corporation / sizeof *l_Corporation; i++)
6924 if (strstr (m_CameraMake, l_Corporation[i])) /* Simplify company names */
6925 strcpy (m_CameraMake, l_Corporation[i]);
6926 if (!strncmp (m_CameraMake,"KODAK",5) &&
6927 ((l_CharPointer = strstr(m_CameraModel," DIGITAL CAMERA")) ||
6928 (l_CharPointer = strstr(m_CameraModel," Digital Camera")) ||
6929 (l_CharPointer = strstr(m_CameraModel,"FILE VERSION"))))
6930 *l_CharPointer = 0;
6931 l_CharPointer = m_CameraMake + strlen(m_CameraMake); /* Remove trailing spaces */
6932 while (*--l_CharPointer == ' ') *l_CharPointer = 0;
6933 l_CharPointer = m_CameraModel + strlen(m_CameraModel);
6934 while (*--l_CharPointer == ' ') *l_CharPointer = 0;
6935 i = strlen(m_CameraMake); /* Remove make from model */
6936 if (!strncasecmp (m_CameraModel, m_CameraMake, i) && m_CameraModel[i++] == ' ')
6937 memmove (m_CameraModel, m_CameraModel+i, 64-i);
6938 if (!strncmp (m_CameraModel,"FinePix ",8))
6939 strcpy (m_CameraModel, m_CameraModel+8);
6940 if (!strncmp (m_CameraModel,"Digital Camera ",15))
6941 strcpy (m_CameraModel, m_CameraModel+15);
6942
6943 m_Description[511] = m_Artist[63] = m_CameraMake[63] = m_CameraModel[63] = m_CameraModelBis[63] = 0;
6944
6945 if (!m_IsRaw) goto notraw;
6946
6947 if (!m_Height) m_Height = m_RawHeight;
6948 if (!m_Width) m_Width = m_RawWidth;
6949 if (m_Height == 2624 && m_Width == 3936) /* Pentax K10D and Samsung GX10 */
6950 { m_Height = 2616; m_Width = 3896; }
6951 if (m_Height == 3136 && m_Width == 4864) /* Pentax K20D and Samsung GX20 */
6952 { m_Height = 3124; m_Width = 4688; m_Filters = 0x16161616; }
6953 if (m_Width == 4352 && (!strcmp(m_CameraModel,"K-r") || !strcmp(m_CameraModel,"K-x")))
6954 { m_Width = 4309; m_Filters = 0x16161616; }
6955 if (m_Width >= 4960 && !strncmp(m_CameraModel,"K-5",3))
6956 { m_LeftMargin = 10; m_Width = 4950; m_Filters = 0x16161616; }
6957 if (m_Width == 4736 && !strcmp(m_CameraModel,"K-7"))
6958 { m_Height = 3122; m_Width = 4684; m_Filters = 0x16161616; m_TopMargin = 2; }
6959 if (m_Width == 7424 && !strcmp(m_CameraModel,"645D"))
6960 { m_Height = 5502; m_Width = 7328; m_Filters = 0x61616161; m_TopMargin = 29;
6961 m_LeftMargin = 48; }
6962 if (m_Height == 3014 && m_Width == 4096) /* Ricoh GX200 */
6963 m_Width = 4014;
6964 if (m_DNG_Version) {
6965 if (m_Filters == UINT_MAX) m_Filters = 0;
6966 if (m_Filters) m_IsRaw = m_Tiff_Samples;
6967 else m_Colors = m_Tiff_Samples;
6968 if (m_Tiff_Compress == 1)
6969 m_LoadRawFunction = &CLASS packed_dng_load_raw;
6970 if (m_Tiff_Compress == 7)
6971 m_LoadRawFunction = &CLASS lossless_dng_load_raw;
6972 goto dng_skip;
6973 }
6974 if ((l_IsCanon = !strcmp(m_CameraMake,"Canon"))) {
6975 m_LoadRawFunction = memcmp (l_Head+6,"HEAPCCDR",8) ?
6976 &CLASS lossless_jpeg_load_raw : &CLASS canon_load_raw;
6977 }
6978 if (!strcmp(m_CameraMake,"NIKON")) {
6979 if (!m_LoadRawFunction)
6980 m_LoadRawFunction = &CLASS packed_load_raw;
6981 if (m_CameraModel[0] == 'E')
6982 m_Load_Flags |= !m_Data_Offset << 2 | 2;
6983 }
6984 if (!strcmp(m_CameraMake,"CASIO")) {
6985 m_LoadRawFunction = &CLASS packed_load_raw;
6986 m_WhiteLevel = 0xf7f;
6987 }
6988
6989 /* Set parameters based on camera name (for non-DNG files). */
6990
6991 if (m_IsFoveon) {
6992 if (m_Height*2 < m_Width) m_PixelAspect = 0.5;
6993 if (m_Height > m_Width) m_PixelAspect = 2;
6994 m_Filters = 0;
6995 simple_coeff(0);
6996 } else if (l_IsCanon && m_Tiff_bps == 15) {
6997 switch (m_Width) {
6998 case 3344: m_Width -= 66;
6999 case 3872: m_Width -= 6;
7000 }
7001 if (m_Height > m_Width) SWAP(m_Height,m_Width);
7002 m_Filters = 0;
7003 m_LoadRawFunction = &CLASS canon_sraw_load_raw;
7004 } else if (!strcmp(m_CameraModel,"PowerShot 600")) {
7005 m_Height = 613;
7006 m_Width = 854;
7007 m_RawWidth = 896;
7008 m_PixelAspect = 607/628.0;
7009 m_Colors = 4;
7010 m_Filters = 0xe1e4e1e4;
7011 m_LoadRawFunction = &CLASS canon_600_load_raw;
7012 } else if (!strcmp(m_CameraModel,"PowerShot A5") ||
7013 !strcmp(m_CameraModel,"PowerShot A5 Zoom")) {
7014 m_Height = 773;
7015 m_Width = 960;
7016 m_RawWidth = 992;
7017 m_PixelAspect = 256/235.0;
7018 m_Colors = 4;
7019 m_Filters = 0x1e4e1e4e;
7020 goto canon_a5;
7021 } else if (!strcmp(m_CameraModel,"PowerShot A50")) {
7022 m_Height = 968;
7023 m_Width = 1290;
7024 m_RawWidth = 1320;
7025 m_Colors = 4;
7026 m_Filters = 0x1b4e4b1e;
7027 goto canon_a5;
7028 } else if (!strcmp(m_CameraModel,"PowerShot Pro70")) {
7029 m_Height = 1024;
7030 m_Width = 1552;
7031 m_Colors = 4;
7032 m_Filters = 0x1e4b4e1b;
7033 goto canon_a5;
7034 } else if (!strcmp(m_CameraModel,"PowerShot SD300")) {
7035 m_Height = 1752;
7036 m_Width = 2344;
7037 m_RawHeight = 1766;
7038 m_RawWidth = 2400;
7039 m_TopMargin = 12;
7040 m_LeftMargin = 12;
7041 goto canon_a5;
7042 } else if (!strcmp(m_CameraModel,"PowerShot A460")) {
7043 m_Height = 1960;
7044 m_Width = 2616;
7045 m_RawHeight = 1968;
7046 m_RawWidth = 2664;
7047 m_TopMargin = 4;
7048 m_LeftMargin = 4;
7049 goto canon_a5;
7050 } else if (!strcmp(m_CameraModel,"PowerShot A530")) {
7051 m_Height = 1984;
7052 m_Width = 2620;
7053 m_RawHeight = 1992;
7054 m_RawWidth = 2672;
7055 m_TopMargin = 6;
7056 m_LeftMargin = 10;
7057 goto canon_a5;
7058 } else if (!strcmp(m_CameraModel,"PowerShot A610")) {
7059 if (canon_s2is()) strcpy (m_CameraModel+10, "S2 IS");
7060 m_Height = 1960;
7061 m_Width = 2616;
7062 m_RawHeight = 1968;
7063 m_RawWidth = 2672;
7064 m_TopMargin = 8;
7065 m_LeftMargin = 12;
7066 goto canon_a5;
7067 } else if (!strcmp(m_CameraModel,"PowerShot A620")) {
7068 m_Height = 2328;
7069 m_Width = 3112;
7070 m_RawHeight = 2340;
7071 m_RawWidth = 3152;
7072 m_TopMargin = 12;
7073 m_LeftMargin = 36;
7074 goto canon_a5;
7075 } else if (!strcmp(m_CameraModel,"PowerShot A470")) {
7076 m_Height = 2328;
7077 m_Width = 3096;
7078 m_RawHeight = 2346;
7079 m_RawWidth = 3152;
7080 m_TopMargin = 6;
7081 m_LeftMargin = 12;
7082 goto canon_a5;
7083 } else if (!strcmp(m_CameraModel,"PowerShot A720 IS")) {
7084 m_Height = 2472;
7085 m_Width = 3298;
7086 m_RawHeight = 2480;
7087 m_RawWidth = 3336;
7088 m_TopMargin = 5;
7089 m_LeftMargin = 6;
7090 goto canon_a5;
7091 } else if (!strcmp(m_CameraModel,"PowerShot A630")) {
7092 m_Height = 2472;
7093 m_Width = 3288;
7094 m_RawHeight = 2484;
7095 m_RawWidth = 3344;
7096 m_TopMargin = 6;
7097 m_LeftMargin = 12;
7098 goto canon_a5;
7099 } else if (!strcmp(m_CameraModel,"PowerShot A640")) {
7100 m_Height = 2760;
7101 m_Width = 3672;
7102 m_RawHeight = 2772;
7103 m_RawWidth = 3736;
7104 m_TopMargin = 6;
7105 m_LeftMargin = 12;
7106 goto canon_a5;
7107 } else if (!strcmp(m_CameraModel,"PowerShot A650")) {
7108 m_Height = 3024;
7109 m_Width = 4032;
7110 m_RawHeight = 3048;
7111 m_RawWidth = 4104;
7112 m_TopMargin = 12;
7113 m_LeftMargin = 48;
7114 goto canon_a5;
7115 } else if (!strcmp(m_CameraModel,"PowerShot S3 IS")) {
7116 m_Height = 2128;
7117 m_Width = 2840;
7118 m_RawHeight = 2136;
7119 m_RawWidth = 2888;
7120 m_TopMargin = 8;
7121 m_LeftMargin = 44;
7122 canon_a5:
7123 m_Tiff_bps = 10;
7124 m_LoadRawFunction = &CLASS packed_load_raw;
7125 m_Load_Flags = 40;
7126 if (m_RawWidth > 1600) m_ZeroIsBad = 1;
7127 } else if (!strcmp(m_CameraModel,"PowerShot SX110 IS")) {
7128 m_Height = 2760;
7129 m_Width = 3684;
7130 m_RawHeight = 2772;
7131 m_RawWidth = 3720;
7132 m_TopMargin = 12;
7133 m_LeftMargin = 6;
7134 m_LoadRawFunction = &CLASS packed_load_raw;
7135 m_Load_Flags = 40;
7136 m_ZeroIsBad = 1;
7137 } else if (!strcmp(m_CameraModel,"PowerShot SX120 IS")) {
7138 m_Height = 2742;
7139 m_Width = 3664;
7140 m_RawHeight = 2778;
7141 m_RawWidth = 3728;
7142 m_TopMargin = 18;
7143 m_LeftMargin = 16;
7144 m_Filters = 0x49494949;
7145 m_LoadRawFunction = &CLASS packed_load_raw;
7146 m_Load_Flags = 40;
7147 m_ZeroIsBad = 1;
7148 } else if (!strcmp(m_CameraModel,"PowerShot SX20 IS")) {
7149 m_Height = 3024;
7150 m_Width = 4032;
7151 m_RawHeight = 3048;
7152 m_RawWidth = 4080;
7153 m_TopMargin = 12;
7154 m_LeftMargin = 24;
7155 m_LoadRawFunction = &CLASS packed_load_raw;
7156 m_Load_Flags = 40;
7157 m_ZeroIsBad = 1;
7158 } else if (!strcmp(m_CameraModel,"PowerShot SX220 HS")) {
7159 m_Height = 3043;
7160 m_Width = 4072;
7161 m_RawHeight = 3060;
7162 m_RawWidth = 4168;
7163 m_Mask[0][0] = m_TopMargin = 16;
7164 m_Mask[0][2] = m_TopMargin + m_Height;
7165 m_Mask[0][3] = m_LeftMargin = 92;
7166 m_LoadRawFunction = &CLASS packed_load_raw;
7167 m_Load_Flags = 8;
7168 m_ZeroIsBad = 1;
7169 } else if (!strcmp(m_CameraModel,"PowerShot SX30 IS")) {
7170 m_Height = 3254;
7171 m_Width = 4366;
7172 m_RawHeight = 3276;
7173 m_RawWidth = 4464;
7174 m_TopMargin = 10;
7175 m_LeftMargin = 25;
7176 m_Filters = 0x16161616;
7177 m_LoadRawFunction = &CLASS packed_load_raw;
7178 m_Load_Flags = 40;
7179 m_ZeroIsBad = 1;
7180 } else if (!strcmp(m_CameraModel,"PowerShot Pro90 IS")) {
7181 m_Width = 1896;
7182 m_Colors = 4;
7183 m_Filters = 0xb4b4b4b4;
7184 } else if (l_IsCanon && m_RawWidth == 2144) {
7185 m_Height = 1550;
7186 m_Width = 2088;
7187 m_TopMargin = 8;
7188 m_LeftMargin = 4;
7189 if (!strcmp(m_CameraModel,"PowerShot G1")) {
7190 m_Colors = 4;
7191 m_Filters = 0xb4b4b4b4;
7192 }
7193 } else if (l_IsCanon && m_RawWidth == 2224) {
7194 m_Height = 1448;
7195 m_Width = 2176;
7196 m_TopMargin = 6;
7197 m_LeftMargin = 48;
7198 } else if (l_IsCanon && m_RawWidth == 2376) {
7199 m_Height = 1720;
7200 m_Width = 2312;
7201 m_TopMargin = 6;
7202 m_LeftMargin = 12;
7203 } else if (l_IsCanon && m_RawWidth == 2672) {
7204 m_Height = 1960;
7205 m_Width = 2616;
7206 m_TopMargin = 6;
7207 m_LeftMargin = 12;
7208 } else if (l_IsCanon && m_RawWidth == 3152) {
7209 m_Height = 2056;
7210 m_Width = 3088;
7211 m_TopMargin = 12;
7212 m_LeftMargin = 64;
7213 if (unique_id == 0x80000170)
7214 adobe_coeff ("Canon","EOS 300D");
7215 } else if (l_IsCanon && m_RawWidth == 3160) {
7216 m_Height = 2328;
7217 m_Width = 3112;
7218 m_TopMargin = 12;
7219 m_LeftMargin = 44;
7220 } else if (l_IsCanon && m_RawWidth == 3344) {
7221 m_Height = 2472;
7222 m_Width = 3288;
7223 m_TopMargin = 6;
7224 m_LeftMargin = 4;
7225 } else if (!strcmp(m_CameraModel,"EOS D2000C")) {
7226 m_Filters = 0x61616161;
7227 m_BlackLevel = m_Curve[200];
7228 } else if (l_IsCanon && m_RawWidth == 3516) {
7229 m_TopMargin = 14;
7230 m_LeftMargin = 42;
7231 if (unique_id == 0x80000189)
7232 adobe_coeff ("Canon","EOS 350D");
7233 goto canon_cr2;
7234 } else if (l_IsCanon && m_RawWidth == 3596) {
7235 m_TopMargin = 12;
7236 m_LeftMargin = 74;
7237 goto canon_cr2;
7238 } else if (l_IsCanon && m_RawWidth == 3744) {
7239 m_Height = 2760;
7240 m_Width = 3684;
7241 m_TopMargin = 16;
7242 m_LeftMargin = 8;
7243 if (unique_id > 0x2720000) {
7244 m_TopMargin = 12;
7245 m_LeftMargin = 52;
7246 }
7247 } else if (l_IsCanon && m_RawWidth == 3944) {
7248 m_Height = 2602;
7249 m_Width = 3908;
7250 m_TopMargin = 18;
7251 m_LeftMargin = 30;
7252 } else if (l_IsCanon && m_RawWidth == 3948) {
7253 m_TopMargin = 18;
7254 m_LeftMargin = 42;
7255 m_Height -= 2;
7256 if (unique_id == 0x80000236)
7257 adobe_coeff ("Canon","EOS 400D");
7258 if (unique_id == 0x80000254)
7259 adobe_coeff ("Canon","EOS 1000D");
7260 goto canon_cr2;
7261 } else if (l_IsCanon && m_RawWidth == 3984) {
7262 m_TopMargin = 20;
7263 m_LeftMargin = 76;
7264 m_Height -= 2;
7265 goto canon_cr2;
7266 } else if (l_IsCanon && m_RawWidth == 4104) {
7267 m_Height = 3024;
7268 m_Width = 4032;
7269 m_TopMargin = 12;
7270 m_LeftMargin = 48;
7271 } else if (l_IsCanon && m_RawWidth == 4152) {
7272 m_TopMargin = 12;
7273 m_LeftMargin = 192;
7274 goto canon_cr2;
7275 } else if (l_IsCanon && m_RawWidth == 4160) {
7276 m_Height = 3048;
7277 m_Width = 4048;
7278 m_TopMargin = 11;
7279 m_LeftMargin = 104;
7280 } else if (l_IsCanon && m_RawWidth == 4176) {
7281 m_Height = 3045;
7282 m_Width = 4072;
7283 m_LeftMargin = 96;
7284 m_Mask[0][0] = m_TopMargin = 17;
7285 m_Mask[0][2] = m_RawHeight;
7286 m_Mask[0][3] = 80;
7287 m_Filters = 0x49494949;
7288 } else if (l_IsCanon && m_RawWidth == 4312) {
7289 m_TopMargin = 18;
7290 m_LeftMargin = 22;
7291 m_Height -= 2;
7292 if (unique_id == 0x80000176)
7293 adobe_coeff ("Canon","EOS 450D");
7294 goto canon_cr2;
7295 } else if (l_IsCanon && m_RawWidth == 4352) {
7296 m_TopMargin = 18;
7297 m_LeftMargin = 62;
7298 if (unique_id == 0x80000288)
7299 adobe_coeff ("Canon","EOS 1100D");
7300 goto canon_cr2;
7301 } else if (l_IsCanon && m_RawWidth == 4476) {
7302 m_TopMargin = 34;
7303 m_LeftMargin = 90;
7304 goto canon_cr2;
7305 } else if (l_IsCanon && m_RawWidth == 4480) {
7306 m_Height = 3326;
7307 m_Width = 4432;
7308 m_TopMargin = 10;
7309 m_LeftMargin = 12;
7310 m_Filters = 0x49494949;
7311 } else if (l_IsCanon && m_RawWidth == 4496) {
7312 m_Height = 3316;
7313 m_Width = 4404;
7314 m_TopMargin = 50;
7315 m_LeftMargin = 80;
7316 } else if (l_IsCanon && m_RawWidth == 4832) {
7317 m_TopMargin = unique_id == 0x80000261 ? 51:26;
7318 m_LeftMargin = 62;
7319 if (unique_id == 0x80000252)
7320 adobe_coeff ("Canon","EOS 500D");
7321 goto canon_cr2;
7322 } else if (l_IsCanon && m_RawWidth == 5108) {
7323 m_TopMargin = 13;
7324 m_LeftMargin = 98;
7325 goto canon_cr2;
7326 } else if (l_IsCanon && m_RawWidth == 5120) {
7327 m_Height -= m_TopMargin = 45;
7328 m_LeftMargin = 142;
7329 m_Width = 4916;
7330 } else if (l_IsCanon && m_RawWidth == 5280) {
7331 m_TopMargin = 52;
7332 m_LeftMargin = 72;
7333 if (unique_id == 0x80000301)
7334 adobe_coeff ("Canon","EOS 650D");
7335 goto canon_cr2;
7336 } else if (l_IsCanon && m_RawWidth == 5344) {
7337 m_TopMargin = 51;
7338 m_LeftMargin = 142;
7339 if (unique_id == 0x80000269) {
7340 m_TopMargin = 100;
7341 m_LeftMargin = 126;
7342 m_Height -= 2;
7343 adobe_coeff ("Canon","EOS-1D X");
7344 }
7345 if (unique_id == 0x80000270)
7346 adobe_coeff ("Canon","EOS 550D");
7347 if (unique_id == 0x80000286)
7348 adobe_coeff ("Canon","EOS 600D");
7349 goto canon_cr2;
7350 } else if (l_IsCanon && m_RawWidth == 5360) {
7351 m_TopMargin = 51;
7352 m_LeftMargin = 158;
7353 goto canon_cr2;
7354 } else if (l_IsCanon && m_RawWidth == 5568) {
7355 m_TopMargin = 38;
7356 m_LeftMargin = 72;
7357 goto canon_cr2;
7358 } else if (l_IsCanon && m_RawWidth == 5712) {
7359 m_Height = 3752;
7360 m_Width = 5640;
7361 m_TopMargin = 20;
7362 m_LeftMargin = 62;
7363 } else if (l_IsCanon && m_RawWidth == 5792) {
7364 m_TopMargin = 51;
7365 m_LeftMargin = 158;
7366 canon_cr2:
7367 m_Height -= m_TopMargin;
7368 m_Width -= m_LeftMargin;
7369 } else if (l_IsCanon && m_RawWidth == 5920) {
7370 m_Height = 3870;
7371 m_Width = 5796;
7372 m_TopMargin = 80;
7373 m_LeftMargin = 122;
7374 } else if (!strcmp(m_CameraModel,"D1")) {
7375 ASSIGN(m_CameraMultipliers[0],VALUE(m_CameraMultipliers[0]) * 256/527.0);
7376 ASSIGN(m_CameraMultipliers[2],VALUE(m_CameraMultipliers[2]) * 256/317.0);
7377 } else if (!strcmp(m_CameraModel,"D1X")) {
7378 m_Width -= 4;
7379 m_PixelAspect = 0.5;
7380 } else if (!strcmp(m_CameraModel,"D40X") ||
7381 !strcmp(m_CameraModel,"D60") ||
7382 !strcmp(m_CameraModel,"D80") ||
7383 !strcmp(m_CameraModel,"D3000")) {
7384 m_Height -= 3;
7385 m_Width -= 4;
7386 } else if (!strcmp(m_CameraModel,"D3") ||
7387 !strcmp(m_CameraModel,"D3S") ||
7388 !strcmp(m_CameraModel,"D700")) {
7389 m_Width -= 4;
7390 m_LeftMargin = 2;
7391 } else if (!strcmp(m_CameraModel,"D3100")) {
7392 m_Width -= 28;
7393 m_LeftMargin = 6;
7394 } else if (!strcmp(m_CameraModel,"D5000") ||
7395 !strcmp(m_CameraModel,"D90")) {
7396 m_Width -= 42;
7397 } else if (!strcmp(m_CameraModel,"D5100") ||
7398 !strcmp(m_CameraModel,"D7000")) {
7399 m_Width -= 44;
7400 } else if (!strcmp(m_CameraModel,"D3200") ||
7401 !strcmp(m_CameraModel,"D600") ||
7402 !strcmp(m_CameraModel,"D800")) {
7403 m_Width -= 46;
7404 } else if (!strcmp(m_CameraModel,"D4")) {
7405 m_Width -= 52;
7406 m_LeftMargin = 2;
7407 } else if (!strncmp(m_CameraModel,"D40",3) ||
7408 !strncmp(m_CameraModel,"D50",3) ||
7409 !strncmp(m_CameraModel,"D70",3)) {
7410 m_Width--;
7411 } else if (!strcmp(m_CameraModel,"D100")) {
7412 if (m_Load_Flags)
7413 m_RawWidth = (m_Width += 3) + 3;
7414 } else if (!strcmp(m_CameraModel,"D200")) {
7415 m_LeftMargin = 1;
7416 m_Width -= 4;
7417 m_Filters = 0x94949494;
7418 } else if (!strncmp(m_CameraModel,"D2H",3)) {
7419 m_LeftMargin = 6;
7420 m_Width -= 14;
7421 } else if (!strncmp(m_CameraModel,"D2X",3)) {
7422 if (m_Width == 3264) m_Width -= 32;
7423 else m_Width -= 8;
7424 } else if (!strncmp(m_CameraModel,"D300",4)) {
7425 m_Width -= 32;
7426 } else if (!strcmp(m_CameraMake,"NIKON") && m_RawWidth == 4032) {
7427 adobe_coeff ("NIKON","COOLPIX P7700");
7428 } else if (!strncmp(m_CameraModel,"COOLPIX P",9)) {
7429 m_Load_Flags = 24;
7430 m_Filters = 0x94949494;
7431 if (m_CameraModel[9] == '7' && m_IsoSpeed >= 400)
7432 m_BlackLevel = 255;
7433 } else if (!strncmp(m_CameraModel,"1 ",2)) {
7434 m_Height -= 2;
7435 } else if (l_FileSize == 1581060) {
7436 m_Height = 963;
7437 m_Width = 1287;
7438 m_RawWidth = 1632;
7439 m_WhiteLevel = 0x3f4;
7440 m_Colors = 4;
7441 m_Filters = 0x1e1e1e1e;
7442 simple_coeff(3);
7443 ASSIGN(m_D65Multipliers[0], 1.2085);
7444 ASSIGN(m_D65Multipliers[1], 1.0943);
7445 ASSIGN(m_D65Multipliers[3], 1.1103);
7446 goto e900;
7447 } else if (l_FileSize == 2465792) {
7448 m_Height = 1203;
7449 m_Width = 1616;
7450 m_RawWidth = 2048;
7451 m_Colors = 4;
7452 m_Filters = 0x4b4b4b4b;
7453 adobe_coeff ("NIKON","E950");
7454 e900:
7455 m_Tiff_bps = 10;
7456 m_LoadRawFunction = &CLASS packed_load_raw;
7457 m_Load_Flags = 6;
7458 } else if (l_FileSize == 4771840) {
7459 m_Height = 1540;
7460 m_Width = 2064;
7461 m_Colors = 4;
7462 m_Filters = 0xe1e1e1e1;
7463 m_LoadRawFunction = &CLASS packed_load_raw;
7464 m_Load_Flags = 6;
7465 if (!m_TimeStamp && nikon_e995())
7466 strcpy (m_CameraModel, "E995");
7467 if (strcmp(m_CameraModel,"E995")) {
7468 m_Filters = 0xb4b4b4b4;
7469 simple_coeff(3);
7470 ASSIGN(m_D65Multipliers[0], 1.196);
7471 ASSIGN(m_D65Multipliers[1], 1.246);
7472 ASSIGN(m_D65Multipliers[2], 1.018);
7473 }
7474 } else if (!strcmp(m_CameraModel,"E2100")) {
7475 if (!m_TimeStamp && !nikon_e2100()) goto cp_e2500;
7476 m_Height = 1206;
7477 m_Width = 1616;
7478 m_Load_Flags = 30;
7479 } else if (!strcmp(m_CameraModel,"E2500")) {
7480 cp_e2500:
7481 strcpy (m_CameraModel, "E2500");
7482 m_Height = 1204;
7483 m_Width = 1616;
7484 m_Colors = 4;
7485 m_Filters = 0x4b4b4b4b;
7486 } else if (l_FileSize == 4775936) {
7487 m_Height = 1542;
7488 m_Width = 2064;
7489 m_LoadRawFunction = &CLASS packed_load_raw;
7490 m_Load_Flags = 30;
7491 if (!m_TimeStamp) nikon_3700();
7492 if (m_CameraModel[0] == 'E' && atoi(m_CameraModel+1) < 3700)
7493 m_Filters = 0x49494949;
7494 if (!strcmp(m_CameraModel,"Optio 33WR")) {
7495 m_Flip = 1;
7496 m_Filters = 0x16161616;
7497 }
7498 if (m_CameraMake[0] == 'O') {
7499 int li = find_green (12, 32, 1188864, 3576832);
7500 int lc = find_green (12, 32, 2383920, 2387016);
7501 if (abs(li) < abs(lc)) {
7502 SWAP(li,lc);
7503 m_Load_Flags = 24;
7504 }
7505 if (li < 0) m_Filters = 0x61616161;
7506 }
7507 } else if (l_FileSize == 5869568) {
7508 m_Height = 1710;
7509 m_Width = 2288;
7510 m_Filters = 0x16161616;
7511 if (!m_TimeStamp && minolta_z2()) {
7512 strcpy (m_CameraMake, "Minolta");
7513 strcpy (m_CameraModel,"DiMAGE Z2");
7514 }
7515 m_LoadRawFunction = &CLASS packed_load_raw;
7516 m_Load_Flags = 6 + 24 * (m_CameraMake[0] == 'M');
7517 } else if (!strcmp(m_CameraModel,"E4500")) {
7518 m_Height = 1708;
7519 m_Width = 2288;
7520 m_Colors = 4;
7521 m_Filters = 0xb4b4b4b4;
7522 } else if (l_FileSize == 7438336) {
7523 m_Height = 1924;
7524 m_Width = 2576;
7525 m_Colors = 4;
7526 m_Filters = 0xb4b4b4b4;
7527 } else if (l_FileSize == 8998912) {
7528 m_Height = 2118;
7529 m_Width = 2832;
7530 m_WhiteLevel = 0xf83;
7531 m_LoadRawFunction = &CLASS packed_load_raw;
7532 m_Load_Flags = 30;
7533 } else if (!strcmp(m_CameraMake,"FUJIFILM")) {
7534 if (!strcmp(m_CameraModel+7,"S2Pro")) {
7535 strcpy (m_CameraModel,"S2Pro");
7536 m_Height = 2144;
7537 m_Width = 2880;
7538 m_Flip = 6;
7539 } else if (m_LoadRawFunction != &CLASS packed_load_raw)
7540 m_WhiteLevel = (m_IsRaw == 2 && m_UserSetting_ShotSelect) ? 0x2f00 : 0x3e00;
7541 m_TopMargin = (m_RawHeight - m_Height) >> 2 << 1;
7542 m_LeftMargin = (m_RawWidth - m_Width ) >> 2 << 1;
7543 if (m_Width == 2848) m_Filters = 0x16161616;
7544 if (m_Width == 3328) {
7545 m_Width = 3262;
7546 m_LeftMargin = 34;
7547 }
7548 if (m_Width == 4952) {
7549 m_LeftMargin = 0;
7550 m_Filters = 2;
7551 }
7552 if (fuji_layout) m_RawWidth *= m_IsRaw;
7553 } else if (!strcmp(m_CameraModel,"RD175")) {
7554 m_Height = 986;
7555 m_Width = 1534;
7556 m_Data_Offset = 513;
7557 m_Filters = 0x61616161;
7558 m_LoadRawFunction = &CLASS minolta_rd175_load_raw;
7559 } else if (!strcmp(m_CameraModel,"KD-400Z")) {
7560 m_Height = 1712;
7561 m_Width = 2312;
7562 m_RawWidth = 2336;
7563 goto konica_400z;
7564 } else if (!strcmp(m_CameraModel,"KD-510Z")) {
7565 goto konica_510z;
7566 } else if (!strcasecmp(m_CameraMake,"MINOLTA")) {
7567 m_LoadRawFunction = &CLASS unpacked_load_raw;
7568 m_WhiteLevel = 0xfff;
7569 if (!strncmp(m_CameraModel,"DiMAGE A",8)) {
7570 if (!strcmp(m_CameraModel,"DiMAGE A200"))
7571 m_Filters = 0x49494949;
7572 m_Tiff_bps = 12;
7573 m_LoadRawFunction = &CLASS packed_load_raw;
7574 } else if (!strncmp(m_CameraModel,"ALPHA",5) ||
7575 !strncmp(m_CameraModel,"DYNAX",5) ||
7576 !strncmp(m_CameraModel,"MAXXUM",6)) {
7577 sprintf (m_CameraModel+20, "DYNAX %-10s", m_CameraModel+6+(m_CameraModel[0]=='M'));
7578 adobe_coeff (m_CameraMake, m_CameraModel+20);
7579 m_LoadRawFunction = &CLASS packed_load_raw;
7580 } else if (!strncmp(m_CameraModel,"DiMAGE G",8)) {
7581 if (m_CameraModel[8] == '4') {
7582 m_Height = 1716;
7583 m_Width = 2304;
7584 } else if (m_CameraModel[8] == '5') {
7585 konica_510z:
7586 m_Height = 1956;
7587 m_Width = 2607;
7588 m_RawWidth = 2624;
7589 } else if (m_CameraModel[8] == '6') {
7590 m_Height = 2136;
7591 m_Width = 2848;
7592 }
7593 m_Data_Offset += 14;
7594 m_Filters = 0x61616161;
7595 konica_400z:
7596 m_LoadRawFunction = &CLASS unpacked_load_raw;
7597 m_WhiteLevel = 0x3df;
7598 m_ByteOrder = 0x4d4d;
7599 }
7600 } else if (!strcmp(m_CameraModel,"*ist D")) {
7601 m_LoadRawFunction = &CLASS unpacked_load_raw;
7602 data_error = -1;
7603 } else if (!strcmp(m_CameraModel,"*ist DS")) {
7604 m_Height -= 2;
7605 } else if (!strcmp(m_CameraModel,"K-x")) {
7606 m_Width = 4309;
7607 m_Filters = 0x16161616;
7608 } else if (!strcmp(m_CameraModel,"Optio S")) {
7609 if (l_FileSize == 3178560) {
7610 m_Height = 1540;
7611 m_Width = 2064;
7612 m_LoadRawFunction = &CLASS eight_bit_load_raw;
7613 ASSIGN(m_CameraMultipliers[0],VALUE(m_CameraMultipliers[0]) * 4);
7614 ASSIGN(m_CameraMultipliers[2],VALUE(m_CameraMultipliers[2]) * 4);
7615 } else {
7616 m_Height = 1544;
7617 m_Width = 2068;
7618 m_RawWidth = 3136;
7619 m_LoadRawFunction = &CLASS packed_load_raw;
7620 m_WhiteLevel = 0xf7c;
7621 }
7622 } else if (l_FileSize == 6114240) {
7623 m_Height = 1737;
7624 m_Width = 2324;
7625 m_RawWidth = 3520;
7626 m_LoadRawFunction = &CLASS packed_load_raw;
7627 m_WhiteLevel = 0xf7a;
7628 } else if (!strcmp(m_CameraModel,"Optio 750Z")) {
7629 m_Height = 2302;
7630 m_Width = 3072;
7631 m_LoadRawFunction = &CLASS packed_load_raw;
7632 m_Load_Flags = 30;
7633 } else if (!strcmp(m_CameraModel,"DC-833m")) {
7634 m_Height = 2448;
7635 m_Width = 3264;
7636 m_ByteOrder = 0x4949;
7637 m_Filters = 0x61616161;
7638 m_LoadRawFunction = &CLASS unpacked_load_raw;
7639 m_WhiteLevel = 0xfc00;
7640 } else if (!strncmp(m_CameraModel,"S85",3)) {
7641 m_Height = 2448;
7642 m_Width = 3264;
7643 m_RawWidth = l_FileSize/m_Height/2;
7644 m_ByteOrder = 0x4d4d;
7645 m_LoadRawFunction = &CLASS unpacked_load_raw;
7646 } else if (!strcmp(m_CameraMake,"SAMSUNG") && m_RawWidth == 4704) {
7647 m_Height -= m_TopMargin = 8;
7648 m_Width -= 2 * (m_LeftMargin = 8);
7649 m_Load_Flags = 32;
7650 } else if (!strcmp(m_CameraMake,"SAMSUNG") && m_RawWidth == 5632) {
7651 m_ByteOrder = 0x4949;
7652 m_Height = 3694;
7653 m_TopMargin = 2;
7654 m_Width = 5574 - (m_LeftMargin = 32 + m_Tiff_bps);
7655 if (m_Tiff_bps == 12) m_Load_Flags = 80;
7656 } else if (!strcmp(m_CameraModel,"EX1")) {
7657 m_ByteOrder = 0x4949;
7658 m_Height -= 20;
7659 m_TopMargin = 2;
7660 if ((m_Width -= 6) > 3682) {
7661 m_Height -= 10;
7662 m_Width -= 46;
7663 m_TopMargin = 8;
7664 }
7665 } else if (!strcmp(m_CameraModel,"WB2000")) {
7666 m_ByteOrder = 0x4949;
7667 m_Height -= 3;
7668 m_TopMargin = 2;
7669 if ((m_Width -= 10) > 3718) {
7670 m_Height -= 28;
7671 m_Width -= 56;
7672 m_TopMargin = 8;
7673 }
7674 } else if (l_FileSize == 20487168) {
7675 m_Height = 2808;
7676 m_Width = 3648;
7677 goto wb550;
7678 } else if (l_FileSize == 24000000) {
7679 m_Height = 3000;
7680 m_Width = 4000;
7681 wb550:
7682 strcpy (m_CameraModel, "WB550");
7683 m_ByteOrder = 0x4d4d;
7684 m_LoadRawFunction = &CLASS unpacked_load_raw;
7685 m_Load_Flags = 6;
7686 m_WhiteLevel = 0x3df;
7687 } else if (!strcmp(m_CameraModel,"EX2F")) {
7688 m_Height = 3045;
7689 m_Width = 4070;
7690 m_TopMargin = 3;
7691 m_ByteOrder = 0x4949;
7692 m_Filters = 0x49494949;
7693 m_LoadRawFunction = &CLASS unpacked_load_raw;
7694 } else if (!strcmp(m_CameraModel,"STV680 VGA")) {
7695 m_Height = 484;
7696 m_Width = 644;
7697 m_LoadRawFunction = &CLASS eight_bit_load_raw;
7698 m_Flip = 2;
7699 m_Filters = 0x16161616;
7700 m_BlackLevel = 16;
7701 } else if (!strcmp(m_CameraModel,"N95")) {
7702 m_TopMargin = 2;
7703 m_Height = m_RawHeight - m_TopMargin;
7704 } else if (!strcmp(m_CameraModel,"531C")) {
7705 m_Height = 1200;
7706 m_Width = 1600;
7707 m_LoadRawFunction = &CLASS unpacked_load_raw;
7708 m_Filters = 0x49494949;
7709 } else if (!strcmp(m_CameraModel,"640x480")) {
7710 m_Height = 480;
7711 m_Width = 640;
7712 m_LoadRawFunction = &CLASS eight_bit_load_raw;
7713 gamma_curve (0.45, 4.5, 1, 255);
7714 } else if (!strcmp(m_CameraModel,"F-080C")) {
7715 m_Height = 768;
7716 m_Width = 1024;
7717 m_LoadRawFunction = &CLASS eight_bit_load_raw;
7718 } else if (!strcmp(m_CameraModel,"F-145C")) {
7719 m_Height = 1040;
7720 m_Width = 1392;
7721 m_LoadRawFunction = &CLASS eight_bit_load_raw;
7722 } else if (!strcmp(m_CameraModel,"F-201C")) {
7723 m_Height = 1200;
7724 m_Width = 1600;
7725 m_LoadRawFunction = &CLASS eight_bit_load_raw;
7726 } else if (!strcmp(m_CameraModel,"F-510C")) {
7727 m_Height = 1958;
7728 m_Width = 2588;
7729 m_LoadRawFunction = l_FileSize < 7500000 ?
7730 &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
7731 m_Data_Offset = l_FileSize - m_Width*m_Height*(l_FileSize >> 22);
7732 m_WhiteLevel = 0xfff0;
7733 } else if (!strcmp(m_CameraModel,"F-810C")) {
7734 m_Height = 2469;
7735 m_Width = 3272;
7736 m_LoadRawFunction = &CLASS unpacked_load_raw;
7737 m_WhiteLevel = 0xfff0;
7738 } else if (!strcmp(m_CameraModel,"XCD-SX910CR")) {
7739 m_Height = 1024;
7740 m_Width = 1375;
7741 m_RawWidth = 1376;
7742 m_Filters = 0x49494949;
7743 m_WhiteLevel = 0x3ff;
7744 m_LoadRawFunction = l_FileSize < 2000000 ?
7745 &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
7746 } else if (!strcmp(m_CameraModel,"2010")) {
7747 m_Height = 1207;
7748 m_Width = 1608;
7749 m_ByteOrder = 0x4949;
7750 m_Filters = 0x16161616;
7751 m_Data_Offset = 3212;
7752 m_WhiteLevel = 0x3ff;
7753 m_LoadRawFunction = &CLASS unpacked_load_raw;
7754 } else if (!strcmp(m_CameraModel,"A782")) {
7755 m_Height = 3000;
7756 m_Width = 2208;
7757 m_Filters = 0x61616161;
7758 m_LoadRawFunction = l_FileSize < 10000000 ?
7759 &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
7760 m_WhiteLevel = 0xffc0;
7761 } else if (!strcmp(m_CameraModel,"3320AF")) {
7762 m_Height = 1536;
7763 m_RawWidth = m_Width = 2048;
7764 m_Filters = 0x61616161;
7765 m_LoadRawFunction = &CLASS unpacked_load_raw;
7766 m_WhiteLevel = 0x3ff;
7767 fseek (m_InputFile, 0x300000, SEEK_SET);
7768 if ((m_ByteOrder = guess_byte_order(0x10000)) == 0x4d4d) {
7769 m_Height -= (m_TopMargin = 16);
7770 m_Width -= (m_LeftMargin = 28);
7771 m_WhiteLevel = 0xf5c0;
7772 strcpy (m_CameraMake, "ISG");
7773 m_CameraModel[0] = 0;
7774 }
7775 } else if (!strcmp(m_CameraMake,"Hasselblad")) {
7776 if (m_LoadRawFunction == &CLASS lossless_jpeg_load_raw)
7777 m_LoadRawFunction = &CLASS hasselblad_load_raw;
7778 if (m_RawWidth == 7262) {
7779 m_Height = 5444;
7780 m_Width = 7248;
7781 m_TopMargin = 4;
7782 m_LeftMargin = 7;
7783 m_Filters = 0x61616161;
7784 } else if (m_RawWidth == 7410) {
7785 m_Height = 5502;
7786 m_Width = 7328;
7787 m_TopMargin = 4;
7788 m_LeftMargin = 41;
7789 m_Filters = 0x61616161;
7790 } else if (m_RawWidth == 9044) {
7791 m_Height = 6716;
7792 m_Width = 8964;
7793 m_TopMargin = 8;
7794 m_LeftMargin = 40;
7795 m_BlackLevel += m_Load_Flags = 256;
7796 m_WhiteLevel = 0x8101;
7797 } else if (m_RawWidth == 4090) {
7798 strcpy (m_CameraModel, "V96C");
7799 m_Height -= (m_TopMargin = 6);
7800 m_Width -= (m_LeftMargin = 3) + 7;
7801 m_Filters = 0x61616161;
7802 }
7803 } else if (!strcmp(m_CameraMake,"Sinar")) {
7804 if (!memcmp(l_Head,"8BPS",4)) {
7805 fseek (m_InputFile, 14, SEEK_SET);
7806 m_Height = get4();
7807 m_Width = get4();
7808 m_Filters = 0x61616161;
7809 m_Data_Offset = 68;
7810 }
7811 if (!m_LoadRawFunction) m_LoadRawFunction = &CLASS unpacked_load_raw;
7812 m_WhiteLevel = 0x3fff;
7813 } else if (!strcmp(m_CameraMake,"Leaf")) {
7814 m_WhiteLevel = 0x3fff;
7815 fseek (m_InputFile, m_Data_Offset, SEEK_SET);
7816 if (ljpeg_start (&l_JHead, 1) && l_JHead.bits == 15)
7817 m_WhiteLevel = 0x1fff;
7818 if (m_Tiff_Samples > 1) m_Filters = 0;
7819 if (m_Tiff_Samples > 1 || m_TileLength < m_RawHeight) {
7820 m_LoadRawFunction = &CLASS leaf_hdr_load_raw;
7821 m_RawWidth = m_TileWidth;
7822 }
7823 if ((m_Width | m_Height) == 2048) {
7824 if (m_Tiff_Samples == 1) {
7825 m_Filters = 1;
7826 strcpy (m_ColorDescriptor, "RBTG");
7827 strcpy (m_CameraModel, "CatchLight");
7828 m_TopMargin = 8; m_LeftMargin = 18; m_Height = 2032; m_Width = 2016;
7829 } else {
7830 strcpy (m_CameraModel, "DCB2");
7831 m_TopMargin = 10; m_LeftMargin = 16; m_Height = 2028; m_Width = 2022;
7832 }
7833 } else if (m_Width+m_Height == 3144+2060) {
7834 if (!m_CameraModel[0]) strcpy (m_CameraModel, "Cantare");
7835 if (m_Width > m_Height) {
7836 m_TopMargin = 6; m_LeftMargin = 32; m_Height = 2048; m_Width = 3072;
7837 m_Filters = 0x61616161;
7838 } else {
7839 m_LeftMargin = 6; m_TopMargin = 32; m_Width = 2048; m_Height = 3072;
7840 m_Filters = 0x16161616;
7841 }
7842 if (!VALUE(m_CameraMultipliers[0]) || m_CameraModel[0] == 'V') m_Filters = 0;
7843 else m_IsRaw = m_Tiff_Samples;
7844 } else if (m_Width == 2116) {
7845 strcpy (m_CameraModel, "Valeo 6");
7846 m_Height -= 2 * (m_TopMargin = 30);
7847 m_Width -= 2 * (m_LeftMargin = 55);
7848 m_Filters = 0x49494949;
7849 } else if (m_Width == 3171) {
7850 strcpy (m_CameraModel, "Valeo 6");
7851 m_Height -= 2 * (m_TopMargin = 24);
7852 m_Width -= 2 * (m_LeftMargin = 24);
7853 m_Filters = 0x16161616;
7854 }
7855 } else if (!strcmp(m_CameraMake,"LEICA") || !strcmp(m_CameraMake,"Panasonic")) {
7856 if ((l_FLen-m_Data_Offset) / (m_RawWidth*8/7) == m_RawHeight)
7857 m_LoadRawFunction = &CLASS panasonic_load_raw;
7858 if (!m_LoadRawFunction) {
7859 m_LoadRawFunction = &CLASS unpacked_load_raw;
7860 m_Load_Flags = 4;
7861 }
7862 m_ZeroIsBad = 1;
7863 if ((m_Height += 12) > m_RawHeight) m_Height = m_RawHeight;
7864 for (i=0; i < sizeof pana / sizeof *pana; i++)
7865 if (m_RawWidth == pana[i][0] && m_RawHeight == pana[i][1]) {
7866 m_LeftMargin = pana[i][2];
7867 m_TopMargin = pana[i][3];
7868 m_Width += pana[i][4];
7869 m_Height += pana[i][5];
7870 }
7871 m_Filters = 0x01010101 * (unsigned char) "\x94\x61\x49\x16"
7872 [((m_Filters-1) ^ (m_LeftMargin & 1) ^ (m_TopMargin << 1)) & 3];
7873 } else if (!strcmp(m_CameraModel,"C770UZ")) {
7874 m_Height = 1718;
7875 m_Width = 2304;
7876 m_Filters = 0x16161616;
7877 m_LoadRawFunction = &CLASS packed_load_raw;
7878 m_Load_Flags = 30;
7879 } else if (!strcmp(m_CameraMake,"OLYMPUS")) {
7880 m_Height += m_Height & 1;
7881 m_Filters = exif_cfa;
7882 if (m_Width == 4100) m_Width -= 4;
7883 if (m_Width == 4080) m_Width -= 24;
7884 if (m_LoadRawFunction == &CLASS unpacked_load_raw)
7885 m_Load_Flags = 4;
7886 m_Tiff_bps = 12;
7887 if (!strcmp(m_CameraModel,"E-300") ||
7888 !strcmp(m_CameraModel,"E-500")) {
7889 m_Width -= 20;
7890 if (m_LoadRawFunction == &CLASS unpacked_load_raw) {
7891 m_WhiteLevel = 0xfc3;
7892 memset (m_CBlackLevel, 0, sizeof m_CBlackLevel);
7893 }
7894 } else if (!strcmp(m_CameraModel,"E-330")) {
7895 m_Width -= 30;
7896 if (m_LoadRawFunction == &CLASS unpacked_load_raw)
7897 m_WhiteLevel = 0xf79;
7898 } else if (!strcmp(m_CameraModel,"SP550UZ")) {
7899 m_ThumbLength = l_FLen - (m_ThumbOffset = 0xa39800);
7900 m_ThumbHeight = 480;
7901 m_ThumbWidth = 640;
7902 } else if (!strcmp(m_CameraModel,"XZ-2")) {
7903 m_LoadRawFunction = &CLASS packed_load_raw;
7904 m_Load_Flags = 24;
7905 }
7906 } else if (!strcmp(m_CameraModel,"N Digital")) {
7907 m_Height = 2047;
7908 m_Width = 3072;
7909 m_Filters = 0x61616161;
7910 m_Data_Offset = 0x1a00;
7911 m_LoadRawFunction = &CLASS packed_load_raw;
7912 } else if (!strcmp(m_CameraModel,"DSC-F828")) {
7913 m_Width = 3288;
7914 m_LeftMargin = 5;
7915 m_Mask[1][3] = -17;
7916 m_Data_Offset = 862144;
7917 m_LoadRawFunction = &CLASS sony_load_raw;
7918 m_Filters = 0x9c9c9c9c;
7919 m_Colors = 4;
7920 strcpy (m_ColorDescriptor, "RGBE");
7921 } else if (!strcmp(m_CameraModel,"DSC-V3")) {
7922 m_Width = 3109;
7923 m_LeftMargin = 59;
7924 m_Mask[0][1] = 9;
7925 m_Data_Offset = 787392;
7926 m_LoadRawFunction = &CLASS sony_load_raw;
7927 } else if (!strcmp(m_CameraMake,"SONY") && m_RawWidth == 3984) {
7928 adobe_coeff ("SONY","DSC-R1");
7929 m_Width = 3925;
7930 m_ByteOrder = 0x4d4d;
7931 } else if (!strcmp(m_CameraMake,"SONY") && m_RawWidth == 5504) {
7932 m_Width -= 8;
7933 } else if (!strcmp(m_CameraMake,"SONY") && m_RawWidth == 6048) {
7934 m_Width -= 24;
7935 } else if (!strcmp(m_CameraModel,"DSLR-A100")) {
7936 if (m_Width == 3880) {
7937 m_Height--;
7938 m_Width = ++m_RawWidth;
7939 } else {
7940 m_ByteOrder = 0x4d4d;
7941 m_Load_Flags = 2;
7942 }
7943 m_Filters = 0x61616161;
7944 } else if (!strcmp(m_CameraModel,"DSLR-A350")) {
7945 m_Height -= 4;
7946 } else if (!strcmp(m_CameraModel,"PIXL")) {
7947 m_Height -= m_TopMargin = 4;
7948 m_Width -= m_LeftMargin = 32;
7949 gamma_curve (0, 7, 1, 255);
7950 } else if (!strcmp(m_CameraModel,"C603v")) {
7951 m_Height = 480;
7952 m_Width = 640;
7953 if (l_FileSize < 614400 || find_green (16, 16, 3840, 5120) < 25) goto c603v;
7954 strcpy (m_CameraModel,"KAI-0340");
7955 m_Height -= 3;
7956 m_Data_Offset = 3840;
7957 m_ByteOrder = 0x4949;
7958 m_LoadRawFunction = &CLASS unpacked_load_raw;
7959 } else if (!strcmp(m_CameraModel,"C603y")) {
7960 m_Height = 2134;
7961 m_Width = 2848;
7962 c603v:
7963 m_Filters = 0;
7964 m_LoadRawFunction = &CLASS kodak_yrgb_load_raw;
7965 gamma_curve (0, 3.875, 1, 255);
7966 } else if (!strcmp(m_CameraModel,"C603")) {
7967 m_RawHeight = m_Height = 2152;
7968 m_RawWidth = m_Width = 2864;
7969 goto c603;
7970 } else if (!strcmp(m_CameraModel,"C330")) {
7971 m_Height = 1744;
7972 m_Width = 2336;
7973 m_RawHeight = 1779;
7974 m_RawWidth = 2338;
7975 m_TopMargin = 33;
7976 m_LeftMargin = 1;
7977 c603:
7978 m_ByteOrder = 0x4949;
7979 if ((m_Data_Offset = l_FileSize - m_RawHeight*m_RawWidth)) {
7980 fseek (m_InputFile, 168, SEEK_SET);
7981 read_shorts (m_Curve, 256);
7982 } else gamma_curve (0, 3.875, 1, 255);
7983 m_LoadRawFunction = &CLASS eight_bit_load_raw;
7984 } else if (!strncasecmp(m_CameraMake,"EasyShare",9)) {
7985 m_Data_Offset = m_Data_Offset < 0x15000 ? 0x15000 : 0x17000;
7986 m_LoadRawFunction = &CLASS packed_load_raw;
7987 } else if (!strcasecmp(m_CameraMake,"KODAK")) {
7988 if (m_Filters == UINT_MAX) m_Filters = 0x61616161;
7989 if (!strncmp(m_CameraModel,"NC2000",6)) {
7990 m_Width -= 4;
7991 m_LeftMargin = 2;
7992 } else if (!strcmp(m_CameraModel,"EOSDCS3B")) {
7993 m_Width -= 4;
7994 m_LeftMargin = 2;
7995 } else if (!strcmp(m_CameraModel,"EOSDCS1")) {
7996 m_Width -= 4;
7997 m_LeftMargin = 2;
7998 } else if (!strcmp(m_CameraModel,"DCS420")) {
7999 m_Width -= 4;
8000 m_LeftMargin = 2;
8001 } else if (!strncmp(m_CameraModel,"DCS460",7)) {
8002 m_CameraModel[6]=0;
8003 m_Width -= 4;
8004 m_LeftMargin = 2;
8005 } else if (!strcmp(m_CameraModel,"DCS460A")) {
8006 m_Width -= 4;
8007 m_LeftMargin = 2;
8008 m_Colors = 1;
8009 m_Filters = 0;
8010 } else if (!strcmp(m_CameraModel,"DCS660M")) {
8011 m_BlackLevel = 214;
8012 m_Colors = 1;
8013 m_Filters = 0;
8014 } else if (!strcmp(m_CameraModel,"DCS760M")) {
8015 m_Colors = 1;
8016 m_Filters = 0;
8017 }
8018 if (!strcmp(m_CameraModel+4,"20X"))
8019 strcpy (m_ColorDescriptor, "MYCY");
8020 if (strstr(m_CameraModel,"DC25")) {
8021 strcpy (m_CameraModel, "DC25");
8022 m_Data_Offset = 15424;
8023 }
8024 if (!strncmp(m_CameraModel,"DC2",3)) {
8025 m_RawHeight = m_Height = 242;
8026 if (l_FLen < 100000) {
8027 m_RawWidth = 256; m_Width = 249;
8028 m_PixelAspect = (4.0*m_Height) / (3.0*m_Width);
8029 } else {
8030 m_RawWidth = 512; m_Width = 501;
8031 m_PixelAspect = (493.0*m_Height) / (373.0*m_Width);
8032 }
8033 m_Data_Offset += m_RawWidth + 1;
8034 m_Colors = 4;
8035 m_Filters = 0x8d8d8d8d;
8036 simple_coeff(1);
8037 ASSIGN(m_D65Multipliers[1], 1.179);
8038 ASSIGN(m_D65Multipliers[2], 1.209);
8039 ASSIGN(m_D65Multipliers[3], 1.036);
8040 m_LoadRawFunction = &CLASS eight_bit_load_raw;
8041 } else if (!strcmp(m_CameraModel,"40")) {
8042 strcpy (m_CameraModel, "DC40");
8043 m_Height = 512;
8044 m_Width = 768;
8045 m_Data_Offset = 1152;
8046 m_LoadRawFunction = &CLASS kodak_radc_load_raw;
8047 } else if (strstr(m_CameraModel,"DC50")) {
8048 strcpy (m_CameraModel, "DC50");
8049 m_Height = 512;
8050 m_Width = 768;
8051 m_Data_Offset = 19712;
8052 m_LoadRawFunction = &CLASS kodak_radc_load_raw;
8053 } else if (strstr(m_CameraModel,"DC120")) {
8054 strcpy (m_CameraModel, "DC120");
8055 m_Height = 976;
8056 m_Width = 848;
8057 m_PixelAspect = m_Height/0.75/m_Width;
8058 m_LoadRawFunction = m_Tiff_Compress == 7 ?
8059 &CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw;
8060 } else if (!strcmp(m_CameraModel,"DCS200")) {
8061 m_ThumbHeight = 128;
8062 m_ThumbWidth = 192;
8063 m_ThumbOffset = 6144;
8064 m_ThumbMisc = 360;
8065 m_WriteThumb = &CLASS layer_thumb;
8066 m_Height = 1024;
8067 m_Width = 1536;
8068 m_Data_Offset = 79872;
8069 m_LoadRawFunction = &CLASS eight_bit_load_raw;
8070 m_BlackLevel = 17;
8071 }
8072 } else if (!strcmp(m_CameraModel,"Fotoman Pixtura")) {
8073 m_Height = 512;
8074 m_Width = 768;
8075 m_Data_Offset = 3632;
8076 m_LoadRawFunction = &CLASS kodak_radc_load_raw;
8077 m_Filters = 0x61616161;
8078 simple_coeff(2);
8079 } else if (!strncmp(m_CameraModel,"QuickTake",9)) {
8080 if (l_Head[5]) strcpy (m_CameraModel+10, "200");
8081 fseek (m_InputFile, 544, SEEK_SET);
8082 m_Height = get2();
8083 m_Width = get2();
8084 m_Data_Offset = (get4(),get2()) == 30 ? 738:736;
8085 if (m_Height > m_Width) {
8086 SWAP(m_Height,m_Width);
8087 fseek (m_InputFile, m_Data_Offset-6, SEEK_SET);
8088 m_Flip = ~get2() & 3 ? 5:6;
8089 }
8090 m_Filters = 0x61616161;
8091 } else if (!strcmp(m_CameraMake,"Rollei") && !m_LoadRawFunction) {
8092 switch (m_RawWidth) {
8093 case 1316:
8094 m_Height = 1030;
8095 m_Width = 1300;
8096 m_TopMargin = 1;
8097 m_LeftMargin = 6;
8098 break;
8099 case 2568:
8100 m_Height = 1960;
8101 m_Width = 2560;
8102 m_TopMargin = 2;
8103 m_LeftMargin = 8;
8104 }
8105 m_Filters = 0x16161616;
8106 m_LoadRawFunction = &CLASS rollei_load_raw;
8107 } else if (!strcmp(m_CameraModel,"PC-CAM 600")) {
8108 m_Height = 768;
8109 m_Data_Offset = m_Width = 1024;
8110 m_Filters = 0x49494949;
8111 m_LoadRawFunction = &CLASS eight_bit_load_raw;
8112 } else if (!strcmp(m_CameraModel,"QV-2000UX")) {
8113 m_Height = 1208;
8114 m_Width = 1632;
8115 m_Data_Offset = m_Width * 2;
8116 m_LoadRawFunction = &CLASS eight_bit_load_raw;
8117 } else if (l_FileSize == 3217760) {
8118 m_Height = 1546;
8119 m_Width = 2070;
8120 m_RawWidth = 2080;
8121 m_LoadRawFunction = &CLASS eight_bit_load_raw;
8122 } else if (!strcmp(m_CameraModel,"QV-4000")) {
8123 m_Height = 1700;
8124 m_Width = 2260;
8125 m_LoadRawFunction = &CLASS unpacked_load_raw;
8126 m_WhiteLevel = 0xffff;
8127 } else if (!strcmp(m_CameraModel,"QV-5700")) {
8128 m_Height = 1924;
8129 m_Width = 2576;
8130 m_RawWidth = 3232;
8131 m_Tiff_bps = 10;
8132 } else if (!strcmp(m_CameraModel,"QV-R41")) {
8133 m_Height = 1720;
8134 m_Width = 2312;
8135 m_RawWidth = 3520;
8136 m_LeftMargin = 2;
8137 } else if (!strcmp(m_CameraModel,"QV-R51")) {
8138 m_Height = 1926;
8139 m_Width = 2580;
8140 m_RawWidth = 3904;
8141 } else if (!strcmp(m_CameraModel,"EX-S20")) {
8142 m_Height = 1208;
8143 m_Width = 1620;
8144 m_RawWidth = 2432;
8145 m_Flip = 3;
8146 } else if (!strcmp(m_CameraModel,"EX-S100")) {
8147 m_Height = 1544;
8148 m_Width = 2058;
8149 m_RawWidth = 3136;
8150 } else if (!strcmp(m_CameraModel,"EX-Z50")) {
8151 m_Height = 1931;
8152 m_Width = 2570;
8153 m_RawWidth = 3904;
8154 } else if (!strcmp(m_CameraModel,"EX-Z500")) {
8155 m_Height = 1937;
8156 m_Width = 2577;
8157 m_RawWidth = 3904;
8158 m_Filters = 0x16161616;
8159 } else if (!strcmp(m_CameraModel,"EX-Z55")) {
8160 m_Height = 1960;
8161 m_Width = 2570;
8162 m_RawWidth = 3904;
8163 } else if (!strcmp(m_CameraModel,"EX-Z60")) {
8164 m_Height = 2145;
8165 m_Width = 2833;
8166 m_RawWidth = 3584;
8167 m_Filters = 0x16161616;
8168 m_Tiff_bps = 10;
8169 } else if (!strcmp(m_CameraModel,"EX-Z75")) {
8170 m_Height = 2321;
8171 m_Width = 3089;
8172 m_RawWidth = 4672;
8173 m_WhiteLevel = 0xfff;
8174 } else if (!strcmp(m_CameraModel,"EX-Z750")) {
8175 m_Height = 2319;
8176 m_Width = 3087;
8177 m_RawWidth = 4672;
8178 m_WhiteLevel = 0xfff;
8179 } else if (!strcmp(m_CameraModel,"EX-Z850")) {
8180 m_Height = 2468;
8181 m_Width = 3279;
8182 m_RawWidth = 4928;
8183 m_WhiteLevel = 0xfff;
8184 } else if (!strcmp(m_CameraModel,"EX-Z8")) {
8185 m_Height = 2467;
8186 m_Width = 3281;
8187 m_RawHeight = 2502;
8188 m_RawWidth = 4992;
8189 m_WhiteLevel = 0xfff;
8190 } else if (l_FileSize == 15499264) { /* EX-Z1050 or EX-Z1080 */
8191 m_Height = 2752;
8192 m_Width = 3672;
8193 m_RawWidth = 5632;
8194 } else if (!strcmp(m_CameraModel,"EX-ZR100")) {
8195 m_Height = 3044;
8196 m_Width = 4072;
8197 m_RawWidth = 4096;
8198 m_Load_Flags = 80;
8199 } else if (!strcmp(m_CameraModel,"EX-P505")) {
8200 m_Height = 1928;
8201 m_Width = 2568;
8202 m_RawWidth = 3852;
8203 m_WhiteLevel = 0xfff;
8204 } else if (l_FileSize == 9313536) { /* EX-P600 or QV-R61 */
8205 m_Height = 2142;
8206 m_Width = 2844;
8207 m_RawWidth = 4288;
8208 } else if (!strcmp(m_CameraModel,"EX-P700")) {
8209 m_Height = 2318;
8210 m_Width = 3082;
8211 m_RawWidth = 4672;
8212 }
8213 if (!m_CameraModel[0])
8214 sprintf (m_CameraModel, "%dx%d", m_Width, m_Height);
8215 if (m_Filters == UINT_MAX) m_Filters = 0x94949494;
8216 if (m_RawColor) adobe_coeff (m_CameraMake, m_CameraModel);
8217 if (m_LoadRawFunction == &CLASS kodak_radc_load_raw)
8218 if (m_RawColor) adobe_coeff ("Apple","Quicktake");
8219 if (m_ThumbOffset && !m_ThumbHeight) {
8220 fseek (m_InputFile, m_ThumbOffset, SEEK_SET);
8221 if (ljpeg_start (&l_JHead, 1)) {
8222 m_ThumbWidth = l_JHead.wide;
8223 m_ThumbHeight = l_JHead.high;
8224 }
8225 }
8226 dng_skip:
8227 if (m_Fuji_Width) {
8228 m_Fuji_Width = m_Width >> !fuji_layout;
8229 if (~m_Fuji_Width & 1) m_Filters = 0x49494949;
8230 m_Width = (m_Height >> fuji_layout) + m_Fuji_Width;
8231 m_Height = m_Width - 1;
8232 m_PixelAspect = 1;
8233 } else {
8234 if (m_RawHeight < m_Height) m_RawHeight = m_Height;
8235 if (m_RawWidth < m_Width ) m_RawWidth = m_Width;
8236 }
8237 if (!m_Tiff_bps) m_Tiff_bps = 12;
8238 if (!m_WhiteLevel) m_WhiteLevel = (1 << m_Tiff_bps) - 1;
8239 if (!m_LoadRawFunction || m_Height < 22) m_IsRaw = 0;
8240 #ifdef NO_JASPER
8241 if (m_LoadRawFunction == &CLASS redcine_load_raw) {
8242 fprintf (stderr,_("%s: You must link dcraw with %s!\n"),
8243 m_UserSetting_InputFileName, "libjasper");
8244 m_IsRaw = 0;
8245 }
8246 #endif
8247 #ifdef NO_JPEG
8248 if (m_LoadRawFunction == &CLASS kodak_jpeg_load_raw ||
8249 m_LoadRawFunction == &CLASS lossy_dng_load_raw) {
8250 fprintf (stderr,_("%s: You must link dcraw with %s!\n"),
8251 m_UserSetting_InputFileName, "libjpeg");
8252 m_IsRaw = 0;
8253 }
8254 #endif
8255 if (!m_ColorDescriptor[0])
8256 strcpy (m_ColorDescriptor, m_Colors == 3 ? "RGBG":"GMCY");
8257 if (!m_RawHeight) m_RawHeight = m_Height;
8258 if (!m_RawWidth ) m_RawWidth = m_Width;
8259 if (m_Filters && m_Colors == 3)
8260 m_Filters |= ((m_Filters >> 2 & 0x22222222) |
8261 (m_Filters << 2 & 0x88888888)) & m_Filters << 1;
8262 notraw:
8263 // Somehow Nikon D90 files give a corrupt value here... although they shouldn't.
8264 if (m_Flip == -1) m_Flip = m_Tiff_Flip;
8265 if (m_Flip == -1) m_Flip = 0;
8266 }
8267
fuji_rotate()8268 void CLASS fuji_rotate() {
8269 int i, row, col;
8270 double step;
8271 float r, c, fr, fc;
8272 unsigned ur, uc;
8273 uint16_t wide, high, (*img)[4], (*pix)[4];
8274
8275 if (!m_Fuji_Width) return;
8276 TRACEKEYVALS("Rotating image 45 degrees","%s","");
8277 TRACEKEYVALS("m_Fuji_Width","%d",m_Fuji_Width);
8278 TRACEKEYVALS("m_Shrink","%d",m_Shrink);
8279 TRACEKEYVALS("m_UserSetting_HalfSize","%d",m_UserSetting_HalfSize);
8280 // XXX JDLA : Was : m_Fuji_Width = (m_Fuji_Width - 1 + m_Shrink) >> m_Shrink;
8281 m_Fuji_Width =
8282 (m_Fuji_Width - 1 + m_UserSetting_HalfSize) >> m_UserSetting_HalfSize;
8283 TRACEKEYVALS("m_Fuji_Width","%d",m_Fuji_Width);
8284 step = sqrt(0.5);
8285 wide = (uint16_t) (m_Fuji_Width / step);
8286 high = (uint16_t) ((m_Height - m_Fuji_Width) / step);
8287 img = (uint16_t (*)[4]) CALLOC (wide*high, sizeof *img);
8288 TRACEKEYVALS("m_Width","%d",m_Width);
8289 TRACEKEYVALS("m_Height","%d",m_Height);
8290 TRACEKEYVALS("wide","%d",wide);
8291 TRACEKEYVALS("high","%d",high);
8292 merror (img, "fuji_rotate()");
8293
8294 for (row=0; row < high; row++)
8295 for (col=0; col < wide; col++) {
8296 ur = (unsigned) (r = m_Fuji_Width + (row-col)*step);
8297 uc = (unsigned) (c = (row+col)*step);
8298 if (ur > (unsigned)(m_Height-2) || uc > (unsigned)(m_Width-2)) continue;
8299 fr = r - ur;
8300 fc = c - uc;
8301 pix = m_Image + ur*m_Width + uc;
8302 for (i=0; i < m_Colors; i++)
8303 img[row*wide+col][i] = (uint16_t) (
8304 (pix[ 0][i]*(1-fc) + pix[ 1][i]*fc) * (1-fr) +
8305 (pix[m_Width][i]*(1-fc) + pix[m_Width+1][i]*fc) * fr);
8306 }
8307 FREE (m_Image);
8308 m_OutWidth = m_Width = wide;
8309 m_OutHeight = m_Height = high;
8310 m_Image = img;
8311 m_Fuji_Width = 0; // this prevents image rotation when only phase 2 is called
8312
8313 TRACEKEYVALS("m_Width","%d",m_Width);
8314 TRACEKEYVALS("m_Height","%d",m_Height);
8315 TRACEKEYVALS("m_OutWidth","%d",m_OutWidth);
8316 TRACEKEYVALS("m_OutHeight","%d",m_OutHeight);
8317 }
8318
stretch()8319 void CLASS stretch()
8320 {
8321 uint16_t newdim, (*img)[4], *pix0, *pix1;
8322 int row, col, c;
8323 double rc, frac;
8324
8325 if (m_PixelAspect == 1) return;
8326 TRACEKEYVALS("Stretching the image","%s","");
8327 TRACEKEYVALS("m_PixelAspect","%f",m_PixelAspect);
8328 if (m_PixelAspect < 1) {
8329 newdim = (uint16_t) (m_Height / m_PixelAspect + 0.5);
8330 img = (uint16_t (*)[4]) CALLOC (m_Width*newdim, sizeof *img);
8331 merror (img, "stretch()");
8332 for (rc=row=0; row < newdim; row++, rc+=m_PixelAspect) {
8333 frac = rc - (c = (int) rc);
8334 pix0 = pix1 = m_Image[c*m_Width];
8335 if (c+1 < m_Height) pix1 += m_Width*4;
8336 for (col=0; col < m_Width; col++, pix0+=4, pix1+=4)
8337 for (c=0; c < m_Colors; c++) img[row*m_Width+col][c] =
8338 (uint16_t)(pix0[c]*(1-frac) + pix1[c]*frac + 0.5);
8339 }
8340 m_OutHeight = m_Height = newdim;
8341 } else {
8342 newdim = (uint16_t) (m_Width * m_PixelAspect + 0.5);
8343 img = (uint16_t (*)[4]) CALLOC (m_Height*newdim, sizeof *img);
8344 merror (img, "stretch()");
8345 for (rc=col=0; col < newdim; col++, rc+=1/m_PixelAspect) {
8346 frac = rc - (c = (int) rc);
8347 pix0 = pix1 = m_Image[c];
8348 if (c+1 < m_Width) pix1 += 4;
8349 for (row=0; row < m_Height; row++, pix0+=m_Width*4, pix1+=m_Width*4)
8350 for (c=0; c < m_Colors; c++) img[row*newdim+col][c] =
8351 (uint16_t) (pix0[c]*(1-frac) + pix1[c]*frac + 0.5);
8352 }
8353 m_OutWidth = m_Width = newdim;
8354 }
8355 FREE (m_Image);
8356 m_Image = img;
8357
8358 TRACEKEYVALS("m_Width","%d",m_Width);
8359 TRACEKEYVALS("m_Height","%d",m_Height);
8360 TRACEKEYVALS("m_OutWidth","%d",m_OutWidth);
8361 TRACEKEYVALS("m_OutHeight","%d",m_OutHeight);
8362 }
8363
flip_index(int row,int col)8364 int CLASS flip_index (int row, int col)
8365 {
8366 if (m_Flip & 4) SWAP(row,col);
8367 if (m_Flip & 2) row = m_OutHeight - 1 - row;
8368 if (m_Flip & 1) col = m_OutWidth - 1 - col;
8369 return row * m_OutWidth + col;
8370 }
8371
8372 struct tiff_tag {
8373 uint16_t tag, type;
8374 int count;
8375 union { char c[4]; short s[2]; int i; } val;
8376 };
8377
8378 struct tiff_hdr {
8379 uint16_t order, magic;
8380 int ifd;
8381 uint16_t pad, ntag;
8382 struct tiff_tag tag[23];
8383 int nextifd;
8384 uint16_t pad2, nexif;
8385 struct tiff_tag exif[4];
8386 uint16_t pad3, ngps;
8387 struct tiff_tag gpst[10];
8388 short bps[4];
8389 int rat[10];
8390 unsigned gps[26];
8391 char desc[512], make[64], model[64], soft[32], date[20], artist[64];
8392 };
8393
tiff_set(uint16_t * ntag,uint16_t tag,uint16_t type,int count,int val)8394 void CLASS tiff_set (uint16_t *ntag,
8395 uint16_t tag, uint16_t type, int count, int val)
8396 {
8397 struct tiff_tag *tt;
8398 int c;
8399
8400 tt = (struct tiff_tag *)(ntag+1) + (*ntag)++;
8401 tt->tag = tag;
8402 tt->type = type;
8403 tt->count = count;
8404 if (type < 3 && count <= 4)
8405 for(c=0;c<4;c++) tt->val.c[c] = val >> (c << 3);
8406 else if (type == 3 && count <= 2)
8407 for(c=0;c<2;c++) tt->val.s[c] = val >> (c << 4);
8408 else tt->val.i = val;
8409 }
8410
8411 #define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
8412
tiff_head(struct tiff_hdr * th)8413 void CLASS tiff_head (struct tiff_hdr *th)
8414 {
8415 int psize=0;
8416 struct tm *t;
8417
8418 memset (th, 0, sizeof *th);
8419 th->order = htonl(0x4d4d4949) >> 16;
8420 th->magic = 42;
8421 th->ifd = 10;
8422 tiff_set (&th->ntag, 270, 2, 512, TOFF(th->desc));
8423 tiff_set (&th->ntag, 271, 2, 64, TOFF(th->make));
8424 tiff_set (&th->ntag, 272, 2, 64, TOFF(th->model));
8425 tiff_set (&th->ntag, 274, 3, 1, "12435867"[m_Flip]-'0');
8426 tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
8427 tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
8428 tiff_set (&th->ntag, 284, 3, 1, 1);
8429 tiff_set (&th->ntag, 296, 3, 1, 2);
8430 tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft));
8431 tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date));
8432 tiff_set (&th->ntag, 315, 2, 64, TOFF(th->artist));
8433 tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif));
8434 if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th);
8435 tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
8436 tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
8437 tiff_set (&th->nexif, 34855, 3, 1, (int) m_IsoSpeed);
8438 tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
8439 strncpy (th->desc, m_Description, 512);
8440 strncpy (th->make, m_CameraMake, 64);
8441 strncpy (th->model, m_CameraModel, 64);
8442 strcpy (th->soft, DCRAW_VERSION);
8443 t = localtime (&m_TimeStamp);
8444 sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d",
8445 t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
8446 strncpy (th->artist, m_Artist, 64);
8447 }
8448
jpeg_thumb()8449 void CLASS jpeg_thumb ()
8450 /* Remember: This function is modified to write the raw’s thumbnail to the
8451 m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
8452 */
8453 {
8454 char *thumb;
8455 uint16_t exif[5];
8456 struct tiff_hdr th;
8457
8458 thumb = (char *) MALLOC (m_ThumbLength);
8459 merror (thumb, "jpeg_thumb()");
8460 ptfread (thumb, 1, m_ThumbLength, m_InputFile);
8461 // fputc (0xff, m_OutputFile);
8462 // fputc (0xd8, m_OutputFile);
8463 m_Thumb.push_back('\xff');
8464 m_Thumb.push_back('\xd8');
8465
8466 if (strcmp (thumb+6, "Exif")) {
8467 memcpy (exif, "\xff\xe1 Exif\0\0", 10);
8468 exif[1] = htons (8 + sizeof th);
8469 //ptfwrite (exif, 1, sizeof exif, m_OutputFile);
8470 VAppend(m_Thumb, (char*)&exif[0], sizeof(exif));
8471 tiff_head (&th);
8472 //ptfwrite (&th, 1, sizeof th, m_OutputFile);
8473 VAppend(m_Thumb, (char*)&th, sizeof(th));
8474 }
8475 //ptfwrite (thumb+2, 1, m_ThumbLength-2, m_OutputFile);
8476 VAppend(m_Thumb, thumb+2, m_ThumbLength-2);
8477
8478 FREE (thumb);
8479 }
8480
8481 ////////////////////////////////////////////////////////////////////////////////
8482 //
8483 // Identify
8484 //
8485 // First method to be called when in an photivo application.
8486 // Hereafter camera, model, and a number of other picture and camera
8487 // parameters are identified.
8488 // Returns 0 on success.
8489 //
8490 ////////////////////////////////////////////////////////////////////////////////
8491
Identify(const QString NewInputFile)8492 short CLASS Identify(const QString NewInputFile) {
8493
8494 // This is here to support multiple calls.
8495 ResetNonUserSettings();
8496 FCLOSE(m_InputFile);
8497
8498 if (NewInputFile != "") {
8499 FREE(m_UserSetting_InputFileName);
8500 m_UserSetting_InputFileName = (char*) MALLOC(1 + strlen(NewInputFile.toLocal8Bit().data()));
8501 ptMemoryError(m_UserSetting_InputFileName,__FILE__,__LINE__);
8502 strcpy(m_UserSetting_InputFileName, NewInputFile.toLocal8Bit().data());
8503 }
8504
8505 if (!(m_InputFile = fopen (m_UserSetting_InputFileName, "rb"))) {
8506 perror (m_UserSetting_InputFileName);
8507 return -1;
8508 }
8509
8510 identify();
8511
8512 if (!m_IsRaw) {
8513 FCLOSE(m_InputFile);
8514 }
8515 return !m_IsRaw;
8516 }
8517
8518 ////////////////////////////////////////////////////////////////////////////////
8519 //
8520 // RunDcRaw_Phase1
8521 //
8522 // Settings are given via the m_UserSetting* members.
8523 // It will end there where the raw image is loaded.
8524 // Badpixels and darkframes subtracted.
8525 // But before colorscaling and the like so that we can
8526 // intervene in the whitebalances etc.
8527 // Returns 0 on success.
8528 //
8529 ////////////////////////////////////////////////////////////////////////////////
8530
RunDcRaw_Phase1()8531 short CLASS RunDcRaw_Phase1() {
8532
8533 // TODO foveon for the moment not in. Need study material
8534 // to have this +/- right.
8535 assert (!m_IsFoveon);
8536
8537 TRACEKEYVALS("PreMult[0]","%f",VALUE(m_PreMultipliers[0]));
8538 TRACEKEYVALS("PreMult[1]","%f",VALUE(m_PreMultipliers[1]));
8539 TRACEKEYVALS("PreMult[2]","%f",VALUE(m_PreMultipliers[2]));
8540 TRACEKEYVALS("PreMult[3]","%f",VALUE(m_PreMultipliers[3]));
8541 #ifdef TRACE_ORIGIN
8542 TRACEKEYVALS("PreMult File","%s",m_PreMultipliers[0].File);
8543 TRACEKEYVALS("PreMult Line","%d",m_PreMultipliers[0].Line);
8544 #endif
8545 TRACEKEYVALS("D65Mult[0]","%f",VALUE(m_D65Multipliers[0]));
8546 TRACEKEYVALS("D65Mult[1]","%f",VALUE(m_D65Multipliers[1]));
8547 TRACEKEYVALS("D65Mult[2]","%f",VALUE(m_D65Multipliers[2]));
8548 TRACEKEYVALS("D65Mult[3]","%f",VALUE(m_D65Multipliers[3]));
8549 #ifdef TRACE_ORIGIN
8550 TRACEKEYVALS("D65Mult File","%s",m_D65Multipliers[0].File);
8551 TRACEKEYVALS("D65Mult Line","%d",m_D65Multipliers[0].Line);
8552 #endif
8553
8554 TRACEKEYVALS("RawWidth","%d",m_RawWidth);
8555 TRACEKEYVALS("RawHeight","%d",m_RawHeight);
8556 TRACEKEYVALS("TopMargin","%d",m_TopMargin);
8557 TRACEKEYVALS("LeftMargin","%d",m_LeftMargin);
8558 TRACEKEYVALS("BlackLevel","%d",m_BlackLevel);
8559
8560 // OK for second entry.
8561 if (m_LoadRawFunction == &CLASS kodak_ycbcr_load_raw) {
8562 m_Height += m_Height & 1;
8563 m_Width += m_Width & 1;
8564 }
8565
8566 m_OutHeight = m_Height;
8567 m_OutWidth = m_Width;
8568
8569 TRACEKEYVALS("OutWidth","%d",m_OutWidth);
8570 TRACEKEYVALS("Width","%d",m_Width);
8571
8572 // Also some reshuffling for second entry problem.
8573 // not sure how c_matrix comes into play here ...
8574 int l_CameraMatrix = (m_UserSetting_CameraMatrix < 0) ?
8575 m_UserSetting_CameraWb : m_UserSetting_CameraMatrix;
8576 TRACEKEYVALS("US_CameraWB","%d",m_UserSetting_CameraWb);
8577 TRACEKEYVALS("US_CameraMatr","%d",m_UserSetting_CameraMatrix);
8578 TRACEKEYVALS("CameraMatrix","%d",l_CameraMatrix);
8579 TRACEKEYVALS("m_cmatrix[0][0","%f",m_cmatrix[0][0]);
8580 if (l_CameraMatrix && m_cmatrix[0][0] > 0.25) {
8581 TRACEKEYVALS("Using CamMatr","%s","Yes");
8582 memcpy (m_MatrixCamRGBToSRGB, m_cmatrix, sizeof m_cmatrix);
8583 m_RawColor = 0;
8584 }
8585
8586 // Allocation is depending on m_Raw_Image below.
8587 FREE(m_Image);
8588
8589 if (m_MetaLength) {
8590 FREE(m_MetaData);
8591 m_MetaData = (char *) MALLOC (m_MetaLength);
8592 merror (m_MetaData, "main()");
8593 }
8594 if (m_Filters || m_Colors == 1) {
8595 m_Raw_Image = (uint16_t *) CALLOC ((m_RawHeight+7)*m_RawWidth, 2);
8596 merror (m_Raw_Image, "main().m_Raw_Image");
8597 } else {
8598 // Basic image memory allocation @ 4 int per pixel happens here.
8599 m_Image = (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
8600 merror (m_Image, "main()");
8601 }
8602
8603 TRACEKEYVALS("CameraMake","%s",m_CameraMake);
8604 TRACEKEYVALS("CameraModel","%s",m_CameraModel);
8605 TRACEKEYVALS("InputFile","%s",m_UserSetting_InputFileName);
8606 TRACEKEYVALS("Filters","%x",m_Filters);
8607 TRACEKEYVALS("Flip","%x",m_Flip);
8608
8609 fseek (m_InputFile, m_Data_Offset, SEEK_SET);
8610
8611 // Basic loading operation.
8612 // That's the hook into the real workhorse.
8613
8614 (*this.*m_LoadRawFunction)();
8615
8616 if (m_Raw_Image) {
8617 // Basic image memory allocation @ 4 int per pixel happens here.
8618 m_Image = (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
8619 merror (m_Image, "main()");
8620 crop_masked_pixels();
8621 FREE (m_Raw_Image);
8622 }
8623
8624 if (m_ZeroIsBad) remove_zeroes();
8625 bad_pixels (m_UserSetting_BadPixelsFileName);
8626 if (m_UserSetting_DarkFrameFileName)
8627 subtract (m_UserSetting_DarkFrameFileName);
8628
8629 // photivo extra.
8630 // Calculation of the inverse m_MatrixCamRGBToSRGB
8631 double rgb_cam_transpose[4][3];
8632 for (short i=0; i<4; i++) for (short j=0; j<3; j++)
8633 rgb_cam_transpose[i][j] = m_MatrixCamRGBToSRGB[j][i];
8634 pseudoinverse(rgb_cam_transpose,m_MatrixSRGBToCamRGB,m_Colors);
8635
8636 // ReportedWidth & Height correct for fuji_rotate stuff and pixelaspects.
8637 m_ReportedWidth = m_Width;
8638 m_ReportedHeight = m_Height;
8639 if (m_Fuji_Width) {
8640 m_IsFuji = m_Fuji_Width;
8641 m_ReportedWidth = (m_Fuji_Width-1) / sqrt(0.5);
8642 m_ReportedHeight = (m_Height-m_Fuji_Width+1)/sqrt(0.5);
8643 }
8644 if (m_PixelAspect<1)
8645 m_ReportedHeight = (uint16_t) (m_Height / m_PixelAspect + 0.5);
8646 if (m_PixelAspect>1)
8647 m_ReportedWidth = (uint16_t) (m_Width * m_PixelAspect + 0.5);
8648
8649 // TODO Mike: m_ReportedH/W is never set back to m_H/W, CHECK!
8650
8651 TRACEKEYVALS("m_Width","%d",m_Width);
8652 TRACEKEYVALS("m_Height","%d",m_Height);
8653 TRACEKEYVALS("m_ReportedWidth","%d",m_ReportedWidth);
8654 TRACEKEYVALS("m_ReportedHeight","%d",m_ReportedHeight);
8655
8656 TRACEKEYVALS("PreMult[0]","%f",VALUE(m_PreMultipliers[0]));
8657 TRACEKEYVALS("PreMult[1]","%f",VALUE(m_PreMultipliers[1]));
8658 TRACEKEYVALS("PreMult[2]","%f",VALUE(m_PreMultipliers[2]));
8659 TRACEKEYVALS("PreMult[3]","%f",VALUE(m_PreMultipliers[3]));
8660 #ifdef TRACE_ORIGIN
8661 TRACEKEYVALS("PreMult File","%s",m_PreMultipliers[0].File);
8662 TRACEKEYVALS("PreMult Line","%d",m_PreMultipliers[0].Line);
8663 #endif
8664 TRACEKEYVALS("D65Mult[0]","%f",VALUE(m_D65Multipliers[0]));
8665 TRACEKEYVALS("D65Mult[1]","%f",VALUE(m_D65Multipliers[1]));
8666 TRACEKEYVALS("D65Mult[2]","%f",VALUE(m_D65Multipliers[2]));
8667 TRACEKEYVALS("D65Mult[3]","%f",VALUE(m_D65Multipliers[3]));
8668 #ifdef TRACE_ORIGIN
8669 TRACEKEYVALS("D65Mult File","%s",m_D65Multipliers[0].File);
8670 TRACEKEYVALS("D65Mult Line","%d",m_D65Multipliers[0].Line);
8671 #endif
8672 TRACEKEYVALS("Colors","%d",m_Colors);
8673 TRACEKEYVALS("Filters","%x",m_Filters);
8674 TRACEKEYVALS("Flip","%x",m_Flip);
8675
8676 // Cache the image after Phase1.
8677 FREE(m_Image_AfterPhase1);
8678 m_Image_AfterPhase1 =
8679 (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
8680 merror (m_Image_AfterPhase1, "main()");
8681 memcpy(m_Image_AfterPhase1,m_Image,m_OutHeight*m_OutWidth*sizeof(*m_Image));
8682 // Some other stuff to cache.
8683 m_Filters_AfterPhase1 = m_Filters;
8684 m_BlackLevel_AfterPhase1 = m_BlackLevel;
8685 for (int k=0; k<8; k++) m_CBlackLevel_AfterPhase1[k] = m_CBlackLevel[k];
8686 m_WhiteLevel_AfterPhase1 = m_WhiteLevel;
8687 m_Width_AfterPhase1 = m_Width;
8688 m_Height_AfterPhase1 = m_Height;
8689 m_OutWidth_AfterPhase1 = m_OutWidth;
8690 m_OutHeight_AfterPhase1 = m_OutHeight;
8691
8692 return 0;
8693 }
8694
8695 ////////////////////////////////////////////////////////////////////////////////
8696 //
8697 // RunDcRaw_Phase2
8698 //
8699 // Color scaling.
8700 // Interpolation.
8701 // Green mixing.
8702 //
8703 ////////////////////////////////////////////////////////////////////////////////
8704
RunDcRaw_Phase2(const short NoCache)8705 short CLASS RunDcRaw_Phase2(const short NoCache) {
8706
8707 // Make sure we are starting from the right image.
8708 if (NoCache) {
8709 FREE(m_Image_AfterPhase1);
8710 } else {
8711 FREE(m_Image);
8712 m_Width = m_Width_AfterPhase1;
8713 m_Height = m_Height_AfterPhase1;
8714 m_OutWidth = m_OutWidth_AfterPhase1;
8715 m_OutHeight = m_OutHeight_AfterPhase1;
8716 m_Image =
8717 (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
8718 merror (m_Image, "main()");
8719 memcpy(m_Image,m_Image_AfterPhase1,m_OutHeight*m_OutWidth*sizeof(*m_Image));
8720 // Restore some other cached values.
8721 m_Filters = m_Filters_AfterPhase1;
8722 m_BlackLevel = m_BlackLevel_AfterPhase1;
8723 for (int k=0; k<8; k++) m_CBlackLevel[k] = m_CBlackLevel_AfterPhase1[k];
8724 m_WhiteLevel = m_WhiteLevel_AfterPhase1;
8725 }
8726 m_Fuji_Width = m_IsFuji;
8727 unsigned i = m_CBlackLevel[3];
8728 for (int c=0; c<3; c++) if (i > m_CBlackLevel[c]) i = m_CBlackLevel[c];
8729 for (int c=0; c<4; c++) m_CBlackLevel[c] -= i;
8730 m_BlackLevel += i;
8731 if (m_UserSetting_BlackPoint >= 0) m_BlackLevel = m_UserSetting_BlackPoint;
8732 for (int c=0; c<4; c++) m_CBlackLevel[c] += m_BlackLevel;
8733 if (m_UserSetting_Saturation > 0) m_WhiteLevel = m_UserSetting_Saturation;
8734
8735 // If m_UserSetting_HalfSize then the BAYER(row,col) macro
8736 // will map 2X2 pixels of the Bayer array, directly onto one
8737 // pixel of the image (and the correct color channel) foregoing
8738 // the need for interpolation and much faster !
8739 m_Shrink = m_Filters && m_UserSetting_HalfSize;
8740
8741 TRACEKEYVALS("Shrink","%d",m_Shrink);
8742
8743 TRACEKEYVALS("BlackLevel","%d",m_BlackLevel);
8744 TRACEKEYVALS("WhiteLevel","%d",m_WhiteLevel);
8745 TRACEKEYVALS("Colors","%d",m_Colors);
8746
8747 TRACEKEYVALS("Phase2 begin Width","%d",m_Width);
8748 TRACEKEYVALS("Phase2 begin Height","%d",m_Height);
8749 TRACEKEYVALS("Phase2 begin OutWidth","%d",m_OutWidth);
8750 TRACEKEYVALS("Phase2 begin OutHeight","%d",m_OutHeight);
8751
8752 // Crop for detail view
8753 if (m_UserSetting_DetailView == 1 &&
8754 m_IsFuji == 0 &&
8755 m_PixelAspect == 1.0f) {
8756 ptCrop();
8757 }
8758
8759 // Copied from earlier to here also.
8760 // Enables Phase3 to reenter with a different FourColorRGB setting.
8761 if ((m_UserSetting_Quality == ptInterpolation_VNG4 || m_UserSetting_HalfSize)
8762 && m_Filters != 0) { // m_Filters==0 <-> 3 channel RAWs
8763 m_MixGreen = 1;
8764 } else {
8765 m_MixGreen = 0;
8766 }
8767
8768 if (!m_IsFoveon && m_UserSetting_AdjustMaximum > 0) {
8769 ptAdjustMaximum(1-m_UserSetting_AdjustMaximum);
8770 }
8771
8772 assert (!m_IsFoveon);
8773 // if (m_IsFoveon ) foveon_interpolate();
8774
8775 if (m_UserSetting_GreenEquil) {
8776 TRACEKEYVALS("Green equilibration","%s","");
8777 green_equilibrate((float)m_UserSetting_GreenEquil/100.0f);
8778 }
8779
8780 if (m_UserSetting_HotpixelReduction) {
8781 TRACEKEYVALS("Hotpixel reduction on bayer","%s","");
8782 ptHotpixelReductionBayer();
8783 }
8784
8785 if (m_UserSetting_CfaLineDn !=0) {
8786 TRACEKEYVALS("Cfa line denoise","%s","");
8787 cfa_linedn(0.00002*(float)m_UserSetting_CfaLineDn);
8788 }
8789
8790 if (!m_IsFoveon) {
8791 ptScaleColors();
8792 }
8793
8794 if (m_UserSetting_CaCorrect !=0) {
8795 TRACEKEYVALS("CA correction","%s","");
8796 CA_correct(m_UserSetting_CaRed,m_UserSetting_CaBlue);
8797 }
8798
8799 TRACEKEYVALS("Colors","%d",m_Colors);
8800
8801 // not 1:1 pipe, use FC marco instead of interpolation
8802 uint16_t (*TempImage)[4];
8803 if (m_Shrink && m_Filters != 2) { // -> preinterpolate will set m_Filters = 0 if != 2
8804 m_OutHeight = (m_Height + 1) / 2;
8805 m_OutWidth = (m_Width + 1) / 2;
8806 TempImage = (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *TempImage);
8807 merror (TempImage, "main()");
8808 #pragma omp parallel for schedule(static)
8809 for (uint16_t row=0; row < m_Height; row++) {
8810 for (uint16_t col=0; col < m_Width; col++) {
8811 TempImage[((row) >> m_Shrink)*m_OutWidth + ((col) >> m_Shrink)][FC(row,col)] =
8812 m_Image[(row)*m_Width + (col)][FC(row,col)];
8813 }
8814 }
8815 FREE(m_Image);
8816 m_Image = TempImage;
8817 }
8818
8819 // RG1BG2 -> RGB (if not 4 colors needed later on)
8820 pre_interpolate();
8821
8822 TRACEKEYVALS("Colors","%d",m_Colors);
8823
8824
8825 // Interpolation/demosaicing according to one of the algorithms.
8826 if (m_Filters) {
8827 if (m_UserSetting_BayerDenoise && !m_UserSetting_HalfSize) {
8828 if (m_UserSetting_BayerDenoise==1) fbdd(0);
8829 else if (m_UserSetting_BayerDenoise==2) fbdd(1);
8830 }
8831 if (m_Filters == 2) // for 3x3 pattern we fix to VNG
8832 vng_interpolate();
8833 else if (m_UserSetting_Quality == ptInterpolation_Linear)
8834 lin_interpolate();
8835 else if (m_UserSetting_Quality == ptInterpolation_VNG ||
8836 m_UserSetting_Quality == ptInterpolation_VNG4)
8837 vng_interpolate();
8838 else if (m_UserSetting_Quality == ptInterpolation_PPG)
8839 ppg_interpolate();
8840 else if (m_UserSetting_Quality == ptInterpolation_DCB)
8841 dcb(m_UserSetting_InterpolationPasses, 1);
8842 else if (m_UserSetting_Quality == ptInterpolation_DCBSoft)
8843 dcb_interpolate_soft_old(m_UserSetting_InterpolationPasses, 1);
8844 else if (m_UserSetting_Quality == ptInterpolation_DCBSharp)
8845 dcb_interpolate_sharp_old(m_UserSetting_InterpolationPasses, 1);
8846 else if (m_UserSetting_Quality == ptInterpolation_AHD)
8847 ahd_interpolate();
8848 else if (m_UserSetting_Quality == ptInterpolation_AHD_mod)
8849 ahd_interpolate_mod();
8850 else if (m_UserSetting_Quality == ptInterpolation_VCD)
8851 vcd_interpolate(12);
8852 else if (m_UserSetting_Quality == ptInterpolation_LMMSE)
8853 lmmse_interpolate(1);
8854 else if (m_UserSetting_Quality == ptInterpolation_AMaZE)
8855 amaze_demosaic();
8856 } else {
8857 if (m_UserSetting_HotpixelReduction && m_UserSetting_HalfSize) {
8858 TRACEKEYVALS("Hotpixel reduction on RGB","%s","");
8859 ptHotpixelReduction();
8860 }
8861 if (m_UserSetting_BayerDenoise && !m_UserSetting_HalfSize) {
8862 if (m_UserSetting_BayerDenoise==1) fbdd(0);
8863 else if (m_UserSetting_BayerDenoise==2) fbdd(1);
8864 }
8865 }
8866 // If 1:1 and no interpolation is chosen show the Bayer pattern.
8867
8868 TRACEKEYVALS("Interpolation type","%d",m_UserSetting_Quality);
8869
8870 // Additional photivo stuff. Other halvings on request.
8871 if (m_UserSetting_HalfSize > 1 ||
8872 (m_UserSetting_HalfSize == 1 && m_Shrink == 0) || // 3 channel RAWs
8873 (m_UserSetting_HalfSize == 1 && m_Filters == 2)) { // 3x3 pattern
8874 short Factor = m_UserSetting_HalfSize - 1;
8875 if (m_Shrink == 0 || m_Filters == 2) Factor += 1;
8876
8877 uint16_t NewHeight = m_Height >> Factor;
8878 uint16_t NewWidth = m_Width >> Factor;
8879
8880 short Step = 1 << Factor;
8881 int Average = 2 * Factor;
8882
8883 uint16_t (*NewImage)[4] =
8884 (uint16_t (*)[4]) CALLOC(NewWidth*NewHeight,sizeof(*m_Image));
8885 ptMemoryError(NewImage,__FILE__,__LINE__);
8886
8887 #pragma omp parallel for schedule(static)
8888 for (uint16_t Row=0; Row < NewHeight*Step; Row+=Step) {
8889 for (uint16_t Col=0; Col < NewWidth*Step; Col+=Step) {
8890 uint32_t PixelValue[4] = {0,0,0,0};
8891 for (uint8_t sRow=0; sRow < Step; sRow++) {
8892 for (uint8_t sCol=0; sCol < Step; sCol++) {
8893 int32_t index = (Row+sRow)*m_Width+Col+sCol;
8894 for (short c=0; c < 4; c++) {
8895 PixelValue[c] += m_Image[index][c];
8896 }
8897 }
8898 }
8899 for (short c=0; c < 4; c++) {
8900 NewImage[Row/Step*NewWidth+Col/Step][c]
8901 = PixelValue[c] >> Average;
8902 }
8903 }
8904 }
8905
8906 FREE(m_Image);
8907 m_Height = m_OutHeight = NewHeight;
8908 m_Width = m_OutWidth = NewWidth;
8909 m_Image = NewImage;
8910 }
8911
8912 // Green mixing
8913 if (m_MixGreen && m_Colors != 3) {
8914 #pragma omp parallel for schedule(static) default(shared)
8915 for (uint32_t i=0; i < (uint32_t) m_Height*m_Width; i++)
8916 m_Image[i][1] = (m_Image[i][1] + m_Image[i][3]) >> 1;
8917 m_Colors = 3;
8918 }
8919
8920 // Median filter.
8921 if (!m_IsFoveon && m_Colors == 3) {
8922 if (m_UserSetting_MedianPasses > 0) median_filter_new();
8923 if (m_UserSetting_ESMedianPasses > 0 && !m_UserSetting_HalfSize) es_median_filter();
8924 if (m_UserSetting_EeciRefine == 1) refinement();
8925 }
8926
8927 // Additional cleaning with hotpixel reduction
8928 if (m_UserSetting_HotpixelReduction && m_UserSetting_Quality != ptInterpolation_Bayer) {
8929 ptHotpixelReduction();
8930 }
8931
8932 // XXX JDLA Additional steps for Fuji
8933 // And they don't hurt for others as they are early stopped.
8934 fuji_rotate();
8935 stretch();
8936
8937 // Crop for detail view
8938 if (m_UserSetting_DetailView == 1 &&
8939 (m_IsFuji != 0 ||
8940 m_PixelAspect != 1.0f)) {
8941 ptCrop();
8942 }
8943
8944 // Cache the image after Phase2.
8945 FREE(m_Image_AfterPhase2);
8946 m_Image_AfterPhase2 =
8947 (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
8948 merror (m_Image_AfterPhase2, "main()");
8949 memcpy(m_Image_AfterPhase2,m_Image,m_OutHeight*m_OutWidth*sizeof(*m_Image));
8950 // Some other stuff to cache.
8951 m_Filters_AfterPhase2 = m_Filters;
8952
8953 TRACEKEYVALS("BlackLevel","%d",m_BlackLevel);
8954 TRACEKEYVALS("WhiteLevel","%d",m_WhiteLevel);
8955 TRACEKEYVALS("Colors","%d",m_Colors);
8956 TRACEKEYVALS("Filters","%x",m_Filters);
8957
8958 TRACEKEYVALS("Phase2 end Width","%d",m_Width);
8959 TRACEKEYVALS("Phase2 end Height","%d",m_Height);
8960 TRACEKEYVALS("Phase2 end OutWidth","%d",m_OutWidth);
8961 TRACEKEYVALS("Phase2 end OutHeight","%d",m_OutHeight);
8962
8963 return 0;
8964 }
8965
8966 ////////////////////////////////////////////////////////////////////////////////
8967 //
8968 // RunDcRaw_Phase3
8969 //
8970 // Highlights
8971 //
8972 ////////////////////////////////////////////////////////////////////////////////
8973
RunDcRaw_Phase3(const short NoCache)8974 short CLASS RunDcRaw_Phase3(const short NoCache) {
8975
8976 // Make sure we are starting from the right image.
8977 if (NoCache) {
8978 FREE(m_Image_AfterPhase2);
8979 } else {
8980 FREE(m_Image);
8981 m_Image =
8982 (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
8983 merror (m_Image, "main()");
8984 memcpy(m_Image,m_Image_AfterPhase2,m_OutHeight*m_OutWidth*sizeof(*m_Image));
8985 // Restore some other cached values.
8986 m_Filters = m_Filters_AfterPhase2;
8987 }
8988
8989 TRACEKEYVALS("CamMult[0]","%f",VALUE(m_CameraMultipliers[0]));
8990 TRACEKEYVALS("CamMult[1]","%f",VALUE(m_CameraMultipliers[1]));
8991 TRACEKEYVALS("CamMult[2]","%f",VALUE(m_CameraMultipliers[2]));
8992 TRACEKEYVALS("CamMult[3]","%f",VALUE(m_CameraMultipliers[3]));
8993 #ifdef TRACE_ORIGIN
8994 TRACEKEYVALS("CamMult File","%s",m_CameraMultipliers[0].File);
8995 TRACEKEYVALS("CamMult Line","%d",m_CameraMultipliers[0].Line);
8996 #endif
8997
8998 ptHighlight(m_UserSetting_photivo_ClipMode,
8999 m_UserSetting_photivo_ClipParameter);
9000
9001 // Cache the image after Phase3.
9002 FREE(m_Image_AfterPhase3);
9003 m_Image_AfterPhase3 =
9004 (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
9005 merror (m_Image_AfterPhase3, "main()");
9006 memcpy(m_Image_AfterPhase3,m_Image,m_OutHeight*m_OutWidth*sizeof(*m_Image));
9007 // Some other stuff to cache.
9008 m_Filters_AfterPhase3 = m_Filters;
9009
9010 return 0;
9011 }
9012
9013 ////////////////////////////////////////////////////////////////////////////////
9014 //
9015 // BlendHighlights
9016 // (original from dcraw TODO Refine and analyse)
9017 //
9018 ////////////////////////////////////////////////////////////////////////////////
9019
ptBlendHighlights()9020 void CLASS ptBlendHighlights() {
9021
9022 int ClipLevel=INT_MAX;
9023 int i;
9024 int j;
9025
9026 static const float trans[2][4][4] =
9027 { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } },
9028 { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
9029 static const float itrans[2][4][4] =
9030 { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } },
9031 { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
9032 float Cam[2][4], lab[2][4], Sum[2], chratio;
9033
9034 const int transIdx = m_Colors - 3;
9035 assert(transIdx > -1);
9036 if (transIdx > 1) return;
9037
9038 // to shut up gcc warnings...
9039 const int localColors = ptMin(static_cast<int>(m_Colors), 4);
9040
9041 for (short c=0; c<m_Colors; c++) {
9042 if (ClipLevel > (i = (int)(0xFFFF*VALUE(m_PreMultipliers[c])))) {
9043 ClipLevel = i;
9044 }
9045 }
9046
9047 for (uint16_t Row=0; Row < m_Height; Row++) {
9048 for (uint16_t Column=0; Column < m_Width; Column++) {
9049 short c;
9050 for (c=0; c<m_Colors; c++) {
9051 if (m_Image[Row*m_Width+Column][c] > ClipLevel) break;
9052 }
9053 if (c == m_Colors) continue; // No clip
9054 for (c=0; c<m_Colors; c++) {
9055 Cam[0][c] = m_Image[Row*m_Width+Column][c];
9056 Cam[1][c] = MIN(Cam[0][c],(float)ClipLevel);
9057 }
9058 for (i=0; i < 2; i++) {
9059 for (c=0; c<m_Colors; c++) {
9060 for (lab[i][c]=j=0; j < m_Colors; j++) {
9061 lab[i][c] += trans[transIdx][c][j] * Cam[i][j];
9062 }
9063 }
9064 for (Sum[i]=0,c=1; c < m_Colors; c++) {
9065 Sum[i] += SQR(lab[i][c]);
9066 }
9067 }
9068 chratio = sqrt(Sum[1]/Sum[0]);
9069 for (c = 1; c < m_Colors; c++) {
9070 lab[0][c] *= chratio;
9071 }
9072 for (c = 0; (c < localColors); c++) {
9073 for (Cam[0][c]=j=0; (j < localColors); j++) {
9074 Cam[0][c] += itrans[transIdx][c][j] * lab[0][j];
9075 }
9076 }
9077 for (c = 0; c < m_Colors; c++) {
9078 m_Image[Row*m_Width+Column][c] = (uint16_t)(Cam[0][c] / m_Colors);
9079 }
9080 }
9081 }
9082 }
9083
9084 ////////////////////////////////////////////////////////////////////////////////
9085 //
9086 // Hotpixel reduction
9087 //
9088 ////////////////////////////////////////////////////////////////////////////////
9089
9090
ptHotpixelReduction()9091 void CLASS ptHotpixelReduction() {
9092 uint16_t HotpixelThreshold = 0x00ff;
9093 uint16_t Threshold = (int32_t) ((1.0-m_UserSetting_HotpixelReduction)*0x2fff);
9094 uint16_t Width = m_OutWidth;
9095 uint16_t Height = m_OutHeight;
9096 // bei 1:2 oder kleiner m_Image hat in jedem Punkt RGBG
9097 // bei 1:1 m_Image hat Bayer Pattern
9098 // Länge und Breite OutWidth und OutHeight
9099 // unterschieptiche pixel in unterschieptichen ebenen ansprechen und werte zur luminanz skalieren
9100 #pragma omp parallel for schedule(static) default(shared)
9101 for (uint16_t Row=0; Row<Height; Row++) {
9102 for (uint16_t Col=0; Col<Width; Col++) {
9103 uint16_t TempValue = 0;
9104 for (int c=0; c<4; c++) {
9105 if (m_Image[Row*Width+Col][c] > HotpixelThreshold) {
9106 if (Row > 1) TempValue = MAX(m_Image[(Row-1)*Width+Col][c],TempValue);
9107 if (Row < Height-1) TempValue = MAX(m_Image[(Row+1)*Width+Col][c],TempValue);
9108 if (Col > 1) TempValue = MAX(m_Image[Row*Width+Col-1][c],TempValue);
9109 if (Col < Width-1) TempValue = MAX(m_Image[Row*Width+Col+1][c],TempValue);
9110 if (TempValue+Threshold<m_Image[Row*Width+Col][c])
9111 m_Image[Row*Width+Col][c] = TempValue;
9112 }
9113 if (m_Image[Row*Width+Col][c] < 10*HotpixelThreshold) {
9114 TempValue = 0xffff;
9115 if (Row > 1) TempValue = MIN(m_Image[(Row-1)*Width+Col][c],TempValue);
9116 if (Row < Height-1) TempValue = MIN(m_Image[(Row+1)*Width+Col][c],TempValue);
9117 if (Col > 1) TempValue = MIN(m_Image[Row*Width+Col-1][c],TempValue);
9118 if (Col < Width-1) TempValue = MIN(m_Image[Row*Width+Col+1][c],TempValue);
9119 if (TempValue-Threshold>m_Image[Row*Width+Col][c])
9120 m_Image[Row*Width+Col][c] = TempValue;
9121 }
9122 }
9123 }
9124 }
9125 }
9126
ptHotpixelReductionBayer()9127 void CLASS ptHotpixelReductionBayer() {
9128 uint16_t HotpixelThreshold = 0x00ff;
9129 uint16_t Threshold = (int32_t) ((1.0-m_UserSetting_HotpixelReduction)*0x2fff);
9130 uint16_t Width = m_OutWidth;
9131 uint16_t Height = m_OutHeight;
9132
9133 #pragma omp parallel for schedule(static)
9134 for (uint16_t Row=0; Row<Height; Row++) {
9135 for (uint16_t Col=0; Col<Width; Col++) {
9136 uint16_t TempValue = 0;
9137 for (int Channel=0; Channel<4; Channel++) {
9138 if (m_Image[Row*Width+Col][Channel] > HotpixelThreshold) {
9139 if (Row > 2) TempValue = MAX(m_Image[(Row-2)*Width+Col][Channel],TempValue);
9140 if (Row < Height-2) TempValue = MAX(m_Image[(Row+2)*Width+Col][Channel],TempValue);
9141 if (Col > 2) TempValue = MAX(m_Image[Row*Width+Col-2][Channel],TempValue);
9142 if (Col < Width-2) TempValue = MAX(m_Image[Row*Width+Col+2][Channel],TempValue);
9143 if (TempValue+Threshold<m_Image[Row*Width+Col][Channel]) {
9144 for (int c=0; c<4; c++) {
9145 if (Row > 1) {
9146 TempValue = MAX(m_Image[(Row-1)*Width+Col][c],TempValue);
9147 if (Col > 1) TempValue = MAX(m_Image[(Row-1)*Width+Col-1][c],TempValue);
9148 if (Col < Width-1) TempValue = MAX(m_Image[(Row-1)*Width+Col+1][c],TempValue);
9149 }
9150 if (Row < Height-1) {
9151 TempValue = MAX(m_Image[(Row+1)*Width+Col][c],TempValue);
9152 if (Col > 1) TempValue = MAX(m_Image[(Row+1)*Width+Col-1][c],TempValue);
9153 if (Col < Width-1) TempValue = MAX(m_Image[(Row+1)*Width+Col+1][c],TempValue);
9154 }
9155 if (Col > 1) TempValue = MAX(m_Image[Row*Width+Col-1][c],TempValue);
9156 if (Col < Width-1) TempValue = MAX(m_Image[Row*Width+Col+1][c],TempValue);
9157 }
9158 if (TempValue+Threshold<m_Image[Row*Width+Col][Channel])
9159 m_Image[Row*Width+Col][Channel] = TempValue;
9160 }
9161 }
9162 }
9163 for (int Channel=0; Channel<4; Channel++) {
9164 if (m_Image[Row*Width+Col][Channel] < 10*HotpixelThreshold) {
9165 TempValue = 0xffff;
9166 if (Row > 2) TempValue = MIN(m_Image[(Row-2)*Width+Col][Channel],TempValue);
9167 if (Row < Height-2) TempValue = MIN(m_Image[(Row+2)*Width+Col][Channel],TempValue);
9168 if (Col > 2) TempValue = MIN(m_Image[Row*Width+Col-2][Channel],TempValue);
9169 if (Col < Width-2) TempValue = MIN(m_Image[Row*Width+Col+2][Channel],TempValue);
9170 if (TempValue-Threshold>m_Image[Row*Width+Col][Channel]) {
9171 for (int c=0; c<4; c++) {
9172 if (Row > 1) {
9173 TempValue = MIN(m_Image[(Row-1)*Width+Col][c],TempValue);
9174 if (Col > 1) TempValue = MIN(m_Image[(Row-1)*Width+Col-1][c],TempValue);
9175 if (Col < Width-1) TempValue = MIN(m_Image[(Row-1)*Width+Col+1][c],TempValue);
9176 }
9177 if (Row < Height-1) {
9178 TempValue = MIN(m_Image[(Row+1)*Width+Col][c],TempValue);
9179 if (Col > 1) TempValue = MIN(m_Image[(Row+1)*Width+Col-1][c],TempValue);
9180 if (Col < Width-1) TempValue = MIN(m_Image[(Row+1)*Width+Col+1][c],TempValue);
9181 }
9182 if (Col > 1) TempValue = MIN(m_Image[Row*Width+Col-1][c],TempValue);
9183 if (Col < Width-1) TempValue = MIN(m_Image[Row*Width+Col+1][c],TempValue);
9184 }
9185 if (TempValue-Threshold>m_Image[Row*Width+Col][Channel])
9186 m_Image[Row*Width+Col][Channel] = TempValue;
9187 }
9188 }
9189 }
9190 }
9191 }
9192 }
9193
9194 ////////////////////////////////////////////////////////////////////////////////
9195 //
9196 // Crop for detail view
9197 //
9198 ////////////////////////////////////////////////////////////////////////////////
9199
MultOf6(uint16_t AValue)9200 inline uint16_t MultOf6(uint16_t AValue) {
9201 return ptMax(AValue - (AValue % 6), 0);
9202 }
9203
ptCrop()9204 void CLASS ptCrop() {
9205 assert (m_UserSetting_HalfSize == 0);
9206
9207 uint16_t (*TempImage)[4];
9208 uint16_t CropW = m_UserSetting_DetailViewCropW;
9209 uint16_t CropH = m_UserSetting_DetailViewCropH;
9210 uint16_t CropX = m_UserSetting_DetailViewCropX;
9211 uint16_t CropY = m_UserSetting_DetailViewCropY;
9212
9213 if (m_Filters == 2) { // for 3x3 pattern
9214 CropW = MultOf6(CropW);
9215 CropH = MultOf6(CropH);
9216 CropX = MultOf6(CropX);
9217 CropY = MultOf6(CropY);
9218 }
9219
9220 if (m_Flip & 2) {
9221 CropX = m_Height - CropX - CropW;
9222 }
9223 if (m_Flip & 1) {
9224 CropY = m_Width - CropY - CropH;
9225 }
9226 if (m_Flip & 4) {
9227 SWAP(CropW, CropH);
9228 SWAP(CropX, CropY);
9229 }
9230 m_OutHeight = CropH;
9231 m_OutWidth = CropW;
9232 TempImage = (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *TempImage);
9233 merror (TempImage, "Temp for detail view");
9234
9235 #pragma omp parallel for schedule(static)
9236 for (uint16_t row=0; row < m_OutHeight; row++) {
9237 for (uint16_t col=0; col < m_OutWidth; col++) {
9238 for (short c=0; c<4; c++) {
9239 TempImage[row *m_OutWidth + col][c] =
9240 m_Image[(row+CropY)*m_Width + (col+CropX)][c];
9241 }
9242 }
9243 }
9244
9245 m_Width = m_OutWidth;
9246 m_Height = m_OutHeight;
9247 FREE(m_Image);
9248 m_Image = TempImage;
9249 TRACEKEYVALS("Phase2 detail view Width","%d",m_Width);
9250 TRACEKEYVALS("Phase2 detail view Height","%d",m_Height);
9251 TRACEKEYVALS("Phase2 detail view OutWidth","%d",m_OutWidth);
9252 TRACEKEYVALS("Phase2 detail view OutHeight","%d",m_OutHeight);
9253 }
9254
9255 ////////////////////////////////////////////////////////////////////////////////
9256 //
9257 // MedianFilter
9258 // Repeatepty 3x3 median filter on R-G and B-G channels
9259 // Repeat : m_UserSetting_MedianPasses
9260 //
9261 ////////////////////////////////////////////////////////////////////////////////
9262
ptMedianFilter()9263 void CLASS ptMedianFilter() {
9264
9265 int Median[9];
9266 static const uint8_t opt[] = /* Optimal 9-element median search */
9267 { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8,
9268 0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 };
9269
9270 for (short Pass=1; Pass <= m_UserSetting_MedianPasses; Pass++) {
9271 for (short c=0; c < 3; c+=2) {
9272 #pragma omp parallel for schedule(static) default(shared)
9273 for (int32_t i = 0; i< (int32_t)m_Width*m_Height; i++) {
9274 m_Image[i][3] = m_Image[i][c];
9275 }
9276 #pragma omp parallel for schedule(static) default(shared) private(Median)
9277 for (int32_t n=m_Width; n<m_Width*(m_Height-1); n++) {
9278 if ((n+1) % m_Width < 2) continue;
9279 short k=0;
9280 for (int32_t i = -m_Width; i <= m_Width; i += m_Width) {
9281 for (int32_t j = i-1; j <= i+1; j++) {
9282 Median[k++] = m_Image[n+j][3] - m_Image[n+j][1];
9283 }
9284 }
9285 for (unsigned short i=0; i < sizeof opt; i+=2) {
9286 if (Median[opt[i]] > Median[opt[i+1]]) {
9287 SWAP (Median[opt[i]] , Median[opt[i+1]]);
9288 }
9289 }
9290 m_Image[n][c] = CLIP(Median[4] + m_Image[n][1]);
9291 }
9292 }
9293 }
9294 }
9295
9296 ////////////////////////////////////////////////////////////////////////////////
9297 //
9298 // WaveletDenoise
9299 // (original from dcraw TODO Refine and analyse)
9300 // Be aware :
9301 // Changes m_WhiteLevel
9302 // Changes m_Blacklevel
9303 //
9304 ////////////////////////////////////////////////////////////////////////////////
9305
ptWaveletDenoise()9306 void CLASS ptWaveletDenoise() {
9307 static const float Noise[] =
9308 { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
9309
9310 int Scale=1;
9311 int lev, hpass, lpass, wlast, blk[2];
9312
9313 TRACEKEYVALS("BlackLevel","%d",m_BlackLevel);
9314 TRACEKEYVALS("WhiteLevel","%d",m_WhiteLevel);
9315
9316 while (m_WhiteLevel << Scale < 0x10000) Scale++;
9317 m_WhiteLevel <<= --Scale;
9318 m_BlackLevel <<= Scale;
9319 for (int c=0; c<4; c++) m_CBlackLevel[c] <<= Scale;
9320
9321 TRACEKEYVALS("Scale(denoise)","%d",Scale);
9322 TRACEKEYVALS("BlackLevel","%d",m_BlackLevel);
9323 TRACEKEYVALS("WhiteLevel","%d",m_WhiteLevel);
9324
9325 uint32_t Size = m_OutHeight*m_OutWidth;
9326 float *fImage = (float*)
9327 MALLOC((Size*3 +m_OutHeight+ m_OutWidth)* sizeof(*fImage));
9328 merror(fImage,"WaveletDenoise()");
9329
9330 float* fTemp = fImage + Size*3;
9331 short NrColors = m_Colors;
9332 if (NrColors == 3 && m_Filters) NrColors++;
9333 for (short c=0; c<NrColors; c++) { /* deNoise R,G1,B,G3 individually */
9334 for (uint32_t i=0; i < Size; i++) {
9335 fImage[i] = 256 * sqrt((unsigned) (m_Image[i][c] << Scale));
9336 }
9337 for (hpass=lev=0; lev < 5; lev++) {
9338 lpass = Size*((lev & 1)+1);
9339 for (uint16_t Row=0; Row < m_OutHeight; Row++) {
9340 hat_transform(fTemp,fImage+hpass+Row*m_OutWidth,1,m_OutWidth,1<<lev);
9341 for (uint16_t Col=0; Col < m_OutWidth; Col++) {
9342 fImage[lpass + Row*m_OutWidth + Col] = fTemp[Col] * 0.25;
9343 }
9344 }
9345 for (uint16_t Col=0; Col < m_OutWidth; Col++) {
9346 hat_transform(fTemp,fImage+lpass+Col,m_OutWidth,m_OutHeight,1<<lev);
9347 for (uint16_t Row=0; Row < m_OutHeight; Row++) {
9348 fImage[lpass + Row*m_OutWidth + Col] = fTemp[Row] * 0.25;
9349 }
9350 }
9351 float Threshold = m_UserSetting_DenoiseThreshold * Noise[lev];
9352 for (uint32_t i=0; i < Size; i++) {
9353 fImage[hpass+i] -= fImage[lpass+i];
9354 if (fImage[hpass+i] < -Threshold) {
9355 fImage[hpass+i] += Threshold;
9356 } else if (fImage[hpass+i] > Threshold) {
9357 fImage[hpass+i] -= Threshold;
9358 } else {
9359 fImage[hpass+i] = 0;
9360 }
9361 if (hpass) {
9362 fImage[i] += fImage[hpass+i];
9363 }
9364 }
9365 hpass = lpass;
9366 }
9367 for (uint32_t i=0; i < Size; i++) {
9368 m_Image[i][c] = CLIP((int32_t)(SQR(fImage[i]+fImage[lpass+i])/0x10000));
9369 }
9370 }
9371 if (m_Filters && m_Colors == 3) { /* pull G1 and G3 closer together */
9372 float Multiplier[2];
9373 for (uint16_t Row=0; Row < 2; Row++) {
9374 Multiplier[Row] = 0.125 *
9375 VALUE(m_PreMultipliers[FC(Row+1,0) | 1]) /
9376 VALUE(m_PreMultipliers[FC(Row,0) | 1]);
9377 blk[Row] = m_CBlackLevel[FC(Row,0) | 1];
9378 }
9379 uint16_t* Window[4];
9380 for (short i=0; i < 4; i++) {
9381 Window[i] = (uint16_t *) fImage + m_Width*i;
9382 }
9383 wlast = -1;
9384 for (uint16_t Row=1; Row < m_Height-1; Row++) {
9385 while (wlast < Row+1) {
9386 wlast++;
9387 for (short i=0; i < 4; i++) {
9388 Window[(i+3) & 3] = Window[i];
9389 }
9390 for (uint16_t Col = FC(wlast,1) & 1; Col < m_Width; Col+=2) {
9391 Window[2][Col] = BAYER(wlast,Col);
9392 }
9393 }
9394 float Threshold = m_UserSetting_DenoiseThreshold/512;
9395 float Average;
9396 float Difference;
9397 for (uint16_t Col = (FC(Row,0) & 1)+1; Col < m_Width-1; Col+=2) {
9398 Average = ( Window[0][Col-1] + Window[0][Col+1] +
9399 Window[2][Col-1] + Window[2][Col+1] - blk[~Row & 1]*4 )
9400 * Multiplier[Row & 1]
9401 + (Window[1][Col] + blk[Row & 1]) * 0.5;
9402 Average = Average < 0 ? 0 : sqrt(Average);
9403 Difference = sqrt(BAYER(Row,Col)) - Average;
9404 if (Difference < -Threshold) {
9405 Difference += Threshold;
9406 } else if (Difference > Threshold) {
9407 Difference -= Threshold;
9408 } else {
9409 Difference = 0;
9410 }
9411 BAYER(Row,Col) = CLIP((int32_t)(SQR(Average+Difference) + 0.5));
9412 }
9413 }
9414 }
9415 FREE(fImage);
9416 }
9417
9418 ////////////////////////////////////////////////////////////////////////////////
9419 //
9420 // RebuildHighlights
9421 // (original from dcraw TODO Refine and analyse)
9422 //
9423 ////////////////////////////////////////////////////////////////////////////////
9424
9425 #define SCALE (4 >> m_Shrink)
ptRebuildHighlights(const short highlight)9426 void CLASS ptRebuildHighlights(const short highlight) {
9427 float *map, sum, wgt, grow;
9428 int hsat[4], count, spread, change, val, i;
9429 unsigned high, wide, mrow, mcol, row, col, d, y, x;
9430 uint16_t *pixel;
9431 static const signed char dir[8][2] =
9432 { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} };
9433
9434 grow = pow (2, 1-highlight);
9435 for (short c=0;c<m_Colors;c++) hsat[c] = (int)(32000 * VALUE(m_PreMultipliers[c]));
9436 short kc = 0;
9437 for (short c=1; c < m_Colors; c++)
9438 if (VALUE(m_PreMultipliers[kc]) < VALUE(m_PreMultipliers[c])) kc = c;
9439 high = m_Height / SCALE;
9440 wide = m_Width / SCALE;
9441 map = (float *) CALLOC (high*wide, sizeof *map);
9442 merror (map, "recover_highlights()");
9443 for (short c=0;c<m_Colors;c++) {
9444 if (c != kc) {
9445 memset (map, 0, high*wide*sizeof *map);
9446 #pragma omp parallel for schedule(static) private(mrow, mcol, sum, wgt, count, pixel, row, col)
9447 for (mrow=0; mrow < high; mrow++) {
9448 for (mcol=0; mcol < wide; mcol++) {
9449 sum = wgt = count = 0;
9450 for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) {
9451 for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
9452 pixel = m_Image[row*m_Width+col];
9453 if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) {
9454 sum += pixel[c];
9455 wgt += pixel[kc];
9456 count++;
9457 }
9458 }
9459 if (count == SCALE*SCALE) map[mrow*wide+mcol] = sum / wgt;
9460 }
9461 }
9462 }
9463 for (spread = (int)(32/grow); spread--; ) {
9464 #pragma omp parallel for schedule(static) private(mrow, mcol, sum, count, x, y, d)
9465 for (mrow=0; mrow < high; mrow++) {
9466 for (mcol=0; mcol < wide; mcol++) {
9467 if (map[mrow*wide+mcol]) continue;
9468 sum = count = 0;
9469 for (d=0; d < 8; d++) {
9470 y = mrow + dir[d][0];
9471 x = mcol + dir[d][1];
9472 if (y < high && x < wide && map[y*wide+x] > 0) {
9473 sum += (1 + (d & 1)) * map[y*wide+x];
9474 count += 1 + (d & 1);
9475 }
9476 }
9477 if (count > 3)
9478 map[mrow*wide+mcol] = - (sum+grow) / (count+grow);
9479 }
9480 }
9481 change = 0;
9482 #pragma omp parallel for schedule(static) private(i) reduction(||:change)
9483 for (i=0; i < (int)(high*wide); i++) {
9484 if (map[i] < 0) {
9485 map[i] = -map[i];
9486 change = 1;
9487 }
9488 }
9489 if (!change) break;
9490 }
9491 #pragma omp parallel for schedule(static) private(i)
9492 for (i=0; i < (int)(high*wide); i++) {
9493 if (map[i] == 0) map[i] = 1;
9494 }
9495 #pragma omp parallel for schedule(static) private(mrow, mcol, row, col, pixel, val)
9496 for (mrow=0; mrow < high; mrow++) {
9497 for (mcol=0; mcol < wide; mcol++) {
9498 for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) {
9499 for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
9500 pixel = m_Image[row*m_Width+col];
9501 if (pixel[c] / hsat[c] > 1) {
9502 val = (int)(pixel[kc] * map[mrow*wide+mcol]);
9503 if (pixel[c] < val) pixel[c] = CLIP(val);
9504 }
9505 }
9506 }
9507 }
9508 }
9509 }
9510 }
9511 FREE (map);
9512 }
9513 #undef SCALE
9514
9515 ////////////////////////////////////////////////////////////////////////////////
9516 //
9517 // LabToCam helper function.
9518 //
9519 // FIXME
9520 // At this moment this is verbatim copies of ptImage.cpp. Room for improvement.
9521 //
9522 ////////////////////////////////////////////////////////////////////////////////
9523
9524
LabToCam(double Lab[3],uint16_t Cam[4])9525 void CLASS LabToCam(double Lab[3],uint16_t Cam[4]) {
9526
9527 if(!ToCamFunctionInited) {
9528 for(short i=0;i<m_Colors;i++) {
9529 for (short j=0;j<3;j++) {
9530 MatrixXYZToCam[i][j] = 0.0;
9531 for (short k=0;k<3;k++) {
9532 MatrixXYZToCam[i][j] +=
9533 m_MatrixSRGBToCamRGB[i][k] * MatrixXYZToRGB[ptSpace_sRGB_D65][k][j];
9534 }
9535 }
9536 }
9537 ToCamFunctionInited = 1;
9538 }
9539
9540 double xyz[3];
9541 double fx,fy,fz;
9542 double xr,yr,zr;
9543 const double epsilon = 216.0/24389.0;
9544 const double kappa = 24389.0/27.0;
9545
9546 const double L = Lab[0];
9547 const double a = Lab[1];
9548 const double b = Lab[2];
9549
9550 const double Tmp1 = (L+16.0)/116.0;
9551
9552 yr = (L<=kappa*epsilon)?
9553 (L/kappa):(Tmp1*Tmp1*Tmp1);
9554 fy = (yr<=epsilon) ? ((kappa*yr+16.0)/116.0) : Tmp1;
9555 fz = fy - b/200.0;
9556 fx = a/500.0 + fy;
9557 const double fz3 = fz*fz*fz;
9558 const double fx3 = fx*fx*fx;
9559 zr = (fz3<=epsilon) ? ((116.0*fz-16.0)/kappa) : fz3;
9560 xr = (fx3<=epsilon) ? ((116.0*fx-16.0)/kappa) : fx3;
9561
9562 xyz[0] = xr*D65Reference[0]*65535.0 - 0.5;
9563 xyz[1] = yr*D65Reference[1]*65535.0 - 0.5;
9564 xyz[2] = zr*D65Reference[2]*65535.0 - 0.5;
9565
9566 // And finally to RGB via the matrix.
9567 for (short c=0; c<m_Colors; c++) {
9568 double Value = 0;
9569 Value += MatrixXYZToCam[c][0] * xyz[0];
9570 Value += MatrixXYZToCam[c][1] * xyz[1];
9571 Value += MatrixXYZToCam[c][2] * xyz[2];
9572 Cam[c] = (uint16_t) CLIP((int32_t)(Value));
9573 }
9574 }
9575
9576 ////////////////////////////////////////////////////////////////////////////////
9577 //
9578 // CamToLab helper function.
9579 //
9580 ////////////////////////////////////////////////////////////////////////////////
9581
9582
CamToLab(uint16_t Cam[4],double Lab[3])9583 void CLASS CamToLab(uint16_t Cam[4], double Lab[3]) {
9584
9585 // Initialize the lookup table for the RGB->LAB function
9586 // if this would be the first time.
9587 if (!ToLABFunctionInited) {
9588 // Remark : we extend the table well beyond r>1.0 for numerical
9589 // stability purposes. XYZ>1.0 occurs sometimes and this way
9590 // it stays stable (srgb->lab->srgb correct within 0.02%)
9591 for (uint32_t i=0; i<0x20000; i++) {
9592 double r = (double)(i) / 0xffff;
9593 ToLABFunctionTable[i] = r > 216.0/24389.0 ?
9594 pow(r,1/3.0) :
9595 (24389.0/27.0*r + 16.0)/116.0;
9596 }
9597 for(short i=0;i<3;i++) {
9598 for (short j=0;j<m_Colors;j++) {
9599 MatrixCamToXYZ[i][j] = 0.0;
9600 for (short k=0;k<3;k++) {
9601 MatrixCamToXYZ[i][j] +=
9602 MatrixRGBToXYZ[ptSpace_sRGB_D65][i][k] * m_MatrixCamRGBToSRGB[k][j];
9603 }
9604 }
9605 }
9606 ToLABFunctionInited = 1;
9607 }
9608
9609 // First go to XYZ
9610 double xyz[3] = {0.5,0.5,0.5};
9611 for (short Color = 0; Color < m_Colors; Color++) {
9612 xyz[0] += MatrixCamToXYZ[0][Color] * Cam[Color];
9613 xyz[1] += MatrixCamToXYZ[1][Color] * Cam[Color];
9614 xyz[2] += MatrixCamToXYZ[2][Color] * Cam[Color];
9615 }
9616
9617 // Reference White
9618 xyz[0] /= D65Reference[0];
9619 xyz[1] /= D65Reference[1];
9620 xyz[2] /= D65Reference[2];
9621
9622 // Then to Lab
9623 xyz[0] = ToLABFunctionTable[ (int32_t) MAX(0.0,xyz[0]) ];
9624 xyz[1] = ToLABFunctionTable[ (int32_t) MAX(0.0,xyz[1]) ];
9625 xyz[2] = ToLABFunctionTable[ (int32_t) MAX(0.0,xyz[2]) ];
9626
9627 // L in 0 , a in 1, b in 2
9628 Lab[0] = 116.0 * xyz[1] - 16.0;
9629 Lab[1] = 500.0*(xyz[0]-xyz[1]);
9630 Lab[2] = 200.0*(xyz[1]-xyz[2]);
9631 }
9632
9633 //==============================================================================
9634
thumbnail()9635 TImage8RawData ptDcRaw::thumbnail() {
9636 m_Thumb.clear();
9637
9638 if(m_InputFile && m_LoadRawFunction) {
9639 fseek (m_InputFile, m_ThumbOffset, SEEK_SET);
9640 (this->*m_WriteThumb)();
9641 }
9642
9643 return m_Thumb;
9644 }
9645
9646