2 GENERATED FILE, DO NOT EDIT
3 Generated from dcraw/dcraw.c at Sun Mar 15 13:33:56 2009
4 Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
5 for copyright information.
8 #line 3286 "dcraw/dcraw.c"
10 #include "libraw/libraw_types.h"
11 #define LIBRAW_IO_REDEFINED
12 #define LIBRAW_LIBRARY_BUILD
13 #include "libraw/libraw.h"
14 #include "internal/defines.h"
15 #define SRC_USES_SHRINK
16 #define SRC_USES_BLACK
17 #define SRC_USES_CURVE
18 #include "internal/var_defines.h"
19 #define sget4(s) sget4((uchar *)s)
20 #line 3299 "dcraw/dcraw.c"
22 /* RESTRICTED code starts here */
24 void CLASS
foveon_decoder (unsigned size
, unsigned code
)
26 #ifndef LIBRAW_NOTHREADS
27 #define huff tls->foveon_decoder_huff
29 static unsigned huff
[1024];
35 for (i
=0; i
< size
; i
++)
40 if (free_decode
> first_decode
+2048) {
41 #ifdef LIBRAW_LIBRARY_BUILD
42 throw LIBRAW_EXCEPTION_DECODE_RAW
;
44 fprintf (stderr
,_("%s: decoder table overflow\n"), ifname
);
49 for (i
=0; i
< size
; i
++)
50 if (huff
[i
] == code
) {
54 if ((len
= code
>> 27) > 26) return;
55 code
= (len
+1) << 27 | (code
& 0x3ffffff) << 1;
57 cur
->branch
[0] = free_decode
;
58 foveon_decoder (size
, code
);
59 cur
->branch
[1] = free_decode
;
60 foveon_decoder (size
, code
+1);
61 #ifndef LIBRAW_NOTHREADS
66 void CLASS
foveon_thumb (FILE *tfp
)
68 unsigned bwide
, row
, col
, bitbuf
=0, bit
=1, c
, i
;
70 struct decode
*dindex
;
74 fprintf (tfp
, "P6\n%d %d\n255\n", thumb_width
, thumb_height
);
76 if (bwide
< thumb_width
*3) return;
77 buf
= (char *) malloc (bwide
);
78 merror (buf
, "foveon_thumb()");
79 for (row
=0; row
< thumb_height
; row
++) {
80 fread (buf
, 1, bwide
, ifp
);
81 fwrite (buf
, 3, thumb_width
, tfp
);
86 foveon_decoder (256, 0);
88 for (row
=0; row
< thumb_height
; row
++) {
89 memset (pred
, 0, sizeof pred
);
91 for (bit
=col
=0; col
< thumb_width
; col
++)
93 for (dindex
=first_decode
; dindex
->branch
[0]; ) {
94 if ((bit
= (bit
-1) & 31) == 31)
96 bitbuf
= (bitbuf
<< 8) + fgetc(ifp
);
97 dindex
= dindex
->branch
[bitbuf
>> bit
& 1];
99 pred
[c
] += dindex
->leaf
;
100 fputc (pred
[c
], tfp
);
105 void CLASS
foveon_load_camf()
107 unsigned key
, i
, val
;
109 fseek (ifp
, meta_offset
, SEEK_SET
);
111 fread (meta_data
, 1, meta_length
, ifp
);
112 for (i
=0; i
< meta_length
; i
++) {
113 key
= (key
* 1597 + 51749) % 244944;
114 val
= key
* (INT64
) 301593171 >> 24;
115 meta_data
[i
] ^= ((((key
<< 8) - val
) >> 1) + val
) >> 17;
119 void CLASS
foveon_load_raw()
121 struct decode
*dindex
;
124 int pred
[3], fixed
, row
, col
, bit
=-1, c
, i
;
127 read_shorts ((ushort
*) diff
, 1024);
128 if (!fixed
) foveon_decoder (1024, 0);
130 for (row
=0; row
< height
; row
++) {
131 memset (pred
, 0, sizeof pred
);
132 if (!bit
&& !fixed
&& atoi(model
+2) < 14) get4();
133 for (col
=bit
=0; col
< width
; col
++) {
136 FORC3 pred
[2-c
] += diff
[bitbuf
>> c
*10 & 0x3ff];
139 for (dindex
=first_decode
; dindex
->branch
[0]; ) {
140 if ((bit
= (bit
-1) & 31) == 31)
141 for (i
=0; i
< 4; i
++)
142 bitbuf
= (bitbuf
<< 8) + fgetc(ifp
);
143 dindex
= dindex
->branch
[bitbuf
>> bit
& 1];
145 pred
[c
] += diff
[dindex
->leaf
];
146 if (pred
[c
] >> 16 && ~pred
[c
] >> 16) derror();
148 FORC3 image
[row
*width
+col
][c
] = pred
[c
];
152 for (i
=0; i
< height
*width
*4; i
++)
153 if ((short) image
[0][i
] < 0) image
[0][i
] = 0;
157 const char * CLASS
foveon_camf_param (const char *block
, const char *param
)
162 for (idx
=0; idx
< meta_length
; idx
+= sget4(pos
+8)) {
163 pos
= meta_data
+ idx
;
164 if (strncmp (pos
, "CMb", 3)) break;
165 if (pos
[3] != 'P') continue;
166 if (strcmp (block
, pos
+sget4(pos
+12))) continue;
167 cp
= pos
+ sget4(pos
+16);
169 dp
= pos
+ sget4(cp
+4);
172 if (!strcmp (param
, dp
+sget4(cp
)))
173 return dp
+sget4(cp
+4);
179 void * CLASS
foveon_camf_matrix (unsigned dim
[3], const char *name
)
181 unsigned i
, idx
, type
, ndim
, size
, *mat
;
185 for (idx
=0; idx
< meta_length
; idx
+= sget4(pos
+8)) {
186 pos
= meta_data
+ idx
;
187 if (strncmp (pos
, "CMb", 3)) break;
188 if (pos
[3] != 'M') continue;
189 if (strcmp (name
, pos
+sget4(pos
+12))) continue;
190 dim
[0] = dim
[1] = dim
[2] = 1;
191 cp
= pos
+ sget4(pos
+16);
193 if ((ndim
= sget4(cp
+4)) > 3) break;
194 dp
= pos
+ sget4(cp
+8);
195 for (i
=ndim
; i
--; ) {
199 if ((dsize
= (double) dim
[0]*dim
[1]*dim
[2]) > meta_length
/4) break;
200 mat
= (unsigned *) malloc ((size
= dsize
) * 4);
201 merror (mat
, "foveon_camf_matrix()");
202 for (i
=0; i
< size
; i
++)
203 if (type
&& type
!= 6)
204 mat
[i
] = sget4(dp
+ i
*4);
206 mat
[i
] = sget4(dp
+ i
*2) & 0xffff;
209 #ifdef LIBRAW_LIBRARY_BUILD
210 imgdata
.process_warnings
|= LIBRAW_WARN_FOVEON_NOMATRIX
;
213 fprintf (stderr
,_("%s: \"%s\" matrix not found!\n"), ifname
, name
);
218 int CLASS
foveon_fixed (void *ptr
, int size
, const char *name
)
223 dp
= foveon_camf_matrix (dim
, name
);
225 memcpy (ptr
, dp
, size
*4);
230 float CLASS
foveon_avg (short *pix
, int range
[2], float cfilt
)
233 float val
, min
=FLT_MAX
, max
=-FLT_MAX
, sum
=0;
235 for (i
=range
[0]; i
<= range
[1]; i
++) {
236 sum
+= val
= pix
[i
*4] + (pix
[i
*4]-pix
[(i
-1)*4]) * cfilt
;
237 if (min
> val
) min
= val
;
238 if (max
< val
) max
= val
;
240 if (range
[1] - range
[0] == 1) return sum
/2;
241 return (sum
- min
- max
) / (range
[1] - range
[0] - 1);
244 short * CLASS
foveon_make_curve (double max
, double mul
, double filt
)
250 if (!filt
) filt
= 0.8;
251 size
= 4*M_PI
*max
/ filt
;
252 if (size
== UINT_MAX
) size
--;
253 curve
= (short *) calloc (size
+1, sizeof *curve
);
254 merror (curve
, "foveon_make_curve()");
256 for (i
=0; i
< size
; i
++) {
258 curve
[i
+1] = (cos(x
)+1)/2 * tanh(i
*filt
/mul
) * mul
+ 0.5;
263 void CLASS foveon_make_curves
264 (short **curvep
, float dq
[3], float div
[3], float filt
)
266 double mul
[3], max
=0;
269 FORC3 mul
[c
] = dq
[c
]/div
[c
];
270 FORC3
if (max
< mul
[c
]) max
= mul
[c
];
271 FORC3 curvep
[c
] = foveon_make_curve (max
, mul
[c
], filt
);
274 int CLASS
foveon_apply_curve (short *curve
, int i
)
276 if (abs(i
) >= curve
[0]) return 0;
277 return i
< 0 ? -curve
[1-i
] : curve
[1+i
];
280 #line 3561 "dcraw/dcraw.c"
284 #define image ((short(*)[4]) imgdata.image)
285 #line 3568 "dcraw/dcraw.c"
287 void CLASS
foveon_interpolate()
289 static const short hood
[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 };
290 short *pix
, prev
[3], *curve
[8], (*shrink
)[3];
291 float cfilt
=0, ddft
[3][3][2], ppm
[3][3][3];
292 float cam_xyz
[3][3], correct
[3][3], last
[3][3], trans
[3][3];
293 float chroma_dq
[3], color_dq
[3], diag
[3][3], div
[3];
294 float (*black
)[3], (*sgain
)[3], (*sgrow
)[3];
295 float fsum
[3], val
, frow
, num
;
296 int row
, col
, c
, i
, j
, diff
, sgx
, irow
, sum
, min
, max
, limit
;
297 int dscr
[2][2], dstb
[4], (*smrow
[7])[3], total
[4], ipix
[3];
298 int work
[3][3], smlast
, smred
, smred_p
=0, dev
[3];
299 int satlev
[3], keep
[4], active
[4];
300 unsigned dim
[3], *badpix
;
301 double dsum
=0, trsum
[3];
308 fprintf(stderr
,_("Foveon interpolation...\n"));
310 #ifdef LIBRAW_LIBRARY_BUILD
311 RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
,0,9);
314 foveon_fixed (dscr
, 4, "DarkShieldColRange");
315 foveon_fixed (ppm
[0][0], 27, "PostPolyMatrix");
316 foveon_fixed (satlev
, 3, "SaturationLevel");
317 foveon_fixed (keep
, 4, "KeepImageArea");
318 foveon_fixed (active
, 4, "ActiveImageArea");
319 foveon_fixed (chroma_dq
, 3, "ChromaDQ");
320 foveon_fixed (color_dq
, 3,
321 foveon_camf_param ("IncludeBlocks", "ColorDQ") ?
322 "ColorDQ" : "ColorDQCamRGB");
323 if (foveon_camf_param ("IncludeBlocks", "ColumnFilter"))
324 foveon_fixed (&cfilt
, 1, "ColumnFilter");
326 memset (ddft
, 0, sizeof ddft
);
327 if (!foveon_camf_param ("IncludeBlocks", "DarkDrift")
328 || !foveon_fixed (ddft
[1][0], 12, "DarkDrift"))
329 for (i
=0; i
< 2; i
++) {
330 foveon_fixed (dstb
, 4, i
? "DarkShieldBottom":"DarkShieldTop");
331 for (row
= dstb
[1]; row
<= dstb
[3]; row
++)
332 for (col
= dstb
[0]; col
<= dstb
[2]; col
++)
333 FORC3 ddft
[i
+1][c
][1] += (short) image
[row
*width
+col
][c
];
334 FORC3 ddft
[i
+1][c
][1] /= (dstb
[3]-dstb
[1]+1) * (dstb
[2]-dstb
[0]+1);
337 if (!(cp
= foveon_camf_param ("WhiteBalanceIlluminants", model2
)))
340 fprintf (stderr
,_("%s: Invalid white balance \"%s\"\n"), ifname
, model2
);
342 #ifdef LIBRAW_LIBRARY_BUILD
343 imgdata
.process_warnings
|= LIBRAW_WARN_FOVEON_INVALIDWB
;
347 foveon_fixed (cam_xyz
, 9, cp
);
348 foveon_fixed (correct
, 9,
349 foveon_camf_param ("WhiteBalanceCorrections", model2
));
350 memset (last
, 0, sizeof last
);
351 for (i
=0; i
< 3; i
++)
352 for (j
=0; j
< 3; j
++)
353 FORC3 last
[i
][j
] += correct
[i
][c
] * cam_xyz
[c
][j
];
355 #define LAST(x,y) last[(i+x)%3][(c+y)%3]
356 for (i
=0; i
< 3; i
++)
357 FORC3 diag
[c
][i
] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1);
359 FORC3 div
[c
] = diag
[c
][0]*0.3127 + diag
[c
][1]*0.329 + diag
[c
][2]*0.3583;
360 sprintf (str
, "%sRGBNeutral", model2
);
361 if (foveon_camf_param ("IncludeBlocks", str
))
362 foveon_fixed (div
, 3, str
);
364 FORC3
if (num
< div
[c
]) num
= div
[c
];
367 memset (trans
, 0, sizeof trans
);
368 for (i
=0; i
< 3; i
++)
369 for (j
=0; j
< 3; j
++)
370 FORC3 trans
[i
][j
] += rgb_cam
[i
][c
] * last
[c
][j
] * div
[j
];
371 FORC3 trsum
[c
] = trans
[c
][0] + trans
[c
][1] + trans
[c
][2];
372 dsum
= (6*trsum
[0] + 11*trsum
[1] + 3*trsum
[2]) / 20;
373 for (i
=0; i
< 3; i
++)
374 FORC3 last
[i
][c
] = trans
[i
][c
] * dsum
/ trsum
[i
];
375 memset (trans
, 0, sizeof trans
);
376 for (i
=0; i
< 3; i
++)
377 for (j
=0; j
< 3; j
++)
378 FORC3 trans
[i
][j
] += (i
==c
? 32 : -1) * last
[c
][j
] / 30;
380 foveon_make_curves (curve
, color_dq
, div
, cfilt
);
381 FORC3 chroma_dq
[c
] /= 3;
382 foveon_make_curves (curve
+3, chroma_dq
, div
, cfilt
);
383 FORC3 dsum
+= chroma_dq
[c
] / div
[c
];
384 curve
[6] = foveon_make_curve (dsum
, dsum
, cfilt
);
385 curve
[7] = foveon_make_curve (dsum
*2, dsum
*2, cfilt
);
387 sgain
= (float (*)[3]) foveon_camf_matrix (dim
, "SpatialGain");
389 sgrow
= (float (*)[3]) calloc (dim
[1], sizeof *sgrow
);
390 sgx
= (width
+ dim
[1]-2) / (dim
[1]-1);
392 black
= (float (*)[3]) calloc (height
, sizeof *black
);
393 #ifdef LIBRAW_LIBRARY_BUILD
394 RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
,1,9);
396 for (row
=0; row
< height
; row
++) {
397 for (i
=0; i
< 6; i
++)
398 ddft
[0][0][i
] = ddft
[1][0][i
] +
399 row
/ (height
-1.0) * (ddft
[2][0][i
] - ddft
[1][0][i
]);
400 FORC3 black
[row
][c
] =
401 ( foveon_avg (image
[row
*width
]+c
, dscr
[0], cfilt
) +
402 foveon_avg (image
[row
*width
]+c
, dscr
[1], cfilt
) * 3
403 - ddft
[0][c
][0] ) / 4 - ddft
[0][c
][1];
405 memcpy (black
, black
+8, sizeof *black
*8);
406 memcpy (black
+height
-11, black
+height
-22, 11*sizeof *black
);
407 memcpy (last
, black
, sizeof last
);
409 for (row
=1; row
< height
-1; row
++) {
410 FORC3
if (last
[1][c
] > last
[0][c
]) {
411 if (last
[1][c
] > last
[2][c
])
412 black
[row
][c
] = (last
[0][c
] > last
[2][c
]) ? last
[0][c
]:last
[2][c
];
414 if (last
[1][c
] < last
[2][c
])
415 black
[row
][c
] = (last
[0][c
] < last
[2][c
]) ? last
[0][c
]:last
[2][c
];
416 memmove (last
, last
+1, 2*sizeof last
[0]);
417 memcpy (last
[2], black
[row
+1], sizeof last
[2]);
419 FORC3 black
[row
][c
] = (last
[0][c
] + last
[1][c
])/2;
420 FORC3 black
[0][c
] = (black
[1][c
] + black
[3][c
])/2;
422 val
= 1 - exp(-1/24.0);
423 memcpy (fsum
, black
, sizeof fsum
);
424 for (row
=1; row
< height
; row
++)
425 FORC3 fsum
[c
] += black
[row
][c
] =
426 (black
[row
][c
] - black
[row
-1][c
])*val
+ black
[row
-1][c
];
427 memcpy (last
[0], black
[height
-1], sizeof last
[0]);
428 FORC3 fsum
[c
] /= height
;
429 for (row
= height
; row
--; )
430 FORC3 last
[0][c
] = black
[row
][c
] =
431 (black
[row
][c
] - fsum
[c
] - last
[0][c
])*val
+ last
[0][c
];
433 memset (total
, 0, sizeof total
);
434 for (row
=2; row
< height
; row
+=4)
435 for (col
=2; col
< width
; col
+=4) {
436 FORC3 total
[c
] += (short) image
[row
*width
+col
][c
];
439 for (row
=0; row
< height
; row
++)
440 FORC3 black
[row
][c
] += fsum
[c
]/2 + total
[c
]/(total
[3]*100.0);
442 #ifdef LIBRAW_LIBRARY_BUILD
443 RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
,2,9);
445 for (row
=0; row
< height
; row
++) {
446 for (i
=0; i
< 6; i
++)
447 ddft
[0][0][i
] = ddft
[1][0][i
] +
448 row
/ (height
-1.0) * (ddft
[2][0][i
] - ddft
[1][0][i
]);
449 pix
= image
[row
*width
];
450 memcpy (prev
, pix
, sizeof prev
);
451 frow
= row
/ (height
-1.0) * (dim
[2]-1);
452 if ((irow
= frow
) == dim
[2]-1) irow
--;
454 for (i
=0; i
< dim
[1]; i
++)
455 FORC3 sgrow
[i
][c
] = sgain
[ irow
*dim
[1]+i
][c
] * (1-frow
) +
456 sgain
[(irow
+1)*dim
[1]+i
][c
] * frow
;
457 for (col
=0; col
< width
; col
++) {
459 diff
= pix
[c
] - prev
[c
];
461 ipix
[c
] = pix
[c
] + floor ((diff
+ (diff
*diff
>> 14)) * cfilt
462 - ddft
[0][c
][1] - ddft
[0][c
][0] * ((float) col
/width
- 0.5)
466 work
[0][c
] = ipix
[c
] * ipix
[c
] >> 14;
467 work
[2][c
] = ipix
[c
] * work
[0][c
] >> 14;
468 work
[1][2-c
] = ipix
[(c
+1) % 3] * ipix
[(c
+2) % 3] >> 14;
471 for (val
=i
=0; i
< 3; i
++)
472 for ( j
=0; j
< 3; j
++)
473 val
+= ppm
[c
][i
][j
] * work
[i
][j
];
474 ipix
[c
] = floor ((ipix
[c
] + floor(val
)) *
475 ( sgrow
[col
/sgx
][c
] * (sgx
- col
%sgx
) +
476 sgrow
[col
/sgx
+1][c
] * (col
%sgx
) ) / sgx
/ div
[c
]);
477 if (ipix
[c
] > 32000) ipix
[c
] = 32000;
487 #ifdef LIBRAW_LIBRARY_BUILD
488 RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
,3,9);
490 if ((badpix
= (unsigned int *) foveon_camf_matrix (dim
, "BadPixels"))) {
491 for (i
=0; i
< dim
[0]; i
++) {
492 col
= (badpix
[i
] >> 8 & 0xfff) - keep
[0];
493 row
= (badpix
[i
] >> 20 ) - keep
[1];
494 if ((unsigned)(row
-1) > height
-3 || (unsigned)(col
-1) > width
-3)
496 memset (fsum
, 0, sizeof fsum
);
497 for (sum
=j
=0; j
< 8; j
++)
498 if (badpix
[i
] & (1 << j
)) {
499 FORC3 fsum
[c
] += (short)
500 image
[(row
+hood
[j
*2])*width
+col
+hood
[j
*2+1]][c
];
503 if (sum
) FORC3 image
[row
*width
+col
][c
] = fsum
[c
]/sum
;
508 /* Array for 5x5 Gaussian averaging of red values */
509 smrow
[6] = (int (*)[3]) calloc (width
*5, sizeof **smrow
);
510 merror (smrow
[6], "foveon_interpolate()");
511 for (i
=0; i
< 5; i
++)
512 smrow
[i
] = smrow
[6] + i
*width
;
514 /* Sharpen the reds against these Gaussian averages */
515 for (smlast
=-1, row
=2; row
< height
-2; row
++) {
516 while (smlast
< row
+2) {
517 for (i
=0; i
< 6; i
++)
518 smrow
[(i
+5) % 6] = smrow
[i
];
519 pix
= image
[++smlast
*width
+2];
520 for (col
=2; col
< width
-2; col
++) {
522 (pix
[0]*6 + (pix
[-4]+pix
[4])*4 + pix
[-8]+pix
[8] + 8) >> 4;
526 pix
= image
[row
*width
+2];
527 for (col
=2; col
< width
-2; col
++) {
528 smred
= ( 6 * smrow
[2][col
][0]
529 + 4 * (smrow
[1][col
][0] + smrow
[3][col
][0])
530 + smrow
[0][col
][0] + smrow
[4][col
][0] + 8 ) >> 4;
533 i
= pix
[0] + ((pix
[0] - ((smred
*7 + smred_p
) >> 3)) >> 3);
534 if (i
> 32000) i
= 32000;
541 #ifdef LIBRAW_LIBRARY_BUILD
542 RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
,4,9);
544 /* Adjust the brighter pixels for better linearity */
547 i
= satlev
[c
] / div
[c
];
548 if (min
> i
) min
= i
;
550 limit
= min
* 9 >> 4;
551 for (pix
=image
[0]; pix
< image
[height
*width
]; pix
+=4) {
552 if (pix
[0] <= limit
|| pix
[1] <= limit
|| pix
[2] <= limit
)
555 for (c
=1; c
< 3; c
++) {
556 if (min
> pix
[c
]) min
= pix
[c
];
557 if (max
< pix
[c
]) max
= pix
[c
];
559 if (min
>= limit
*2) {
560 pix
[0] = pix
[1] = pix
[2] = max
;
562 i
= 0x4000 - ((min
- limit
) << 14) / limit
;
563 i
= 0x4000 - (i
*i
>> 14);
565 FORC3 pix
[c
] += (max
- pix
[c
]) * i
>> 14;
569 Because photons that miss one detector often hit another,
570 the sum R+G+B is much less noisy than the individual colors.
571 So smooth the hues without smoothing the total.
573 #ifdef LIBRAW_LIBRARY_BUILD
574 RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
,5,9);
576 for (smlast
=-1, row
=2; row
< height
-2; row
++) {
577 while (smlast
< row
+2) {
578 for (i
=0; i
< 6; i
++)
579 smrow
[(i
+5) % 6] = smrow
[i
];
580 pix
= image
[++smlast
*width
+2];
581 for (col
=2; col
< width
-2; col
++) {
582 FORC3 smrow
[4][col
][c
] = (pix
[c
-4]+2*pix
[c
]+pix
[c
+4]+2) >> 2;
586 pix
= image
[row
*width
+2];
587 for (col
=2; col
< width
-2; col
++) {
588 FORC3 dev
[c
] = -foveon_apply_curve (curve
[7], pix
[c
] -
589 ((smrow
[1][col
][c
] + 2*smrow
[2][col
][c
] + smrow
[3][col
][c
]) >> 2));
590 sum
= (dev
[0] + dev
[1] + dev
[2]) >> 3;
591 FORC3 pix
[c
] += dev
[c
] - sum
;
595 for (smlast
=-1, row
=2; row
< height
-2; row
++) {
596 while (smlast
< row
+2) {
597 for (i
=0; i
< 6; i
++)
598 smrow
[(i
+5) % 6] = smrow
[i
];
599 pix
= image
[++smlast
*width
+2];
600 for (col
=2; col
< width
-2; col
++) {
601 FORC3 smrow
[4][col
][c
] =
602 (pix
[c
-8]+pix
[c
-4]+pix
[c
]+pix
[c
+4]+pix
[c
+8]+2) >> 2;
606 pix
= image
[row
*width
+2];
607 for (col
=2; col
< width
-2; col
++) {
608 for (total
[3]=375, sum
=60, c
=0; c
< 3; c
++) {
609 for (total
[c
]=i
=0; i
< 5; i
++)
610 total
[c
] += smrow
[i
][col
][c
];
611 total
[3] += total
[c
];
614 if (sum
< 0) sum
= 0;
615 j
= total
[3] > 375 ? (sum
<< 16) / total
[3] : sum
* 174;
616 FORC3 pix
[c
] += foveon_apply_curve (curve
[6],
617 ((j
*total
[c
] + 0x8000) >> 16) - pix
[c
]);
622 #ifdef LIBRAW_LIBRARY_BUILD
623 RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
,6,9);
625 /* Transform the image to a different colorspace */
626 for (pix
=image
[0]; pix
< image
[height
*width
]; pix
+=4) {
627 FORC3 pix
[c
] -= foveon_apply_curve (curve
[c
], pix
[c
]);
628 sum
= (pix
[0]+pix
[1]+pix
[1]+pix
[2]) >> 2;
629 FORC3 pix
[c
] -= foveon_apply_curve (curve
[c
], pix
[c
]-sum
);
631 for (dsum
=i
=0; i
< 3; i
++)
632 dsum
+= trans
[c
][i
] * pix
[i
];
633 if (dsum
< 0) dsum
= 0;
634 if (dsum
> 24000) dsum
= 24000;
635 ipix
[c
] = dsum
+ 0.5;
637 FORC3 pix
[c
] = ipix
[c
];
640 /* Smooth the image bottom-to-top and save at 1/4 scale */
641 shrink
= (short (*)[3]) calloc ((width
/4) * (height
/4), sizeof *shrink
);
642 merror (shrink
, "foveon_interpolate()");
643 for (row
= height
/4; row
--; )
644 for (col
=0; col
< width
/4; col
++) {
645 ipix
[0] = ipix
[1] = ipix
[2] = 0;
646 for (i
=0; i
< 4; i
++)
647 for (j
=0; j
< 4; j
++)
648 FORC3 ipix
[c
] += image
[(row
*4+i
)*width
+col
*4+j
][c
];
650 if (row
+2 > height
/4)
651 shrink
[row
*(width
/4)+col
][c
] = ipix
[c
] >> 4;
653 shrink
[row
*(width
/4)+col
][c
] =
654 (shrink
[(row
+1)*(width
/4)+col
][c
]*1840 + ipix
[c
]*141 + 2048) >> 12;
656 /* From the 1/4-scale image, smooth right-to-left */
657 #ifdef LIBRAW_LIBRARY_BUILD
658 RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
,7,9);
660 for (row
=0; row
< (height
& ~3); row
++) {
661 ipix
[0] = ipix
[1] = ipix
[2] = 0;
663 for (col
= width
& ~3 ; col
--; )
664 FORC3 smrow
[0][col
][c
] = ipix
[c
] =
665 (shrink
[(row
/4)*(width
/4)+col
/4][c
]*1485 + ipix
[c
]*6707 + 4096) >> 13;
667 /* Then smooth left-to-right */
668 ipix
[0] = ipix
[1] = ipix
[2] = 0;
669 for (col
=0; col
< (width
& ~3); col
++)
670 FORC3 smrow
[1][col
][c
] = ipix
[c
] =
671 (smrow
[0][col
][c
]*1485 + ipix
[c
]*6707 + 4096) >> 13;
673 /* Smooth top-to-bottom */
675 memcpy (smrow
[2], smrow
[1], sizeof **smrow
* width
);
677 for (col
=0; col
< (width
& ~3); col
++)
678 FORC3 smrow
[2][col
][c
] =
679 (smrow
[2][col
][c
]*6707 + smrow
[1][col
][c
]*1485 + 4096) >> 13;
681 /* Adjust the chroma toward the smooth values */
682 for (col
=0; col
< (width
& ~3); col
++) {
683 for (i
=j
=30, c
=0; c
< 3; c
++) {
684 i
+= smrow
[2][col
][c
];
685 j
+= image
[row
*width
+col
][c
];
688 for (sum
=c
=0; c
< 3; c
++) {
689 ipix
[c
] = foveon_apply_curve (curve
[c
+3],
690 ((smrow
[2][col
][c
] * j
+ 0x8000) >> 16) - image
[row
*width
+col
][c
]);
695 i
= image
[row
*width
+col
][c
] + ipix
[c
] - sum
;
697 image
[row
*width
+col
][c
] = i
;
703 for (i
=0; i
< 8; i
++)
705 #ifdef LIBRAW_LIBRARY_BUILD
706 RUN_CALLBACK(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
,8,9);
709 /* Trim off the black border */
710 active
[1] -= keep
[1];
712 i
= active
[2] - active
[0];
713 for (row
=0; row
< active
[3]-active
[1]; row
++)
714 memcpy (image
[row
*i
], image
[(row
+active
[1])*width
+active
[0]],
721 /* RESTRICTED code ends here */
722 #line 7128 "dcraw/dcraw.c"
723 char * CLASS
foveon_gets (int offset
, char *str
, int len
)
726 fseek (ifp
, offset
, SEEK_SET
);
727 for (i
=0; i
< len
-1; i
++)
728 if ((str
[i
] = get2()) == 0) break;
733 void CLASS
parse_foveon()
735 int entries
, img
=0, off
, len
, tag
, save
, i
, wide
, high
, pent
, poff
[256][2];
736 char name
[64], value
[64];
738 order
= 0x4949; /* Little-endian */
739 fseek (ifp
, 36, SEEK_SET
);
741 fseek (ifp
, -4, SEEK_END
);
742 fseek (ifp
, get4(), SEEK_SET
);
743 if (get4() != 0x64434553) return; /* SECd */
744 entries
= (get4(),get4());
750 fseek (ifp
, off
, SEEK_SET
);
751 if (get4() != (0x20434553 | (tag
<< 24))) return;
753 case 0x47414d49: /* IMAG */
754 case 0x32414d49: /* IMA2 */
755 fseek (ifp
, 12, SEEK_CUR
);
758 if (wide
> raw_width
&& high
> raw_height
) {
761 data_offset
= off
+24;
763 fseek (ifp
, off
+28, SEEK_SET
);
764 if (fgetc(ifp
) == 0xff && fgetc(ifp
) == 0xd8
765 && thumb_length
< len
-28) {
766 thumb_offset
= off
+28;
767 thumb_length
= len
-28;
768 write_thumb
= &CLASS jpeg_thumb
;
770 if (++img
== 2 && !thumb_length
) {
771 thumb_offset
= off
+24;
774 write_thumb
= &CLASS foveon_thumb
;
777 case 0x464d4143: /* CAMF */
778 meta_offset
= off
+24;
779 meta_length
= len
-28;
780 if (meta_length
> 0x20000)
781 meta_length
= 0x20000;
783 case 0x504f5250: /* PROP */
784 pent
= (get4(),get4());
785 fseek (ifp
, 12, SEEK_CUR
);
787 if ((unsigned) pent
> 256) pent
=256;
788 for (i
=0; i
< pent
*2; i
++)
789 poff
[0][i
] = off
+ get4()*2;
790 for (i
=0; i
< pent
; i
++) {
791 foveon_gets (poff
[i
][0], name
, 64);
792 foveon_gets (poff
[i
][1], value
, 64);
793 if (!strcmp (name
, "ISO"))
794 iso_speed
= atoi(value
);
795 if (!strcmp (name
, "CAMMANUF"))
796 strcpy (make
, value
);
797 if (!strcmp (name
, "CAMMODEL"))
798 strcpy (model
, value
);
799 if (!strcmp (name
, "WB_DESC"))
800 strcpy (model2
, value
);
801 if (!strcmp (name
, "TIME"))
802 timestamp
= atoi(value
);
803 if (!strcmp (name
, "EXPTIME"))
804 shutter
= atoi(value
) / 1000000.0;
805 if (!strcmp (name
, "APERTURE"))
806 aperture
= atof(value
);
807 if (!strcmp (name
, "FLENGTH"))
808 focal_len
= atof(value
);
811 timestamp
= mktime (gmtime (×tamp
));
814 fseek (ifp
, save
, SEEK_SET
);