2 * Copyright 2007-2008, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
5 * Copyright 1997-2007, Dave Coffin, dcoffin a cybercom o net
6 * This code is based on Dave Coffin's dcraw 8.63 - it's basically the same
7 * thing in C++, but follows common sense programming rules a bit more :-)
8 * Except the Fovean functions, dcraw is public domain.
13 #include "ReadHelper.h"
16 #include <TranslationErrors.h>
25 //#define TRACE(x) printf x
27 //#define TAG(x...) printf(x)
30 #define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
31 #define LIM(x,min,max) MAX(min,MIN(x,max))
32 #define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
33 #define CLIP(x) LIM(x,0,65535)
34 #define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
37 (fFilters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
40 static const uint32 kImageBufferCount
= 10;
41 static const uint32 kDecodeBufferCount
= 2048;
43 const double xyz_rgb
[3][3] = { /* XYZ from RGB */
44 { 0.412453, 0.357580, 0.180423 },
45 { 0.212671, 0.715160, 0.072169 },
46 { 0.019334, 0.119193, 0.950227 } };
47 const float kD65White
[3] = { 0.950456, 1, 1.088754 };
50 struct decode
*branch
[2];
55 int bits
, high
, wide
, clrs
, restart
, vpred
[4];
56 struct decode
*huff
[4];
62 int32 image_file_directory
;
64 struct tiff_tag tag
[15];
65 int32 next_image_file_directory
;
67 struct tiff_tag exif
[4];
70 char make
[64], model
[64], soft
[32], date
[20];
74 template<class T
> inline T
75 square(const T
& value
)
82 x_flipped(int32 orientation
)
84 return orientation
== 2 || orientation
== 3
85 || orientation
== 7 || orientation
== 8;
90 y_flipped(int32 orientation
)
92 return orientation
== 3 || orientation
== 4
93 || orientation
== 6 || orientation
== 7;
99 dump_to_disk(void* data
, size_t length
)
101 FILE* file
= fopen("/tmp/RAW.out", "wb");
105 fwrite(data
, length
, 1, file
);
114 DCRaw::DCRaw(BPositionIO
& stream
)
125 fUseCameraWhiteBalance(true),
126 fUseAutoWhiteBalance(true),
140 fOutputProfile(NULL
),
141 fOutputBitsPerSample(8),
143 fDecodeBitsZeroAfterMax(false),
146 fProgressMonitor(NULL
)
148 fImages
= new image_data_info
[kImageBufferCount
];
149 fDecodeBuffer
= new decode
[kDecodeBufferCount
];
150 fCurve
= new uint16
[0x1000];
151 for (uint32 i
= 0; i
< 0x1000; i
++) {
155 cbrt
= new float[0x10000];
156 fHistogram
= (int32 (*)[4])calloc(sizeof(int32
) * 0x2000 * 4, 1);
158 memset(fImages
, 0, sizeof(image_data_info
) * kImageBufferCount
);
159 memset(&fMeta
, 0, sizeof(image_meta_info
));
160 memset(fUserMultipliers
, 0, sizeof(fUserMultipliers
));
161 memset(fWhite
, 0, sizeof(fWhite
));
163 fMeta
.camera_multipliers
[0] = -1;
171 delete[] fDecodeBuffer
;
182 DCRaw::_AllocateImage()
184 if (fNumImages
+ 1 == kImageBufferCount
)
185 throw (status_t
)B_ERROR
;
195 fRawIndex
= _AllocateImage();
197 throw (status_t
)B_ERROR
;
199 return fImages
[fRawIndex
];
207 fThumbIndex
= _AllocateImage();
209 throw (status_t
)B_ERROR
;
211 return fImages
[fThumbIndex
];
215 //! Make sure that the raw image always comes first
217 DCRaw::_CorrectIndex(uint32
& index
) const
222 else if (index
<= (uint32
)fRawIndex
)
229 DCRaw::_Bayer(int32 column
, int32 row
)
231 return fImageData
[((row
) >> fShrink
) * fOutputWidth
232 + ((column
) >> fShrink
)][FC(row
, column
)];
237 DCRaw::_FilterCoefficient(int32 x
, int32 y
)
239 static const char filter
[16][16] = {
240 { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
241 { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
242 { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
243 { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
244 { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
245 { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
246 { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
247 { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
248 { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
249 { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
250 { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
251 { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
252 { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
253 { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
254 { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
255 { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 }
261 return filter
[(y
+ fTopMargin
) & 15][(x
+ fLeftMargin
) & 15];
266 DCRaw::_FlipIndex(uint32 row
, uint32 col
, uint32 flip
)
271 row
= fInputHeight
- 1 - row
;
273 col
= fInputWidth
- 1 - col
;
275 return row
* fInputWidth
+ col
;
280 DCRaw::_SupportsCompression(image_data_info
& image
) const
282 switch (image
.compression
) {
283 //case COMPRESSION_NONE:
284 case COMPRESSION_OLD_JPEG
:
285 case COMPRESSION_PACKBITS
:
295 DCRaw::_IsCanon() const
297 return !strncasecmp(fMeta
.manufacturer
, "Canon", 5);
302 DCRaw::_IsKodak() const
304 return !strncasecmp(fMeta
.manufacturer
, "Kodak", 5);
309 DCRaw::_IsNikon() const
311 return !strncasecmp(fMeta
.manufacturer
, "Nikon", 5);
316 DCRaw::_IsOlympus() const
318 return !strncasecmp(fMeta
.manufacturer
, "Olympus", 7);
323 DCRaw::_IsPentax() const
325 return !strncasecmp(fMeta
.manufacturer
, "Pentax", 6);
330 DCRaw::_IsSamsung() const
332 return !strncasecmp(fMeta
.manufacturer
, "Samsung", 7);
337 DCRaw::_ParseThumbTag(off_t baseOffset
, uint32 offsetTag
, uint32 lengthTag
)
345 _ParseTIFFTag(baseOffset
, tag
, nextOffset
);
347 if (tag
.tag
== offsetTag
)
348 _Thumb().data_offset
= fRead
.Next
<uint32
>();
349 if (tag
.tag
== lengthTag
)
350 _Thumb().bytes
= fRead
.Next
<uint32
>();
352 fRead
.Seek(nextOffset
, SEEK_SET
);
358 DCRaw::_ParseManufacturerTag(off_t baseOffset
)
360 static const uchar xlat
[2][256] = {
362 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
363 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
364 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
365 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
366 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
367 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
368 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
369 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
370 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
371 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
372 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
373 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
374 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
375 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
376 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
377 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7
380 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
381 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
382 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
383 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
384 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
385 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
386 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
387 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
388 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
389 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
390 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
391 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
392 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
393 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
394 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
395 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f
399 uint32 ver97
= 0, serial
= 0;
400 uchar buf97
[324], ci
, cj
, ck
;
401 bool originalSwap
= fRead
.IsSwapping();
402 image_data_info
& image
= fImages
[fNumImages
];
404 // The MakerNote might have its own TIFF header (possibly with
405 // its own byte-order!), or it might just be a table.
408 fRead(type
, sizeof(type
));
410 if (!strncmp(type
, "KDK", 3)
411 || !strncmp(type
, "VER", 3)
412 || !strncmp(type
, "IIII", 4)
413 || !strncmp(type
, "MMMM", 4)) {
414 // these aren't TIFF tables
417 if (!strncmp(type
, "KC", 2) // Konica KD-400Z, KD-510Z
418 || !strncmp(type
, "MLY", 3)) { // Minolta DiMAGE G series
419 fRead
.SetSwap(B_HOST_IS_LENDIAN
!= 0);
420 // this chunk is always in big endian
422 uint32 whiteBalance
[4] = {0, 0, 0, 0};
425 while ((offset
= fRead
.Position()) < image
.data_offset
427 whiteBalance
[0] = whiteBalance
[2];
428 whiteBalance
[2] = whiteBalance
[1];
429 whiteBalance
[1] = whiteBalance
[3];
431 whiteBalance
[3] = fRead
.Next
<uint16
>();
432 if (whiteBalance
[1] == 256 && whiteBalance
[3] == 256
433 && whiteBalance
[0] > 256 && whiteBalance
[0] < 640
434 && whiteBalance
[2] > 256 && whiteBalance
[2] < 640) {
435 for (uint32 i
= 0; i
< 4; i
++) {
436 fMeta
.camera_multipliers
[i
] = whiteBalance
[i
];
442 if (!strcmp(type
, "Nikon")) {
443 baseOffset
= fRead
.Position();
448 #if B_HOST_IS_LENDIAN
449 fRead
.SetSwap(endian
== 'MM');
451 fRead
.SetSwap(endian
== 'II');
454 if (fRead
.Next
<uint16
>() != 42)
457 uint32 offset
= fRead
.Next
<uint32
>();
458 fRead
.Seek(offset
- 8, SEEK_CUR
);
459 } else if (!strncmp(type
, "FUJIFILM", 8)
460 || !strncmp(type
, "SONY", 4)
461 || !strcmp(type
, "Panasonic")) {
462 fRead
.SetSwap(B_HOST_IS_BENDIAN
!= 0);
463 // this chunk is always in little endian
464 fRead
.Seek(2, SEEK_CUR
);
465 } else if (!strcmp(type
, "OLYMP")
466 || !strcmp(type
, "LEICA")
467 || !strcmp(type
, "Ricoh")
468 || !strcmp(type
, "EPSON"))
469 fRead
.Seek(-2, SEEK_CUR
);
470 else if (!strcmp(type
, "AOC") || !strcmp(type
, "QVC"))
471 fRead
.Seek(-4, SEEK_CUR
);
473 fRead
.Seek(-10, SEEK_CUR
);
483 _ParseTIFFTag(baseOffset
, tag
, nextOffset
);
484 TAG("Manufacturer tag %u (type %u, length %lu)\n", tag
.tag
, tag
.type
,
487 if (strstr(fMeta
.manufacturer
, "PENTAX")) {
492 } else if (tag
.tag
== 2 && strstr(fMeta
.manufacturer
, "NIKON")) {
493 fRead
.Next
<uint16
>();
495 fMeta
.iso_speed
= fRead
.Next
<uint16
>();
498 if (tag
.tag
== 4 && tag
.length
== 27) {
499 fRead
.Next
<uint32
>();
501 fMeta
.iso_speed
= 50 * pow(2, fRead
.Next
<uint16
>() / 32.0 - 4);
502 fRead
.Next
<uint16
>();
504 fMeta
.aperture
= pow(2, fRead
.Next
<uint16
>() / 64.0);
505 fMeta
.shutter
= pow(2, fRead
.Next
<int16
>() / -32.0);
507 if (tag
.tag
== 8 && tag
.type
== 4)
508 fMeta
.shot_order
= fRead
.Next
<uint32
>();
509 if (tag
.tag
== 0xc && tag
.length
== 4) {
510 fMeta
.camera_multipliers
[0] = fRead
.NextDouble(TIFF_FRACTION_TYPE
);
511 fMeta
.camera_multipliers
[2] = fRead
.NextDouble(TIFF_FRACTION_TYPE
);
513 if (tag
.tag
== 0x10 && tag
.type
== 4)
514 fUniqueID
= fRead
.Next
<uint32
>();
515 if (tag
.tag
== 0x11) {
516 if (_ParseTIFFImageFileDirectory(baseOffset
, fRead
.Next
<uint32
>())
520 if (tag
.tag
== 0x14 && tag
.length
== 2560 && tag
.type
== 7) {
521 fRead
.Seek(1248, SEEK_CUR
);
524 if (tag
.tag
== 0x1d) {
526 while ((c
= fRead
.Next
<uint8
>()) && c
!= EOF
) {
527 serial
= serial
* 10 + (isdigit(c
) ? c
- '0' : c
% 10);
530 if (tag
.tag
== 0x81 && tag
.type
== 4) {
531 _Raw().data_offset
= fRead
.Next
<uint32
>();
532 fRead
.Seek(_Raw().data_offset
+ 41, SEEK_SET
);
533 _Raw().height
= fRead
.Next
<uint16
>() * 2;
534 _Raw().width
= fRead
.Next
<uint16
>();
535 fFilters
= 0x61616161;
537 if ((tag
.tag
== 0x81 && tag
.type
== 7)
538 || (tag
.tag
== 0x100 && tag
.type
== 7)
539 || (tag
.tag
== 0x280 && tag
.type
== 1)) {
540 _Thumb().data_offset
= fRead
.Position();
541 _Thumb().bytes
= tag
.length
;
543 if (tag
.tag
== 0x88 && tag
.type
== 4
544 && (_Thumb().data_offset
= fRead
.Next
<uint32
>())) {
545 _Thumb().data_offset
+= baseOffset
;
547 if (tag
.tag
== 0x89 && tag
.type
== 4)
548 _Thumb().bytes
= fRead
.Next
<uint32
>();
550 fCurveOffset
= fRead
.Position() + 2112;
552 fCurveOffset
= fRead
.Position() + 2;
553 if (tag
.tag
== 0x97) {
554 for (uint32 i
= 0; i
< 4; i
++) {
555 ver97
= (ver97
<< 4) + fRead
.Next
<uint8
>() - '0';
559 fRead
.Seek(68, SEEK_CUR
);
560 for (uint32 i
= 0; i
< 4; i
++) {
561 fMeta
.camera_multipliers
[(i
>> 1) | ((i
& 1) << 1)]
562 = fRead
.Next
<uint16
>();
566 fRead
.Seek(6, SEEK_CUR
);
569 fRead
.Seek(16, SEEK_CUR
);
570 for (uint32 i
= 0; i
< 4; i
++) {
571 fMeta
.camera_multipliers
[i
] = fRead
.Next
<uint16
>();
575 if (ver97
>> 8 == 2) {
577 fRead
.Seek(280, SEEK_CUR
);
578 fRead(buf97
, sizeof(buf97
));
581 if (tag
.tag
== 0xa7 && ver97
>> 8 == 2) {
582 ci
= xlat
[0][serial
& 0xff];
583 cj
= xlat
[1][fRead
.Next
<uint8
>() ^ fRead
.Next
<uint8
>()
584 ^ fRead
.Next
<uint8
>() ^ fRead
.Next
<uint8
>()];
586 for (uint32 i
= 0; i
< 324; i
++) {
587 buf97
[i
] ^= (cj
+= ci
* ck
++);
589 for (uint32 i
= 0; i
< 4; i
++) {
590 uint16
* data
= (uint16
*)(buf97
591 + (ver97
== 0x205 ? 14 : 6) + i
* 2);
593 if (fRead
.IsSwapping()) {
594 fMeta
.camera_multipliers
[i
^ (i
>> 1)]
595 = __swap_int16(*data
);
597 fMeta
.camera_multipliers
[i
^ (i
>> 1)] = *data
;
601 if (tag
.tag
== 0x200 && tag
.length
== 4) {
602 fMeta
.black
= (fRead
.Next
<uint16
>() + fRead
.Next
<uint16
>()
603 + fRead
.Next
<uint16
>() + fRead
.Next
<uint16
>()) / 4;
605 if (tag
.tag
== 0x201 && tag
.length
== 4)
607 if (tag
.tag
== 0x401 && tag
.length
== 4) {
608 fMeta
.black
= (fRead
.Next
<uint32
>() + fRead
.Next
<uint32
>()
609 + fRead
.Next
<uint32
>() + fRead
.Next
<uint32
>()) / 4;
611 if (tag
.tag
== 0xe01) {
612 // Nikon Capture Note
613 bool previousSwap
= fRead
.IsSwapping();
614 fRead
.SetSwap(B_HOST_IS_BENDIAN
!= 0);
615 // this chunk is always in little endian
618 fRead
.Seek(offset
, SEEK_CUR
);
622 for (; offset
+ 22 < tag
.length
; offset
+= 22 + i
) {
623 tag
.tag
= fRead
.Next
<uint32
>();
624 fRead
.Seek(14, SEEK_CUR
);
625 i
= fRead
.Next
<uint32
>() - 4;
626 if (tag
.tag
== 0x76a43207)
627 fMeta
.flip
= fRead
.Next
<uint16
>();
629 fRead
.Seek(i
, SEEK_CUR
);
632 fRead
.SetSwap(previousSwap
);
634 if (tag
.tag
== 0xe80 && tag
.length
== 256 && tag
.type
== 7) {
635 fRead
.Seek(48, SEEK_CUR
);
636 fMeta
.camera_multipliers
[0]
637 = fRead
.Next
<uint16
>() * 508 * 1.078 / 0x10000;
638 fMeta
.camera_multipliers
[2]
639 = fRead
.Next
<uint16
>() * 382 * 1.173 / 0x10000;
641 if (tag
.tag
== 0xf00 && tag
.type
== 7) {
642 if (tag
.length
== 614)
643 fRead
.Seek(176, SEEK_CUR
);
644 else if (tag
.length
== 734 || tag
.length
== 1502)
645 fRead
.Seek(148, SEEK_CUR
);
650 if (tag
.tag
== 0x1011 && tag
.length
== 9 && fUseCameraWhiteBalance
) {
651 for (uint32 i
= 0; i
< 3; i
++) {
652 for (uint32 j
= 0; j
< 3; j
++) {
653 fMeta
.rgb_camera
[i
][j
] = fRead
.Next
<int16
>() / 256.0;
656 fRawColor
= fMeta
.rgb_camera
[0][0] < 1;
658 if (tag
.tag
== 0x1012 && tag
.length
== 4) {
660 for (uint32 i
= 0; i
< 4; i
++) {
661 fMeta
.black
+= fRead
.Next
<uint16
>() << 2;
664 if (tag
.tag
== 0x1017)
665 fMeta
.camera_multipliers
[0] = fRead
.Next
<uint16
>() / 256.0;
666 if (tag
.tag
== 0x1018)
667 fMeta
.camera_multipliers
[2] = fRead
.Next
<uint16
>() / 256.0;
669 if (tag
.tag
== 0x2011 && tag
.length
== 2) {
671 bool previousSwap
= fRead
.IsSwapping();
672 fRead
.SetSwap(B_HOST_IS_LENDIAN
!= 0);
673 // this chunk is always in big endian
675 fMeta
.camera_multipliers
[0] = fRead
.Next
<uint16
>() / 256.0;
676 fMeta
.camera_multipliers
[2] = fRead
.Next
<uint16
>() / 256.0;
678 fRead
.SetSwap(previousSwap
);
681 if (tag
.tag
== 0x2020)
682 _ParseThumbTag(baseOffset
, 257, 258);
683 if (tag
.tag
== 0xb028) {
684 fRead
.Seek(fRead
.Next
<uint32
>(), SEEK_SET
);
685 _ParseThumbTag(baseOffset
, 136, 137);
688 if (tag
.tag
== 0x4001) {
690 off_t offset
= tag
.length
== 582 ? 50 : tag
.length
== 653
692 fRead
.Seek(offset
, SEEK_CUR
);
695 for (uint32 i
= 0; i
< 4; i
++) {
696 fMeta
.camera_multipliers
[i
^ (i
>> 1)] = fRead
.Next
<uint16
>();
701 fRead
.Seek(nextOffset
, SEEK_SET
);
705 fRead
.SetSwap(originalSwap
);
710 DCRaw::_ParseEXIF(off_t baseOffset
)
712 bool kodak
= !strncmp(fMeta
.manufacturer
, "EASTMAN", 7);
720 _ParseTIFFTag(baseOffset
, tag
, nextOffset
);
721 TAG("EXIF tag %u (type %u, length %lu)\n", tag
.tag
, tag
.type
,
727 printf(" unhandled EXIF tag %u\n", tag
.tag
);
731 fMeta
.shutter
= fRead
.NextDouble(TIFF_FRACTION_TYPE
);
734 fMeta
.aperture
= fRead
.NextDouble(TIFF_FRACTION_TYPE
);
737 fMeta
.iso_speed
= fRead
.Next
<uint16
>();
741 fMeta
.timestamp
= _ParseTIFFTimestamp(false);
746 if ((expo
= -fRead
.NextDouble(TIFF_FRACTION_TYPE
)) < 128)
747 fMeta
.shutter
= pow(2, expo
);
752 = pow(2, fRead
.NextDouble(TIFF_FRACTION_TYPE
) / 2);
755 fMeta
.focal_length
= fRead
.NextDouble(TIFF_FRACTION_TYPE
);
758 _ParseManufacturerTag(baseOffset
);
762 _Raw().width
= fRead
.Next
<uint32
>();
766 _Raw().height
= fRead
.Next
<uint32
>();
769 if (fRead
.Next
<uint32
>() == 0x20002) {
771 for (uint32 c
= 0; c
< 8; c
+= 2) {
772 fEXIFFilters
|= fRead
.Next
<uint8
>() * 0x01010101 << c
;
778 fRead
.Seek(nextOffset
, SEEK_SET
);
784 DCRaw::_ParseLinearTable(uint32 length
)
789 fRead
.NextShorts(fCurve
, length
);
791 for (uint32 i
= length
; i
< 0x1000; i
++) {
792 fCurve
[i
] = fCurve
[i
- 1];
795 fMeta
.maximum
= fCurve
[0xfff];
799 /*! This (lengthy) method contains fixes for the values in the image data to
800 be able to actually read the image data correctly.
803 DCRaw::_FixupValues()
805 // PENTAX and SAMSUNG section
806 // (Samsung sells rebranded Pentax cameras)
808 if (_IsPentax() || _IsSamsung()) {
809 if (fInputWidth
== 3936 && fInputHeight
== 2624) {
810 // Pentax K10D and Samsumg GX10
820 if (strstr(fMeta
.model
, "EOS D2000C")) {
821 fFilters
= 0x61616161;
822 fMeta
.black
= fCurve
[200];
825 switch (_Raw().width
) {
831 if (!strcmp(fMeta
.model
, "PowerShot G1")) {
833 fFilters
= 0xb4b4b4b4;
863 if (fUniqueID
== 0x80000170)
864 _AdobeCoefficients("Canon", "EOS 300D");
865 fMeta
.maximum
= 0xfa0;
885 if (fUniqueID
== 0x80000189)
886 _AdobeCoefficients("Canon", "EOS 350D");
900 if (fUniqueID
== 0x80000236)
901 _AdobeCoefficients("Canon", "EOS 400D");
909 fMeta
.maximum
= 0x3bb0;
916 fMeta
.maximum
= 0xe6c;
923 fMeta
.maximum
= 0xe80;
929 fInputHeight
-= fTopMargin
;
930 fInputWidth
-= fLeftMargin
;
937 if (!strcmp(fMeta
.model
,"E-300") || !strcmp(fMeta
.model
,"E-500")) {
939 fMeta
.maximum
= 0xfc30;
940 //if (load_raw == &CLASS unpacked_load_raw) black = 0;
946 // #pragma mark - Image Conversion
950 DCRaw::_ScaleColors()
952 if (fProgressMonitor
!= NULL
)
953 fProgressMonitor("Scale Colors", 5, fProgressData
);
956 uint32 row
, col
, x
, y
;
957 double dsum
[8], dmin
, dmax
;
960 if (fUseCameraWhiteBalance
&& fMeta
.camera_multipliers
[0] != -1) {
961 memset(sum
, 0, sizeof(sum
));
962 for (row
= 0; row
< 8; row
++) {
963 for (col
= 0; col
< 8; col
++) {
965 if ((val
= fWhite
[row
][col
] - fMeta
.black
) > 0)
971 if (sum
[0] && sum
[1] && sum
[2] && sum
[3]) {
972 for (int c
= 0; c
< 4; c
++) {
973 fMeta
.pre_multipliers
[c
] = (float)sum
[c
+4] / sum
[c
];
975 } else if (fMeta
.camera_multipliers
[0] && fMeta
.camera_multipliers
[2]) {
976 memcpy(fMeta
.pre_multipliers
, fMeta
.camera_multipliers
,
977 sizeof(fMeta
.pre_multipliers
));
979 fprintf(stderr
, "Cannot use camera white balance.\n");
980 } else if (fUseAutoWhiteBalance
) {
981 memset(dsum
, 0, sizeof(dsum
));
982 for (row
= 0; row
< fOutputHeight
- 7; row
+= 8) {
983 for (col
= 0; col
< fOutputWidth
- 7; col
+= 8) {
984 memset(sum
, 0, sizeof(sum
));
985 for (y
= row
; y
< row
+ 8; y
++) {
986 for (x
= col
; x
< col
+ 8; x
++) {
987 for (int c
= 0; c
< 4; c
++) {
988 val
= fImageData
[y
* fOutputWidth
+ x
][c
];
991 if (val
> fMeta
.maximum
- 25)
1002 for (c
=0; c
< 8; c
++) {
1010 for (int c
= 0; c
< 4; c
++) {
1012 fMeta
.pre_multipliers
[c
] = dsum
[c
+ 4] / dsum
[c
];
1017 if (fUserMultipliers
[0]) {
1018 memcpy(fMeta
.pre_multipliers
, fUserMultipliers
,
1019 sizeof(fMeta
.pre_multipliers
));
1021 if (fMeta
.pre_multipliers
[3] == 0)
1022 fMeta
.pre_multipliers
[3] = fColors
< 4 ? fMeta
.pre_multipliers
[1] : 1;
1025 int dblack
= fMeta
.black
;
1030 fMeta
.maximum
-= fMeta
.black
;
1031 for (dmin
= DBL_MAX
, dmax
= c
= 0; c
< 4; c
++) {
1032 if (dmin
> fMeta
.pre_multipliers
[c
])
1033 dmin
= fMeta
.pre_multipliers
[c
];
1034 if (dmax
< fMeta
.pre_multipliers
[c
])
1035 dmax
= fMeta
.pre_multipliers
[c
];
1041 for (int c
= 0; c
< 4; c
++) {
1042 scale_mul
[c
] = (fMeta
.pre_multipliers
[c
] /= dmax
) * 65535.0
1048 fprintf(stderr
, "Scaling with black %d, multipliers", dblack
);
1049 for (int c
= 0; c
< 4; c
++) {
1050 fprintf(stderr
, " %f", fMeta
.pre_multipliers
[c
]);
1052 fputc('\n', stderr
);
1056 for (row
= 0; row
< fOutputHeight
; row
++) {
1057 for (col
= 0; col
< fOutputWidth
; col
++) {
1058 for (int c
= 0; c
< 4; c
++) {
1059 val
= fImageData
[row
* fOutputWidth
+ col
][c
];
1063 val
= int(val
* scale_mul
[c
]);
1064 fImageData
[row
* fOutputWidth
+ col
][c
] = CLIP(val
);
1072 DCRaw::_WaveletDenoise()
1074 if (fProgressMonitor
!= NULL
)
1075 fProgressMonitor("Wavelet Denoise", 8, fProgressData
);
1077 float *fimg
, *temp
, mul
[2], avg
, diff
;
1078 int32 scale
= 1, sh
, c
, i
, j
, k
, m
, row
, col
, size
, numColors
, dim
= 0;
1081 // Daubechies 9-tap/7-tap filter
1082 static const float wlet
[] = { 1.149604398, -1.586134342,
1083 -0.05298011854, 0.8829110762, 0.4435068522 };
1085 while ((fMeta
.maximum
<< scale
) < 0x10000) {
1088 fMeta
.maximum
<<= fMeta
.maximum
<< --scale
;
1089 fMeta
.black
<<= scale
;
1091 while ((1UL << dim
) < fOutputWidth
|| (1UL << dim
) < fOutputHeight
) {
1095 fimg
= (float *)calloc((1UL << dim
*2) + (1UL << dim
) + 2, sizeof *fimg
);
1099 temp
= fimg
+ (1 << dim
* 2) + 1;
1100 numColors
= fColors
;
1101 if (numColors
== 3 && fFilters
)
1104 for (c
= 0; c
< numColors
; c
++) {
1105 // denoise R,G1,B,G3 individually
1106 for (row
= 0; row
< (int32
)fOutputHeight
; row
++) {
1107 for (col
= 0; col
< (int32
)fOutputWidth
; col
++) {
1108 fimg
[(row
<< dim
) + col
]
1109 = fImageData
[row
* fOutputWidth
+ col
][c
] << scale
;
1112 for (size
= 1UL << dim
; size
> 1; size
>>= 1) {
1113 for (sh
= 0; sh
<= dim
; sh
+= dim
) {
1114 for (i
= 0; i
< size
; i
++) {
1115 for (j
= 0; j
< size
; j
++) {
1116 temp
[j
] = fimg
[(i
<< (dim
- sh
)) + (j
<< sh
)];
1118 for (k
= 1; k
< 5; k
+= 2) {
1119 temp
[size
] = temp
[size
- 2];
1120 for (m
= 1; m
< size
; m
+= 2) {
1121 temp
[m
] += wlet
[k
] * (temp
[m
- 1] + temp
[m
+ 1]);
1124 for (m
= 0; m
< size
; m
+= 2) {
1125 temp
[m
] += wlet
[k
+ 1]
1126 * (temp
[m
- 1] + temp
[m
+ 1]);
1129 for (m
= 0; m
< size
; m
++) {
1130 temp
[m
] *= (m
& 1) ? 1 / wlet
[0] : wlet
[0];
1132 for (j
= k
= 0; j
< size
; j
++, k
+= 2) {
1135 fimg
[(i
<< (dim
- sh
)) + (j
<< sh
)] = temp
[k
];
1141 for (i
= 0; i
< (1 << dim
* 2); i
++) {
1142 if (fimg
[i
] < -fThreshold
)
1143 fimg
[i
] += fThreshold
;
1144 else if (fimg
[i
] > fThreshold
)
1145 fimg
[i
] -= fThreshold
;
1150 for (size
= 2; size
<= (1 << dim
); size
<<= 1) {
1151 for (sh
= dim
; sh
>= 0; sh
-= dim
) {
1152 for (i
= 0; i
< size
; i
++) {
1153 for (j
= k
= 0; j
< size
; j
++, k
+= 2) {
1156 temp
[k
] = fimg
[(i
<< (dim
- sh
)) + (j
<< sh
)];
1158 for (m
= 0; m
< size
; m
++) {
1159 temp
[m
] *= (m
& 1) ? wlet
[0] : 1 / wlet
[0];
1161 for (k
= 3; k
> 0; k
-= 2) {
1163 for (m
= 0; m
< size
; m
+= 2) {
1164 temp
[m
] -= wlet
[k
+ 1]
1165 * (temp
[m
- 1] + temp
[m
+ 1]);
1167 temp
[size
] = temp
[size
- 2];
1168 for (m
= 1; m
< size
; m
+= 2) {
1169 temp
[m
] -= wlet
[k
] * (temp
[m
- 1] + temp
[m
+ 1]);
1172 for (j
= 0; j
< size
; j
++) {
1173 fimg
[(i
<< (dim
- sh
)) + (j
<< sh
)] = temp
[j
];
1179 for (row
= 0; row
< (int32
)fOutputHeight
; row
++) {
1180 for (col
= 0; col
< (int32
)fOutputWidth
; col
++) {
1181 fImageData
[row
* fOutputWidth
+ col
][c
]
1182 = (uint16
)CLIP(fimg
[(row
<< dim
) + col
] + 0.5);
1187 if (fFilters
&& fColors
== 3) {
1188 // pull G1 and G3 closer together
1189 for (row
= 0; row
< 2; row
++) {
1190 mul
[row
] = 0.125 * fMeta
.pre_multipliers
[FC(row
+ 1, 0) | 1]
1191 / fMeta
.pre_multipliers
[FC(row
, 0) | 1];
1193 for (i
= 0; i
< 4; i
++) {
1194 window
[i
] = (ushort
*)fimg
+ fInputWidth
* i
;
1196 for (wlast
= -1, row
= 1; row
< (int32
)fInputHeight
- 1; row
++) {
1197 while (wlast
< (int32
)row
+ 1) {
1198 for (wlast
++, i
= 0; i
< 4; i
++) {
1199 window
[(i
+ 3) & 3] = window
[i
];
1201 for (col
= FC(wlast
, 1) & 1; col
< (int32
)fInputWidth
;
1203 window
[2][col
] = _Bayer(col
, wlast
);
1207 for (col
= (FC(row
, 0) & 1) + 1; col
< (int32
)fInputWidth
- 1;
1209 avg
= ( window
[0][col
- 1] + window
[0][col
+ 1]
1210 + window
[2][col
- 1] + window
[2][col
+ 1] - fMeta
.black
* 4)
1211 * mul
[row
& 1] + (window
[1][col
] - fMeta
.black
) * 0.5
1213 diff
= _Bayer(col
, row
) - avg
;
1215 if (diff
< -fThreshold
/ M_SQRT2
)
1216 diff
+= fThreshold
/ M_SQRT2
;
1217 else if (diff
> fThreshold
/ M_SQRT2
)
1218 diff
-= fThreshold
/ M_SQRT2
;
1221 _Bayer(col
, row
) = (uint16
)CLIP(avg
+ diff
+ 0.5);
1231 DCRaw::_PreInterpolate()
1233 if (fProgressMonitor
!= NULL
)
1234 fProgressMonitor("Pre-Interpolate", 10, fProgressData
);
1240 fInputHeight
= fOutputHeight
;
1241 fInputWidth
= fOutputWidth
;
1244 uint16 (*data
)[4] = (uint16 (*)[4])calloc(fInputHeight
1245 * fInputWidth
, sizeof(*data
));
1247 throw (status_t
)B_NO_MEMORY
;
1249 for (row
= 0; row
< fInputHeight
; row
++) {
1250 for (col
= 0; col
< fInputWidth
; col
++) {
1251 data
[row
* fInputWidth
+ col
][FC(row
, col
)]
1262 if (fFilters
&& fColors
== 3) {
1263 // if ((mix_green = four_color_rgb))
1267 for (row
= FC(1, 0) >> 1; row
< fInputHeight
; row
+= 2) {
1268 for (col
= FC(row
, 1) & 1; col
< fInputWidth
; col
+= 2) {
1269 fImageData
[row
* fInputWidth
+ col
][1]
1270 = fImageData
[row
* fInputWidth
+ col
][3];
1273 fFilters
&= ~((fFilters
& 0x55555555) << 1);
1280 DCRaw::_CameraToCIELab(ushort cam
[4], float lab
[3])
1283 for (uint32 i
= 0; i
< 0x10000; i
++) {
1284 float r
= i
/ 65535.0;
1285 cbrt
[i
] = r
> 0.008856 ? pow(r
, 1 / 3.0) : 7.787 * r
+ 16 / 116.0;
1287 for (uint32 i
= 0; i
< 3; i
++) {
1288 for (uint32 j
= 0; j
< fColors
; j
++) {
1290 for (uint32 k
= 0; k
< 3; k
++) {
1291 xyz_cam
[i
][j
] += xyz_rgb
[i
][k
] * fMeta
.rgb_camera
[k
][j
]
1298 xyz
[0] = xyz
[1] = xyz
[2] = 0.5;
1299 for (uint32 c
= 0; c
< fColors
; c
++) {
1300 xyz
[0] += xyz_cam
[0][c
] * cam
[c
];
1301 xyz
[1] += xyz_cam
[1][c
] * cam
[c
];
1302 xyz
[2] += xyz_cam
[2][c
] * cam
[c
];
1304 xyz
[0] = cbrt
[CLIP((int) xyz
[0])];
1305 xyz
[1] = cbrt
[CLIP((int) xyz
[1])];
1306 xyz
[2] = cbrt
[CLIP((int) xyz
[2])];
1307 lab
[0] = 116 * xyz
[1] - 16;
1308 lab
[1] = 500 * (xyz
[0] - xyz
[1]);
1309 lab
[2] = 200 * (xyz
[1] - xyz
[2]);
1315 DCRaw::_CameraXYZCoefficients(double cameraXYZ
[4][3])
1317 double cam_rgb
[4][3], inverse
[4][3], num
;
1320 // Multiply out XYZ colorspace
1321 for (i
= 0; i
< fColors
; i
++) {
1322 for (j
= 0; j
< 3; j
++) {
1323 for (cam_rgb
[i
][j
] = k
= 0; k
< 3; k
++) {
1324 cam_rgb
[i
][j
] += cameraXYZ
[i
][k
] * xyz_rgb
[k
][j
];
1329 // Normalize cam_rgb so that cam_rgb * (1,1,1) is (1,1,1,1)
1330 for (i
= 0; i
< fColors
; i
++) {
1331 for (num
= j
= 0; j
< 3; j
++) {
1332 num
+= cam_rgb
[i
][j
];
1334 for (j
= 0; j
< 3; j
++) {
1335 cam_rgb
[i
][j
] /= num
;
1337 fMeta
.pre_multipliers
[i
] = 1 / num
;
1340 _PseudoInverse(cam_rgb
, inverse
, fColors
);
1343 for (i
= 0; i
< 3; i
++) {
1344 for (j
=0; j
< fColors
; j
++) {
1345 fMeta
.rgb_camera
[i
][j
] = inverse
[j
][i
];
1351 /*! Thanks to Adobe for providing these excellent CAM -> XYZ matrices!
1354 DCRaw::_AdobeCoefficients(const char *make
, const char *model
)
1356 static const struct {
1358 short black
, trans
[12];
1360 { "Canon EOS D2000", 0,
1361 { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 }},
1362 { "Canon EOS D6000", 0,
1363 { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 }},
1364 { "Canon EOS D30", 0,
1365 { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 }},
1366 { "Canon EOS D60", 0,
1367 { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 }},
1368 { "Canon EOS 5D", 0,
1369 { 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 }},
1370 { "Canon EOS 20Da", 0,
1371 { 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 }},
1372 { "Canon EOS 20D", 0,
1373 { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 }},
1374 { "Canon EOS 30D", 0,
1375 { 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 }},
1376 { "Canon EOS 350D", 0,
1377 { 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 }},
1378 { "Canon EOS 400D", 0,
1379 { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 }},
1380 { "Canon EOS-1Ds Mark II", 0,
1381 { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 }},
1382 { "Canon EOS-1D Mark II N", 0,
1383 { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 }},
1384 { "Canon EOS-1D Mark II", 0,
1385 { 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 }},
1386 { "Canon EOS-1DS", 0,
1387 { 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 }},
1388 { "Canon EOS-1D", 0,
1389 { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 }},
1391 { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 }},
1392 { "Canon PowerShot A50", 0,
1393 { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 }},
1394 { "Canon PowerShot A5", 0,
1395 { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 }},
1396 { "Canon PowerShot G1", 0,
1397 { -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 }},
1398 { "Canon PowerShot G2", 0,
1399 { 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 }},
1400 { "Canon PowerShot G3", 0,
1401 { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 }},
1402 { "Canon PowerShot G5", 0,
1403 { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 }},
1404 { "Canon PowerShot G6", 0,
1405 { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 }},
1406 { "Canon PowerShot Pro1", 0,
1407 { 10062,-3522,-999,-7643,15117,2730,-765,817,7323 }},
1408 { "Canon PowerShot Pro70", 34,
1409 { -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 }},
1410 { "Canon PowerShot Pro90", 0,
1411 { -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 }},
1412 { "Canon PowerShot S30", 0,
1413 { 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 }},
1414 { "Canon PowerShot S40", 0,
1415 { 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 }},
1416 { "Canon PowerShot S45", 0,
1417 { 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 }},
1418 { "Canon PowerShot S50", 0,
1419 { 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 }},
1420 { "Canon PowerShot S60", 0,
1421 { 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 }},
1422 { "Canon PowerShot S70", 0,
1423 { 9976,-3810,-832,-7115,14463,2906,-901,989,7889 }},
1424 { "Canon PowerShot A610", 0, /* DJC */
1425 { 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 }},
1426 { "Canon PowerShot A620", 0, /* DJC */
1427 { 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 }},
1428 { "Canon PowerShot S3 IS", 0, /* DJC */
1429 { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 }},
1430 { "Contax N Digital", 0,
1431 { 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 }},
1433 { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 }},
1434 { "FUJIFILM FinePix E550", 0,
1435 { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 }},
1436 { "FUJIFILM FinePix E900", 0,
1437 { 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 }},
1438 { "FUJIFILM FinePix F8", 0,
1439 { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 }},
1440 { "FUJIFILM FinePix F7", 0,
1441 { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 }},
1442 { "FUJIFILM FinePix S20Pro", 0,
1443 { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 }},
1444 { "FUJIFILM FinePix S2Pro", 128,
1445 { 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 }},
1446 { "FUJIFILM FinePix S3Pro", 0,
1447 { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 }},
1448 { "FUJIFILM FinePix S5000", 0,
1449 { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 }},
1450 { "FUJIFILM FinePix S5100", 0,
1451 { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 }},
1452 { "FUJIFILM FinePix S5500", 0,
1453 { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 }},
1454 { "FUJIFILM FinePix S5200", 0,
1455 { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 }},
1456 { "FUJIFILM FinePix S5600", 0,
1457 { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 }},
1458 { "FUJIFILM FinePix S6", 0,
1459 { 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 }},
1460 { "FUJIFILM FinePix S7000", 0,
1461 { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 }},
1462 { "FUJIFILM FinePix S9000", 0,
1463 { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 }},
1464 { "FUJIFILM FinePix S9500", 0,
1465 { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 }},
1466 { "FUJIFILM FinePix S9100", 0,
1467 { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 }},
1468 { "FUJIFILM FinePix S9600", 0,
1469 { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 }},
1470 { "Imacon Ixpress", 0, /* DJC */
1471 { 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 }},
1472 { "KODAK NC2000", 0, /* DJC */
1473 { 16475,-6903,-1218,-851,10375,477,2505,-7,1020 }},
1474 { "Kodak DCS315C", 8,
1475 { 17523,-4827,-2510,756,8546,-137,6113,1649,2250 }},
1476 { "Kodak DCS330C", 8,
1477 { 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 }},
1478 { "KODAK DCS420", 0,
1479 { 10868,-1852,-644,-1537,11083,484,2343,628,2216 }},
1480 { "KODAK DCS460", 0,
1481 { 10592,-2206,-967,-1944,11685,230,2206,670,1273 }},
1482 { "KODAK EOSDCS1", 0,
1483 { 10592,-2206,-967,-1944,11685,230,2206,670,1273 }},
1484 { "KODAK EOSDCS3B", 0,
1485 { 9898,-2700,-940,-2478,12219,206,1985,634,1031 }},
1486 { "Kodak DCS520C", 180,
1487 { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 }},
1488 { "Kodak DCS560C", 188,
1489 { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 }},
1490 { "Kodak DCS620C", 180,
1491 { 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 }},
1492 { "Kodak DCS620X", 185,
1493 { 13095,-6231,154,12221,-21,-2137,895,4602,2258 }},
1494 { "Kodak DCS660C", 214,
1495 { 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 }},
1496 { "Kodak DCS720X", 0,
1497 { 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 }},
1498 { "Kodak DCS760C", 0,
1499 { 16623,-6309,-1411,-4344,13923,323,2285,274,2926 }},
1500 { "Kodak DCS Pro SLR", 0,
1501 { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 }},
1502 { "Kodak DCS Pro 14nx", 0,
1503 { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 }},
1504 { "Kodak DCS Pro 14", 0,
1505 { 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 }},
1506 { "Kodak ProBack645", 0,
1507 { 16414,-6060,-1470,-3555,13037,473,2545,122,4948 }},
1508 { "Kodak ProBack", 0,
1509 { 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 }},
1511 { 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 }},
1513 { 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 }},
1515 { 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 }},
1517 { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 }},
1518 { "Leaf Valeo 6", 0,
1519 { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 }},
1520 { "Leaf Aptus 65", 0,
1521 { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 }},
1522 { "Leaf Aptus 75", 0,
1523 { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 }},
1525 { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 }},
1526 { "Micron 2010", 110, /* DJC */
1527 { 16695,-3761,-2151,155,9682,163,3433,951,4904 }},
1528 { "Minolta DiMAGE 5", 0,
1529 { 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 }},
1530 { "Minolta DiMAGE 7Hi", 0,
1531 { 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 }},
1532 { "Minolta DiMAGE 7", 0,
1533 { 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 }},
1534 { "Minolta DiMAGE A1", 0,
1535 { 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 }},
1536 { "MINOLTA DiMAGE A200", 0,
1537 { 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 }},
1538 { "Minolta DiMAGE A2", 0,
1539 { 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 }},
1540 { "Minolta DiMAGE Z2", 0, /* DJC */
1541 { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 }},
1542 { "MINOLTA DYNAX 5", 0,
1543 { 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 }},
1544 { "MINOLTA DYNAX 7", 0,
1545 { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 }},
1547 { 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 }},
1549 { 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 }},
1551 { 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 }},
1552 { "NIKON D1", 0, /* multiplied by 2.218750, 1.0, 1.148438 */
1553 { 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 }},
1555 { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 }},
1557 { 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 }},
1559 { 6992,-1668,-806,-8138,15748,2543,-874,850,7897 }},
1561 { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 }},
1563 { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 }},
1565 { 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 }},
1567 { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 }},
1568 { "NIKON E950", 0, /* DJC */
1569 { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 }},
1570 { "NIKON E995", 0, /* copied from E5000 */
1571 { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 }},
1573 { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 }},
1574 { "NIKON E4300", 0, /* copied from Minolta DiMAGE Z2 */
1575 { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 }},
1577 { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 }},
1579 { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 }},
1581 { 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 }},
1583 { -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 }},
1585 { 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 }},
1587 { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 }},
1589 { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 }},
1590 { "OLYMPUS C5050", 0,
1591 { 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 }},
1592 { "OLYMPUS C5060", 0,
1593 { 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 }},
1594 { "OLYMPUS C7070", 0,
1595 { 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 }},
1597 { 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 }},
1599 { 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 }},
1600 { "OLYMPUS E-10", 0,
1601 { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 }},
1603 { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 }},
1604 { "OLYMPUS E-20", 0,
1605 { 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 }},
1606 { "OLYMPUS E-300", 0,
1607 { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 }},
1608 { "OLYMPUS E-330", 0,
1609 { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 }},
1610 { "OLYMPUS E-400", 0,
1611 { 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 }},
1612 { "OLYMPUS E-500", 0,
1613 { 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 }},
1614 { "OLYMPUS SP350", 0,
1615 { 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 }},
1617 { 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 }},
1618 { "OLYMPUS SP500UZ", 0,
1619 { 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 }},
1620 { "OLYMPUS SP510UZ", 0,
1621 { 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 }},
1622 { "PENTAX *ist DL2", 0,
1623 { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 }},
1624 { "PENTAX *ist DL", 0,
1625 { 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 }},
1626 { "PENTAX *ist DS2", 0,
1627 { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 }},
1628 { "PENTAX *ist DS", 0,
1629 { 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 }},
1630 { "PENTAX *ist D", 0,
1631 { 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 }},
1633 { 9566,-2863,-803,-7170,15172,2112,-818,803,9705 }},
1635 { 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 }},
1636 { "Panasonic DMC-FZ30", 0,
1637 { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 }},
1638 { "Panasonic DMC-FZ50", 0, /* aka "LEICA V-LUX1" */
1639 { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 }},
1640 { "Panasonic DMC-L1", 0, /* aka "LEICA DIGILUX 3" */
1641 { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 }},
1642 { "Panasonic DMC-LC1", 0, /* aka "LEICA DIGILUX 2" */
1643 { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 }},
1644 { "Panasonic DMC-LX1", 0, /* aka "LEICA D-LUX2" */
1645 { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 }},
1646 { "Panasonic DMC-LX2", 0, /* aka "LEICA D-LUX3" */
1647 { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 }},
1648 { "SAMSUNG GX-1", 0,
1649 { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 }},
1650 { "Sinar", 0, /* DJC */
1651 { 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 }},
1652 { "SONY DSC-F828", 491,
1653 { 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 }},
1654 { "SONY DSC-R1", 512,
1655 { 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 }},
1657 { 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 }},
1658 { "SONY DSLR-A100", 0,
1659 { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 }}
1661 double cameraXYZ
[4][3];
1663 for (uint32 i
= 0; i
< sizeof table
/ sizeof *table
; i
++) {
1664 if (!strncasecmp(model
, table
[i
].prefix
, strlen(table
[i
].prefix
))) {
1666 fMeta
.black
= table
[i
].black
;
1667 for (uint32 j
= 0; j
< 12; j
++) {
1668 ((double**)cameraXYZ
)[0][j
] = table
[i
].trans
[j
] / 10000.0;
1670 _CameraXYZCoefficients(cameraXYZ
);
1678 DCRaw::_BorderInterpolate(uint32 border
)
1680 uint32 row
, col
, y
, x
, f
, c
, sum
[8];
1682 for (row
= 0; row
< fInputHeight
; row
++) {
1683 for (col
= 0; col
< fInputWidth
; col
++) {
1684 if (col
== border
&& row
>= border
&& row
< fInputHeight
- border
)
1685 col
= fInputWidth
- border
;
1687 memset(sum
, 0, sizeof(sum
));
1689 for (y
= row
- 1; y
!= row
+ 2; y
++) {
1690 for (x
= col
- 1; x
!= col
+ 2; x
++) {
1691 if (y
< fInputHeight
&& x
< fInputWidth
) {
1692 f
= _FilterCoefficient(x
, y
);
1693 sum
[f
] += fImageData
[y
* fInputWidth
+ x
][f
];
1699 f
= _FilterCoefficient(col
, row
);
1701 for (c
= 0; c
< fColors
; c
++) {
1702 if (c
!= f
&& sum
[c
+ 4]) {
1703 fImageData
[row
* fInputWidth
+ col
][c
]
1704 = sum
[c
] / sum
[c
+ 4];
1712 /*! Adaptive Homogeneity-Directed interpolation is based on
1713 the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
1716 DCRaw::_AHDInterpolate()
1718 if (fProgressMonitor
!= NULL
)
1719 fProgressMonitor("Interpolate", 20, fProgressData
);
1721 #define TS 256 /* Tile Size */
1723 int i
, j
, tr
, tc
, fc
, c
, d
, val
, hm
[2];
1724 uint32 top
, left
, row
, col
;
1725 ushort (*pix
)[4], (*rix
)[3];
1726 static const int dir
[4] = { -1, 1, -TS
, TS
};
1727 unsigned ldiff
[2][4], abdiff
[2][4], leps
, abeps
;
1729 ushort (*rgb
)[TS
][TS
][3];
1730 short (*lab
)[TS
][TS
][3];
1731 char (*homo
)[TS
][TS
], *buffer
;
1733 _BorderInterpolate(3);
1734 buffer
= (char *)malloc(26 * TS
* TS
); /* 1664 kB */
1736 throw (status_t
)B_NO_MEMORY
;
1738 rgb
= (ushort(*)[TS
][TS
][3])buffer
;
1739 lab
= (short (*)[TS
][TS
][3])(buffer
+ 12 * TS
* TS
);
1740 homo
= (char (*)[TS
][TS
])(buffer
+ 24 * TS
* TS
);
1741 float percentage
= 20;
1742 float percentageStep
= 70.0f
/ (fInputHeight
/ (TS
- 6));
1744 for (top
= 0; top
< fInputHeight
; top
+= TS
- 6) {
1745 if (fProgressMonitor
) {
1746 fProgressMonitor("Interpolate", percentage
, fProgressData
);
1747 percentage
+= percentageStep
;
1750 for (left
= 0; left
< fInputWidth
; left
+= TS
- 6) {
1751 memset(rgb
, 0, 12 * TS
* TS
);
1753 /* Interpolate green horizontally and vertically: */
1754 for (row
= top
< 2 ? 2 : top
; row
< top
+ TS
1755 && row
< fInputHeight
- 2; row
++) {
1756 col
= left
+ (FC(row
, left
) == 1);
1759 for (fc
= FC(row
, col
); col
< left
+ TS
1760 && col
< fInputWidth
- 2; col
+= 2) {
1761 pix
= fImageData
+ row
* fInputWidth
+ col
;
1762 val
= ((pix
[-1][1] + pix
[0][fc
] + pix
[1][1]) * 2
1763 - pix
[-2][fc
] - pix
[2][fc
]) >> 2;
1764 rgb
[0][row
- top
][col
- left
][1]
1765 = ULIM(val
, pix
[-1][1], pix
[1][1]);
1766 val
= ((pix
[-fInputWidth
][1] + pix
[0][fc
]
1767 + pix
[fInputWidth
][1]) * 2
1768 - pix
[-2 * fInputWidth
][fc
] - pix
[2 * fInputWidth
][fc
])
1770 rgb
[1][row
- top
][col
- left
][1] = ULIM(val
,
1771 pix
[-fInputWidth
][1], pix
[fInputWidth
][1]);
1775 /* Interpolate red and blue, and convert to CIELab: */
1776 for (d
= 0; d
< 2; d
++) {
1777 for (row
= top
+ 1; row
< top
+ TS
- 1
1778 && row
< fInputHeight
- 1; row
++) {
1779 for (col
= left
+ 1; col
< left
+ TS
- 1
1780 && col
< fInputWidth
- 1; col
++) {
1781 pix
= fImageData
+ row
* fInputWidth
+ col
;
1782 rix
= &rgb
[d
][row
- top
][col
- left
];
1783 if ((c
= 2 - FC(row
, col
)) == 1) {
1784 c
= FC(row
+ 1,col
);
1785 val
= pix
[0][1] + ((pix
[-1][2-c
] + pix
[1][2 - c
]
1786 - rix
[-1][1] - rix
[1][1] ) >> 1);
1787 rix
[0][2-c
] = CLIP(val
);
1788 val
= pix
[0][1] + ((pix
[-fInputWidth
][c
]
1789 + pix
[fInputWidth
][c
]
1790 - rix
[-TS
][1] - rix
[TS
][1] ) >> 1);
1792 val
= rix
[0][1] + ((pix
[-fInputWidth
- 1][c
]
1793 + pix
[-fInputWidth
+ 1][c
]
1794 + pix
[fInputWidth
- 1][c
]
1795 + pix
[fInputWidth
+ 1][c
]
1796 - rix
[-TS
- 1][1] - rix
[-TS
+ 1][1]
1797 - rix
[TS
- 1][1] - rix
[TS
+ 1][1] + 1) >> 2);
1799 rix
[0][c
] = CLIP(val
);
1801 rix
[0][c
] = pix
[0][c
];
1802 _CameraToCIELab(rix
[0], flab
);
1803 for (c
= 0; c
< 3; c
++) {
1804 lab
[d
][row
- top
][col
- left
][c
]
1805 = int16(64 * flab
[c
]);
1811 /* Build homogeneity maps from the CIELab images: */
1812 memset(homo
, 0, 2 * TS
* TS
);
1813 for (row
= top
+ 2; row
< top
+TS
-2 && row
< fInputHeight
; row
++) {
1815 for (col
= left
+ 2; col
< left
+ TS
- 2
1816 && col
< fInputWidth
; col
++) {
1818 for (d
= 0; d
< 2; d
++) {
1819 for (i
= 0; i
< 4; i
++) {
1820 ldiff
[d
][i
] = ABS(lab
[d
][tr
][tc
][0]
1821 - lab
[d
][tr
][tc
+dir
[i
]][0]);
1825 leps
= MIN(MAX(ldiff
[0][0],ldiff
[0][1]),
1826 MAX(ldiff
[1][2],ldiff
[1][3]));
1828 for (d
= 0; d
< 2; d
++) {
1829 for (i
= 0; i
< 4; i
++) {
1830 if (i
>> 1 == d
|| ldiff
[d
][i
] <= leps
) {
1831 abdiff
[d
][i
] = square(lab
[d
][tr
][tc
][1]
1832 - lab
[d
][tr
][tc
+dir
[i
]][1])
1833 + square(lab
[d
][tr
][tc
][2]
1834 - lab
[d
][tr
][tc
+dir
[i
]][2]);
1839 abeps
= MIN(MAX(abdiff
[0][0],abdiff
[0][1]),
1840 MAX(abdiff
[1][2],abdiff
[1][3]));
1842 for (d
=0; d
< 2; d
++) {
1843 for (i
=0; i
< 4; i
++) {
1844 if (ldiff
[d
][i
] <= leps
&& abdiff
[d
][i
] <= abeps
)
1851 /* Combine the most homogenous pixels for the final result: */
1852 for (row
= top
+ 3; row
< top
+ TS
- 3 && row
< fInputHeight
- 3;
1855 for (col
= left
+ 3; col
< left
+ TS
- 3
1856 && col
< fInputWidth
- 3; col
++) {
1858 for (d
= 0; d
< 2; d
++) {
1859 for (hm
[d
] = 0, i
= tr
- 1; i
<= tr
+ 1; i
++) {
1860 for (j
= tc
- 1; j
<= tc
+ 1; j
++) {
1861 hm
[d
] += homo
[d
][i
][j
];
1865 if (hm
[0] != hm
[1]) {
1866 for (c
= 0; c
< 3; c
++) {
1867 fImageData
[row
* fInputWidth
+ col
][c
]
1868 = rgb
[hm
[1] > hm
[0]][tr
][tc
][c
];
1871 for (c
= 0; c
< 3; c
++) {
1872 fImageData
[row
* fInputWidth
+ col
][c
]
1873 = (rgb
[0][tr
][tc
][c
] + rgb
[1][tr
][tc
][c
]) >> 1;
1886 DCRaw::_PseudoInverse(double (*in
)[3], double (*out
)[3], uint32 size
)
1888 double work
[3][6], num
;
1891 for (i
= 0; i
< 3; i
++) {
1892 for (j
= 0; j
< 6; j
++) {
1893 work
[i
][j
] = j
== i
+ 3;
1895 for (j
= 0; j
< 3; j
++) {
1896 for (k
= 0; k
< size
; k
++) {
1897 work
[i
][j
] += in
[k
][i
] * in
[k
][j
];
1902 for (i
= 0; i
< 3; i
++) {
1904 for (j
= 0; j
< 6; j
++) {
1907 for (k
= 0; k
< 3; k
++) {
1913 for (j
= 0; j
< 6; j
++) {
1914 work
[k
][j
] -= work
[i
][j
] * num
;
1919 for (i
= 0; i
< size
; i
++) {
1920 for (j
= 0; j
< 3; j
++) {
1921 for (out
[i
][j
] = k
=0; k
< 3; k
++) {
1922 out
[i
][j
] += work
[j
][k
+3] * in
[i
][k
];
1930 DCRaw::_ConvertToRGB()
1932 if (fProgressMonitor
!= NULL
)
1933 fProgressMonitor("Convert to RGB", 90, fProgressData
);
1935 uint32 row
, col
, c
, i
, j
, k
;
1936 float out
[3], out_cam
[3][4];
1937 double num
, inverse
[3][3];
1938 static const double xyzd50_srgb
[3][3] = {
1939 { 0.436083, 0.385083, 0.143055 },
1940 { 0.222507, 0.716888, 0.060608 },
1941 { 0.013930, 0.097097, 0.714022 }};
1942 static const double rgb_rgb
[3][3] = {
1943 { 1,0,0 }, { 0,1,0 }, { 0,0,1 }};
1944 static const double adobe_rgb
[3][3] = {
1945 { 0.715146, 0.284856, 0.000000 },
1946 { 0.000000, 1.000000, 0.000000 },
1947 { 0.000000, 0.041166, 0.958839 }};
1948 static const double wide_rgb
[3][3] = {
1949 { 0.593087, 0.404710, 0.002206 },
1950 { 0.095413, 0.843149, 0.061439 },
1951 { 0.011621, 0.069091, 0.919288 }};
1952 static const double prophoto_rgb
[3][3] = {
1953 { 0.529317, 0.330092, 0.140588 },
1954 { 0.098368, 0.873465, 0.028169 },
1955 { 0.016879, 0.117663, 0.865457 }};
1956 static const double (*out_rgb
[])[3]
1957 = { rgb_rgb
, adobe_rgb
, wide_rgb
, prophoto_rgb
, xyz_rgb
};
1958 static const char *name
[] = { "sRGB", "Adobe RGB (1998)", "WideGamut D65",
1959 "ProPhoto D65", "XYZ" };
1960 static const unsigned phead
[] = { 1024, 0, 0x2100000, 0x6d6e7472,
1961 0x52474220, 0x58595a20, 0, 0, 0, 0x61637370, 0, 0, 0x6e6f6e65,
1962 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d };
1963 unsigned pbody
[] = { 10,
1964 0x63707274, 0, 36, /* cprt */
1965 0x64657363, 0, 40, /* desc */
1966 0x77747074, 0, 20, /* wtpt */
1967 0x626b7074, 0, 20, /* bkpt */
1968 0x72545243, 0, 14, /* rTRC */
1969 0x67545243, 0, 14, /* gTRC */
1970 0x62545243, 0, 14, /* bTRC */
1971 0x7258595a, 0, 20, /* rXYZ */
1972 0x6758595a, 0, 20, /* gXYZ */
1973 0x6258595a, 0, 20 }; /* bXYZ */
1974 static const unsigned pwhite
[] = { 0xf351, 0x10000, 0x116cc };
1975 unsigned pcurve
[] = { 0x63757276, 0, 1, 0x1000000 };
1977 memcpy(out_cam
, fMeta
.rgb_camera
, sizeof(out_cam
));
1978 fRawColor
|= fColors
== 1 || fDocumentMode
1979 || fOutputColor
< 1 || fOutputColor
> 5;
1981 fOutputProfile
= (uint32
*)calloc(phead
[0], 1);
1982 if (fOutputProfile
== NULL
)
1983 throw (status_t
)B_NO_MEMORY
;
1985 memcpy(fOutputProfile
, phead
, sizeof(phead
));
1986 if (fOutputColor
== 5)
1987 fOutputProfile
[4] = fOutputProfile
[5];
1989 fOutputProfile
[0] = 132 + 12 * pbody
[0];
1990 for (i
= 0; i
< pbody
[0]; i
++) {
1991 fOutputProfile
[fOutputProfile
[0] / 4]
1992 = i
? (i
> 1 ? 0x58595a20 : 0x64657363) : 0x74657874;
1993 pbody
[i
*3+2] = fOutputProfile
[0];
1994 fOutputProfile
[0] += (pbody
[i
*3+3] + 3) & -4;
1997 memcpy(fOutputProfile
+ 32, pbody
, sizeof(pbody
));
1998 fOutputProfile
[pbody
[5] / 4 + 2] = strlen(name
[fOutputColor
- 1]) + 1;
1999 memcpy((char *)fOutputProfile
+ pbody
[8] + 8, pwhite
, sizeof(pwhite
));
2000 if (fOutputBitsPerSample
== 8) {
2002 pcurve
[3] = 0x2330000;
2004 pcurve
[3] = 0x1f00000;
2008 for (i
= 4; i
< 7; i
++) {
2009 memcpy((char *)fOutputProfile
+ pbody
[i
* 3 + 2], pcurve
,
2013 _PseudoInverse((double (*)[3])out_rgb
[fOutputColor
- 1], inverse
, 3);
2015 for (i
= 0; i
< 3; i
++) {
2016 for (j
= 0; j
< 3; j
++) {
2017 for (num
= k
=0; k
< 3; k
++) {
2018 num
+= xyzd50_srgb
[i
][k
] * inverse
[j
][k
];
2020 fOutputProfile
[pbody
[j
* 3 + 23] / 4 + i
+ 2]
2021 = uint32(num
* 0x10000 + 0.5);
2024 for (i
= 0; i
< phead
[0]/4; i
++) {
2025 fOutputProfile
[i
] = htonl(fOutputProfile
[i
]);
2027 strcpy((char *)fOutputProfile
+ pbody
[2] + 8,
2028 "auto-generated by dcraw");
2029 strcpy((char *)fOutputProfile
+ pbody
[5] + 12, name
[fOutputColor
- 1]);
2031 for (i
= 0; i
< 3; i
++) {
2032 for (j
= 0; j
< fColors
; j
++) {
2033 for (out_cam
[i
][j
] = k
= 0; k
< 3; k
++) {
2034 out_cam
[i
][j
] += out_rgb
[fOutputColor
-1][i
][k
]
2035 * fMeta
.rgb_camera
[k
][j
];
2043 fprintf(stderr
, "Building histograms...\n");
2045 fprintf(stderr
, "Converting to %s colorspace...\n",
2046 name
[fOutputColor
- 1]);
2050 ushort
* img
= fImageData
[0];
2051 memset(fHistogram
, 0, sizeof(int32
) * 0x2000 * 4);
2053 for (row
= 0; row
< fInputHeight
; row
++) {
2054 for (col
= 0; col
< fInputWidth
; col
++, img
+= 4) {
2056 out
[0] = out
[1] = out
[2] = 0;
2057 for (c
= 0; c
< fColors
; c
++) {
2058 out
[0] += out_cam
[0][c
] * img
[c
];
2059 out
[1] += out_cam
[1][c
] * img
[c
];
2060 out
[2] += out_cam
[2][c
] * img
[c
];
2062 for (c
= 0; c
< 3; c
++) {
2063 img
[c
] = CLIP((int)out
[c
]);
2065 } else if (fDocumentMode
)
2066 img
[0] = img
[FC(row
, col
)];
2068 for (c
= 0; c
< fColors
; c
++) {
2069 fHistogram
[img
[c
] >> 3][c
]++;
2074 if (fColors
== 4 && fOutputColor
)
2076 if (fDocumentMode
&& fFilters
)
2082 DCRaw::_GammaLookUpTable(uchar
* lut
)
2084 int32 percent
, val
, total
, i
;
2087 percent
= int32(fInputWidth
* fInputHeight
* 0.01);
2088 // 99th percentile white point
2090 // if (fuji_width) perc /= 2;
2094 for (uint32 c
= 0; c
< fColors
; c
++) {
2095 for (val
= 0x2000, total
= 0; --val
> 32;) {
2096 if ((total
+= fHistogram
[val
][c
]) > percent
)
2103 white
*= 8 / fBrightness
;
2105 for (i
= 0; i
< 0x10000; i
++) {
2107 val
= int32(256 * (!fUseGamma
? r
:
2109 r
<= 0.00304 ? r
*12.92 : pow(r
,2.5/6)*1.055-0.055));
2111 r
<= 0.018 ? r
*4.5 : pow(r
,0.45)*1.099-0.099));
2120 // #pragma mark - Lossless JPEG
2124 DCRaw::_InitDecoder()
2126 memset(fDecodeBuffer
, 0, sizeof(decode
) * kDecodeBufferCount
);
2127 fFreeDecode
= fDecodeBuffer
;
2131 /*! Construct a decode tree according the specification in *source.
2132 The first 16 bytes specify how many codes should be 1-bit, 2-bit
2133 3-bit, etc. Bytes after that are the leaf values.
2135 For example, if the source is
2137 { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
2138 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
2157 DCRaw::_MakeDecoder(const uchar
* source
, int level
)
2162 if ((uint8
*)fFreeDecode
> (uint8
*)fDecodeBuffer
2163 + sizeof(decode
) * kDecodeBufferCount
) {
2164 fprintf(stderr
, "decoder table overflow\n");
2165 throw (status_t
)B_ERROR
;
2168 struct decode
* current
= fFreeDecode
++;
2171 for (i
= next
= 0; i
<= fDecodeLeaf
&& next
< 16; ) {
2172 i
+= source
[next
++];
2175 if (i
> fDecodeLeaf
) {
2177 current
->branch
[0] = fFreeDecode
;
2178 _MakeDecoder(source
, level
+ 1);
2179 current
->branch
[1] = fFreeDecode
;
2180 _MakeDecoder(source
, level
+ 1);
2182 current
->leaf
= source
[16 + fDecodeLeaf
++];
2185 return (uchar
*)source
+ 16 + fDecodeLeaf
;
2189 /*! Not a full implementation of Lossless JPEG, just
2190 enough to decode Canon, Kodak and Adobe DNG images.
2193 DCRaw::_InitDecodeBits()
2195 fDecodeBits
= fDecodeBitsRead
= 0;
2196 fDecodeBitsReset
= false;
2200 /*! _GetDecodeBits(n) where 0 <= n <= 25 returns an n-bit integer
2203 DCRaw::_GetDecodeBits(uint32 numBits
)
2205 if (numBits
== 0 || fDecodeBitsReset
)
2208 while (fDecodeBitsRead
< numBits
) {
2209 uint8 c
= fRead
.Next
<uint8
>();
2210 if ((fDecodeBitsReset
= fDecodeBitsZeroAfterMax
2211 && c
== 0xff && fRead
.Next
<uint8
>()))
2213 fDecodeBits
= (fDecodeBits
<< 8) + c
;
2214 fDecodeBitsRead
+= 8;
2217 fDecodeBitsRead
-= numBits
;
2219 return fDecodeBits
<< (32 - numBits
- fDecodeBitsRead
) >> (32 - numBits
);
2224 DCRaw::_LosslessJPEGInit(struct jhead
* jh
, bool infoOnly
)
2230 for (i
= 0; i
< 4; i
++) {
2231 jh
->huff
[i
] = fFreeDecode
;
2234 jh
->restart
= INT_MAX
;
2236 uchar data
[0x10000], *dp
;
2238 if (data
[1] != 0xd8)
2243 tag
= data
[0] << 8 | data
[1];
2244 len
= (data
[2] << 8 | data
[3]) - 2;
2253 jh
->high
= data
[1] << 8 | data
[2];
2254 jh
->wide
= data
[3] << 8 | data
[4];
2261 for (dp
= data
; dp
< data
+len
&& *dp
< 4; ) {
2262 jh
->huff
[*dp
] = fFreeDecode
;
2263 dp
= _MakeDecoder(++dp
, 0);
2267 jh
->restart
= data
[0] << 8 | data
[1];
2270 } while (tag
!= 0xffda);
2275 jh
->row
= (ushort
*)calloc(jh
->wide
*jh
->clrs
, 2);
2276 if (jh
->row
== NULL
)
2277 throw (status_t
)B_NO_MEMORY
;
2279 fDecodeBitsZeroAfterMax
= true;
2285 DCRaw::_LosslessJPEGDiff(struct decode
*dindex
)
2287 while (dindex
->branch
[0]) {
2288 dindex
= dindex
->branch
[_GetDecodeBits(1)];
2291 int length
= dindex
->leaf
;
2292 if (length
== 16 && (!fDNGVersion
|| fDNGVersion
>= 0x1010000))
2295 int diff
= _GetDecodeBits(length
);
2296 if ((diff
& (1 << (length
- 1))) == 0)
2297 diff
-= (1 << length
) - 1;
2304 DCRaw::_LosslessJPEGRow(struct jhead
*jh
, int jrow
)
2306 if (jrow
* jh
->wide
% jh
->restart
== 0) {
2307 for (uint32 i
= 0; i
< 4; i
++) {
2308 jh
->vpred
[i
] = 1 << (jh
->bits
- 1);
2314 mark
= (mark
<< 8) + (c
= fRead
.Next
<uint8
>());
2315 } while (c
!= EOF
&& mark
>> 4 != 0xffd);
2320 uint16
* outp
= jh
->row
;
2322 for (int32 col
= 0; col
< jh
->wide
; col
++) {
2323 for (int32 c
= 0; c
< jh
->clrs
; c
++) {
2324 int32 diff
= _LosslessJPEGDiff(jh
->huff
[c
]);
2325 *outp
= col
? outp
[-jh
->clrs
]+diff
: (jh
->vpred
[c
] += diff
);
2332 // #pragma mark - RAW loaders
2336 DCRaw::_LoadRAWUnpacked(const image_data_info
& image
)
2338 uint32 rawWidth
= _Raw().width
;
2340 uint16
* pixel
= (uint16
*)calloc(rawWidth
, sizeof(uint16
));
2344 fRead
.Seek((fTopMargin
* rawWidth
+ fLeftMargin
) * sizeof(uint16
),
2347 for (uint32 row
= 0; row
< fInputHeight
; row
++) {
2348 fRead
.NextShorts(pixel
, rawWidth
);
2349 for (uint32 column
= 0; column
< fInputWidth
; column
++) {
2350 _Bayer(column
, row
) = pixel
[column
];
2358 /*! This is, for example, used in PENTAX RAW images
2361 DCRaw::_LoadRAWPacked12(const image_data_info
& image
)
2363 uint32 rawWidth
= _Raw().width
;
2367 for (uint32 row
= 0; row
< fInputHeight
; row
++) {
2368 for (uint32 column
= 0; column
< fInputWidth
; column
++) {
2369 //uint16 bits = _GetDecodeBits(12);
2370 _Bayer(column
, row
) = _GetDecodeBits(12);
2371 //fImageData[((row) >> fShrink)*fOutputWidth + ((column) >> fShrink)][FC(row,column)] = bits;
2373 for (uint32 column
= fInputWidth
* 3 / 2; column
< rawWidth
; column
++) {
2381 DCRaw::_MakeCanonDecoder(uint32 table
)
2383 static const uchar kFirstTree
[3][29] = {
2384 { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
2385 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
2386 { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0,
2387 0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff },
2388 { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0,
2389 0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff },
2391 static const uchar kSecondTree
[3][180] = {
2392 { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139,
2393 0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08,
2394 0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0,
2395 0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42,
2396 0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57,
2397 0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9,
2398 0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98,
2399 0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6,
2400 0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4,
2401 0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7,
2402 0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1,
2403 0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64,
2404 0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba,
2405 0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4,
2406 0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff },
2407 { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140,
2408 0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06,
2409 0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32,
2410 0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51,
2411 0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26,
2412 0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59,
2413 0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9,
2414 0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99,
2415 0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85,
2416 0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8,
2417 0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a,
2418 0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9,
2419 0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8,
2420 0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8,
2421 0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff },
2422 { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117,
2423 0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08,
2424 0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22,
2425 0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34,
2426 0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41,
2427 0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48,
2428 0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69,
2429 0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8,
2430 0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94,
2431 0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a,
2432 0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6,
2433 0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62,
2434 0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5,
2435 0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3,
2436 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff }
2444 _MakeDecoder(kFirstTree
[table
], 0);
2445 fSecondDecode
= fFreeDecode
;
2446 _MakeDecoder(kSecondTree
[table
], 0);
2450 /*! Return 0 if the image starts with compressed data,
2451 1 if it starts with uncompressed low-order bits.
2453 In Canon compressed data, 0xff is always followed by 0x00.
2456 DCRaw::_CanonHasLowBits()
2458 bool hasLowBits
= true;
2459 uchar test
[0x4000 - 540];
2461 fRead
.Seek(540, SEEK_SET
);
2462 fRead(test
, sizeof(test
));
2464 for (uint32 i
= 0; i
< sizeof(test
) - 1; i
++)
2465 if (test
[i
] == 0xff) {
2476 DCRaw::_LoadRAWCanonCompressed(const image_data_info
& image
)
2478 uint32 rawWidth
= _Raw().width
;
2479 int carry
= 0, pnum
= 0, base
[2];
2481 _MakeCanonDecoder(image
.compression
);
2483 uint16
* pixel
= (uint16
*)calloc(rawWidth
* 8, sizeof(*pixel
));
2485 throw (status_t
)B_NO_MEMORY
;
2487 bool hasLowBits
= _CanonHasLowBits();
2489 fMeta
.maximum
= 0x3ff;
2491 fRead
.Seek(540 + (hasLowBits
? _Raw().height
* rawWidth
/ 4 : 0),
2494 fDecodeBitsZeroAfterMax
= true;
2497 for (uint32 row
= 0; row
< _Raw().height
; row
+= 8) {
2498 for (uint32 block
= 0; block
< rawWidth
>> 3; block
++) {
2500 memset(diffbuf
, 0, sizeof diffbuf
);
2501 struct decode
* decode
= fDecodeBuffer
;
2503 for (uint32 i
= 0; i
< 64; i
++) {
2504 struct decode
* dindex
= decode
;
2505 while (dindex
->branch
[0]) {
2506 dindex
= dindex
->branch
[_GetDecodeBits(1)];
2508 int leaf
= dindex
->leaf
;
2509 decode
= fSecondDecode
;
2516 int len
= leaf
& 15;
2519 int diff
= _GetDecodeBits(len
);
2520 if ((diff
& (1 << (len
-1))) == 0)
2521 diff
-= (1 << len
) - 1;
2526 diffbuf
[0] += carry
;
2529 for (uint32 i
= 0; i
< 64; i
++) {
2530 if (pnum
++ % _Raw().width
== 0)
2531 base
[0] = base
[1] = 512;
2532 pixel
[(block
<< 6) + i
] = (base
[i
& 1] += diffbuf
[i
]);
2537 off_t savedOffset
= fRead
.Position();
2538 fRead
.Seek(26 + row
* _Raw().width
/ 4, SEEK_SET
);
2540 uint16
* pixelRow
= pixel
;
2541 for (uint32 i
= 0; i
< rawWidth
* 2; i
++) {
2542 uint8 c
= fRead
.Next
<uint8
>();
2544 for (uint32 r
= 0; r
< 8; r
+= 2, pixelRow
++) {
2545 uint32 val
= (*pixelRow
<< 2) + ((c
>> r
) & 3);
2546 if (rawWidth
== 2672 && val
< 512)
2552 fRead
.Seek(savedOffset
, SEEK_SET
);
2555 for (uint32 r
= 0; r
< 8; r
++) {
2556 uint32 irow
= row
- fTopMargin
+ r
;
2557 if (irow
>= fInputHeight
)
2560 for (uint32 col
= 0; col
< rawWidth
; col
++) {
2561 uint32 icol
= col
- fLeftMargin
;
2562 if (icol
< fInputWidth
)
2563 _Bayer(icol
, irow
) = pixel
[r
* rawWidth
+ col
];
2565 fMeta
.black
+= pixel
[r
* rawWidth
+ col
];
2572 if (rawWidth
> fInputWidth
)
2573 fMeta
.black
/= (rawWidth
- fInputWidth
) * fInputHeight
;
2578 DCRaw::_LoadRAWLosslessJPEG(const image_data_info
& image
)
2580 int jwide
, jrow
, jcol
, val
, jidx
, i
, j
, row
= 0, col
= 0;
2581 uint32 rawWidth
= _Raw().width
;
2585 if (_LosslessJPEGInit(&jh
, false) != B_OK
)
2586 throw (status_t
)B_NO_TRANSLATOR
;
2588 jwide
= jh
.wide
* jh
.clrs
;
2590 for (jrow
= 0; jrow
< jh
.high
; jrow
++) {
2591 _LosslessJPEGRow(&jh
, jrow
);
2593 for (jcol
= 0; jcol
< jwide
; jcol
++) {
2599 jidx
= jrow
* jwide
+ jcol
;
2600 i
= jidx
/ (fCR2Slice
[1] * jh
.high
);
2601 if ((j
= i
>= fCR2Slice
[0]))
2603 jidx
-= i
* (fCR2Slice
[1] * jh
.high
);
2604 row
= jidx
/ fCR2Slice
[1 + j
];
2605 col
= jidx
% fCR2Slice
[1 + j
] + i
* fCR2Slice
[1];
2608 if (_Raw().width
== 3984 && (col
-= 2) < 0) {
2613 if (uint32(row
- fTopMargin
) < fInputHeight
) {
2614 if (uint32(col
- fLeftMargin
) < fInputWidth
) {
2615 _Bayer(col
- fLeftMargin
, row
- fTopMargin
) = val
;
2621 if (++col
>= (int32
)rawWidth
) {
2628 //dump_to_disk(fImageData, fInputWidth * fColors * 100);
2631 if (rawWidth
> fInputWidth
)
2632 fMeta
.black
/= (rawWidth
- fInputWidth
) * fInputHeight
;
2639 DCRaw::_LoadRAW(const image_data_info
& image
)
2645 _LoadRAWCanonCompressed(image
);
2649 switch (image
.compression
) {
2650 case COMPRESSION_NONE
:
2651 _LoadRAWUnpacked(image
);
2653 case COMPRESSION_OLD_JPEG
:
2654 _LoadRAWLosslessJPEG(image
);
2655 //_LoadRAWCanonCompressed(image);
2657 case COMPRESSION_PACKBITS
:
2658 _LoadRAWPacked12(image
);
2662 fprintf(stderr
, "DCRaw: unknown compression: %" B_PRId32
"\n",
2664 throw (status_t
)B_NO_TRANSLATOR
;
2671 // #pragma mark - Image writers
2675 DCRaw::_WriteRGB32(image_data_info
& image
, uint8
* outputBuffer
)
2677 if (fProgressMonitor
!= NULL
)
2678 fProgressMonitor("Write RGB", 95, fProgressData
);
2680 uint8
* line
, lookUpTable
[0x10000];
2682 uint32 width
= image
.flip
> 4 ? fOutputHeight
: fOutputWidth
;
2683 uint32 height
= image
.flip
> 4 ? fOutputWidth
: fOutputHeight
;
2684 uint32 outputRow
= (4 * fOutputBitsPerSample
/ 8) * width
;
2685 uint32 outputOffset
= 0;
2687 line
= (uint8
*)malloc(outputRow
);
2689 throw (status_t
)B_NO_MEMORY
;
2691 memset(line
, 0, outputRow
);
2693 if (fOutputBitsPerSample
== 8)
2694 _GammaLookUpTable(lookUpTable
);
2696 int32 sourceOffset
= _FlipIndex(0, 0, image
.flip
);
2697 int32 colStep
= _FlipIndex(0, 1, image
.flip
) - sourceOffset
;
2698 int32 rowStep
= _FlipIndex(1, 0, image
.flip
)
2699 - _FlipIndex(0, width
, image
.flip
);
2701 TRACE(("flip = %ld, sourceOffset = %ld, colStep = %ld, rowStep = %ld, "
2702 "input: %lu x %lu, output: %lu x %lu\n", image
.flip
, sourceOffset
,
2703 colStep
, rowStep
, fInputWidth
, fInputHeight
, width
,
2706 if (fOutputBitsPerSample
== 8) {
2707 for (uint32 row
= 0; row
< height
; row
++, sourceOffset
+= rowStep
) {
2708 for (uint32 col
= 0; col
< width
; col
++, sourceOffset
+= colStep
) {
2709 line
[col
* 4 + 2] = lookUpTable
[fImageData
[sourceOffset
][0]];
2710 line
[col
* 4 + 1] = lookUpTable
[fImageData
[sourceOffset
][1]];
2711 line
[col
* 4 + 0] = lookUpTable
[fImageData
[sourceOffset
][2]];
2714 memcpy(&outputBuffer
[outputOffset
], line
, outputRow
);
2715 outputOffset
+= outputRow
;
2719 uint16
* ppm2
= (uint16
*)line
;
2720 for (row
= 0; row
< fOutputHeight
; row
++, soff
+= rstep
) {
2721 for (col
= 0; col
< fOutputWidth
; col
++, soff
+= cstep
) {
2722 FORCC ppm2
[col
*colors
+c
] = image
[soff
][c
];
2724 if (!output_tiff
&& htons(0x55aa) != 0x55aa)
2725 swab (ppm2
, ppm2
, width
*colors
*2);
2726 fwrite (ppm
, colors
*output_bps
/8, width
, ofp
);
2736 DCRaw::_WriteJPEG(image_data_info
& image
, uint8
* outputBuffer
)
2738 fRead(outputBuffer
, image
.bytes
);
2740 if (outputBuffer
[0] != 0xff || outputBuffer
[1] != 0xd8)
2741 throw (status_t
)B_NO_TRANSLATOR
;
2744 uint8
* thumb
= (uint8
*)malloc(image
.bytes
);
2746 throw (status_t
)B_NO_MEMORY
;
2748 fRead(thumb
, image
.bytes
);
2750 uint8
* data
= (uint8
*)fImageData
;
2754 if (strcmp((char *)thumb
+ 6, "Exif")) {
2755 // TODO: no EXIF data - write them ourselves
2758 memcpy(&data
[2], thumb
+ 2, image
.bytes
- 2);
2764 // #pragma mark - TIFF
2768 DCRaw::_ParseTIFFTimestamp(bool reversed
)
2774 for (int i
= 19; i
--; ) {
2775 str
[i
] = fRead
.Next
<uint8
>();
2781 memset(&t
, 0, sizeof t
);
2783 if (sscanf(str
, "%d:%d:%d %d:%d:%d", &t
.tm_year
, &t
.tm_mon
,
2784 &t
.tm_mday
, &t
.tm_hour
, &t
.tm_min
, &t
.tm_sec
) != 6)
2794 /*! Reads a TIFF tag and positions the file stream to its data section
2797 DCRaw::_ParseTIFFTag(off_t baseOffset
, tiff_tag
& tag
, off_t
& offset
)
2803 offset
= fRead
.Position() + 4;
2805 uint32 length
= tag
.length
;
2808 case TIFF_UINT16_TYPE
:
2809 case TIFF_INT16_TYPE
:
2813 case TIFF_UINT32_TYPE
:
2814 case TIFF_INT32_TYPE
:
2815 case TIFF_FLOAT_TYPE
:
2819 case TIFF_UFRACTION_TYPE
:
2820 case TIFF_FRACTION_TYPE
:
2821 case TIFF_DOUBLE_TYPE
:
2833 fRead
.Seek(baseOffset
+ position
, SEEK_SET
);
2839 DCRaw::_ParseTIFFImageFileDirectory(off_t baseOffset
, uint32 offset
)
2841 double analogBalance
[] = {1, 1, 1, 1};
2842 double xyz
[] = {1, 1, 1, 1};
2843 bool useColorMatrix
= false;
2844 double cameraCalibration
[4][4], colorMatrix
[4][3], cameraXYZ
[4][3];
2846 for (int32 j
= 0; j
< 4; j
++) {
2847 for (int32 i
= 0; i
< 4; i
++) {
2848 cameraCalibration
[j
][i
] = i
== j
;
2852 fRead
.Seek(baseOffset
+ offset
, SEEK_SET
);
2859 image_data_info
& image
= fImages
[fNumImages
];
2864 _ParseTIFFTag(baseOffset
, tag
, nextOffset
);
2865 TAG("TIFF tag: %u\n", tag
.tag
);
2870 printf("tag %u NOT HANDLED!\n", tag
.tag
);
2876 if (tag
.type
== 3 && tag
.length
== 1) {
2877 fMeta
.camera_multipliers
[(tag
.tag
- 17) * 2]
2878 = fRead
.Next
<uint16
>() / 256.0;
2882 case 23: // ISO speed
2883 fMeta
.iso_speed
= fRead
.Next(tag
.type
);
2889 fMeta
.camera_multipliers
[tag
.tag
- 0x24] = fRead
.Next
<uint16
>();
2893 if (tag
.length
< 50 || fMeta
.camera_multipliers
[0])
2896 fRead
.Stream().Seek(12, SEEK_CUR
);
2897 for (uint32 i
= 0; i
< 3; i
++) {
2898 fMeta
.camera_multipliers
[i
] = fRead
.Next
<uint16
>();
2902 case 2: // image width
2904 image
.width
= fRead
.Next(tag
.type
);
2907 case 3: // image height
2909 image
.height
= fRead
.Next(tag
.type
);
2912 case 258: // bits per sample
2913 image
.samples
= tag
.length
;
2914 image
.bits_per_sample
= fRead
.Next
<uint16
>();
2917 case 259: // compression
2918 image
.compression
= fRead
.Next
<uint16
>();
2921 case 262: // Photometric Interpretation
2922 image
.photometric_interpretation
= fRead
.Next
<uint16
>();
2925 case 271: // manufacturer
2926 fRead(fMeta
.manufacturer
, 64);
2930 fRead(fMeta
.model
, 64);
2933 case 273: // Strip Offset
2935 image
.data_offset
= baseOffset
+ fRead
.Next
<uint32
>();
2936 if (!image
.bits_per_sample
) {
2937 fRead
.Stream().Seek(image
.data_offset
, SEEK_SET
);
2939 if (_LosslessJPEGInit(&jh
, true) == B_OK
) {
2940 image
.compression
= 6;
2941 image
.width
= jh
.wide
<< (jh
.clrs
== 2);
2942 image
.height
= jh
.high
;
2943 image
.bits_per_sample
= jh
.bits
;
2944 image
.samples
= jh
.clrs
;
2949 case 274: // Orientation
2950 image
.flip
= fRead
.Next
<uint16
>();
2953 case 277: // Samples Per Pixel
2954 image
.samples
= fRead
.Next(tag
.type
);
2957 case 279: // Strip Byte Counts
2959 image
.bytes
= fRead
.Next
<uint32
>();
2962 case 305: // Software
2963 fRead(fMeta
.software
, 64);
2964 if (!strncmp(fMeta
.software
, "Adobe", 5)
2965 || !strncmp(fMeta
.software
, "dcraw", 5)
2966 || !strncmp(fMeta
.software
, "Bibble", 6)
2967 || !strncmp(fMeta
.software
, "Nikon Scan", 10)
2968 || !strcmp(fMeta
.software
,"Digital Photo Professional"))
2969 throw (status_t
)B_NO_TRANSLATOR
;
2972 case 306: // Date/Time
2973 fMeta
.timestamp
= _ParseTIFFTimestamp(false);
2977 case 323: // Tile Length
2978 tile_length
= fRead
.Next(type
);
2981 case 324: // Tile Offsets
2982 image
.data_offset
= tag
.length
> 1
2983 ? fRead
.Stream().Position() : fRead
.Next
<uint32
>();
2984 if (tag
.length
== 4)
2985 load_raw
= &CLASS sinar_4shot_load_raw
;
2989 case 330: // Sub IFDs
2990 if (!strcmp(fMeta
.model
, "DSLR-A100") && image
.width
== 3872) {
2991 // TODO: this might no longer work!
2992 image
.data_offset
= fRead
.Next
<uint32
>() + baseOffset
;
2996 while (tag
.length
--) {
2997 off_t nextOffset
= fRead
.Position() + sizeof(uint32
);
2999 fRead
.Seek(fRead
.Next
<uint32
>() + baseOffset
, SEEK_SET
);
3000 if (_ParseTIFFImageFileDirectory(baseOffset
) != B_OK
)
3004 fRead
.Seek(nextOffset
, SEEK_SET
);
3010 strcpy(fMeta
.manufacturer
, "Sarnoff");
3017 sony_offset
= get4();
3020 sony_length
= get4();
3028 for (uint32 i
= 0; i
< 4; i
++) {
3029 fMeta
.camera_multipliers
[i
^ (i
< 2)] = fRead
.Next
<uint16
>();
3033 case 33405: // Model 2
3034 fRead(fMeta
.model
+ 64, 64);
3038 case 33422: // CFA Pattern
3039 case 64777: // Kodak P-series
3041 if ((plen
=len
) > 16) plen
= 16;
3042 fread (cfa_pat
, 1, plen
, ifp
);
3043 for (colors
=cfa
=i
=0; i
< plen
; i
++) {
3044 colors
+= !(cfa
& (1 << cfa_pat
[i
]));
3045 cfa
|= 1 << cfa_pat
[i
];
3047 if (cfa
== 070) memcpy (cfa_pc
,"\003\004\005",3); /* CMY */
3048 if (cfa
== 072) memcpy (cfa_pc
,"\005\003\004\001",4); /* GMCY */
3054 fseek(ifp
, get4()+base
, SEEK_SET
);
3055 parse_kodak_ifd (base
);
3059 case 33434: // Exposure Time
3060 fMeta
.shutter
= fRead
.NextDouble(TIFF_FRACTION_TYPE
);
3063 case 33437: // Aperture
3064 fMeta
.aperture
= fRead
.NextDouble(TIFF_FRACTION_TYPE
);
3067 case 34306: // Leaf white balance
3068 for (uint32 i
= 0; i
< 4; i
++) {
3069 fMeta
.camera_multipliers
[i
^ 1] = 4096.0 / fRead
.Next
<uint16
>();
3074 case 34307: // Leaf Catch Light color matrix
3075 fread (software
, 1, 7, ifp
);
3076 if (strncmp(software
,"MATRIX",6))
3079 for (fRawColor
= i
=0; i
< 3; i
++) {
3080 FORC4
fscanf (ifp
, "%f", &rgb_cam
[i
][c
^1]);
3084 FORC4 num
+= rgb_cam
[i
][c
];
3085 FORC4 rgb_cam
[i
][c
] /= num
;
3088 case 34310: // Leaf metadata
3089 parse_mos (ftell(ifp
));
3091 strcpy(image
.manufacturer
, "Leaf");
3095 case 34665: // EXIF tag
3096 fRead
.Seek(fRead
.Next
<uint32
>() + baseOffset
, SEEK_SET
);
3098 fEXIFOffset
= fRead
.Position();
3099 fEXIFLength
= tag
.length
;
3101 _ParseEXIF(baseOffset
);
3105 case 34675: // InterColorProfile
3106 case 50831: // AsShotICCProfile
3107 profile_offset
= fRead
.Stream().Position();
3108 profile_length
= tag
.length
;
3111 case 37122: // Compressed Bits Per Pixel
3112 kodak_cbpp
= fRead
.Next
<uint32
>();
3116 case 37386: // Focal Length
3117 fMeta
.focal_length
= fRead
.NextDouble(TIFF_FRACTION_TYPE
);
3120 case 37393: // Image Number
3121 fMeta
.shot_order
= fRead
.Next(tag
.type
);
3125 case 37400: // old Kodak KDC tag
3126 for (fRawColor
= i
=0; i
< 3; i
++) {
3128 FORC3 rgb_cam
[i
][c
] = getrat();
3132 case 46275: // Imacon tags
3133 strcpy (make
, "Imacon");
3134 data_offset
= ftell(ifp
);
3138 fseek (ifp
, 78, SEEK_CUR
);
3140 raw_height
= get4();
3141 left_margin
= get4() & 7;
3142 width
= raw_width
- left_margin
- (get4() & 7);
3143 top_margin
= get4() & 7;
3144 height
= raw_height
- top_margin
- (get4() & 7);
3145 fseek (ifp
, 52, SEEK_CUR
);
3146 FORC3 cam_multipliers
[c
] = getreal(11);
3147 fseek (ifp
, 114, SEEK_CUR
);
3148 flip
= (get2() >> 7) * 90;
3149 if (width
* height
* 6 == ima_len
) {
3150 if (flip
% 180 == 90) SWAP(width
,height
);
3154 case 50454: /* Sinar tag */
3156 if (!(cbuf
= (char *) malloc(len
))) break;
3157 fread (cbuf
, 1, len
, ifp
);
3158 for (cp
= cbuf
-1; cp
&& cp
< cbuf
+len
; cp
= strchr(cp
,'\n'))
3159 if (!strncmp (++cp
,"Neutral ",8))
3160 sscanf (cp
+8, "%f %f %f", cam_multipliers
, cam_multipliers
+1, cam_multipliers
+2);
3165 case 50706: // DNG Version
3166 for (int32 i
= 0; i
< 4; i
++) {
3167 fDNGVersion
= (fDNGVersion
<< 8) + fRead
.Next
<uint8
>();
3172 case 50710: // CFAPlaneColor
3176 fread(cfa_pc
, 1, colors
, ifp
);
3178 FORCC tab
[cfa_pc
[c
]] = c
;
3181 filters
= filters
<< 2 | tab
[cfa_pat
[i
% plen
]];
3183 case 50711: // CFALayout
3186 filters
= 0x49494949;
3191 case 291: // Linearization Table
3193 _ParseLinearTable(tag
.length
);
3196 case 50714: /* BlackLevel */
3197 case 50715: /* BlackLevelDeltaH */
3198 case 50716: /* BlackLevelDeltaV */
3201 for (uint32 i
= 0; i
< tag
.length
; i
++) {
3202 black
+= fRead
.NextDouble(tag
.type
);
3204 fMeta
.black
+= int32(black
/ tag
.length
+ 0.5);
3208 case 50717: // White Level
3209 fMeta
.maximum
= fRead
.Next(tag
.type
);
3212 case 50718: // Default Scale
3213 fMeta
.pixel_aspect
= fRead
.NextDouble(TIFF_FRACTION_TYPE
);
3214 fMeta
.pixel_aspect
/= fRead
.NextDouble(TIFF_FRACTION_TYPE
);
3217 case 50721: // Color Matrix
3219 for (uint32 c
= 0; c
< fColors
; c
++) {
3220 for (uint32 j
= 0; j
< 3; j
++) {
3221 colorMatrix
[c
][j
] = fRead
.NextDouble(TIFF_FRACTION_TYPE
);
3224 useColorMatrix
= true;
3227 case 50723: // Camera Calibration
3229 for (uint32 i
= 0; i
< fColors
; i
++) {
3230 for (uint32 c
= 0; c
< fColors
; c
++) {
3231 cameraCalibration
[i
][c
] = fRead
.NextDouble(
3232 TIFF_FRACTION_TYPE
);
3236 case 50727: // Analog Balance
3237 for (uint32 c
= 0; c
< fColors
; c
++) {
3238 analogBalance
[c
] = fRead
.NextDouble(TIFF_FRACTION_TYPE
);
3239 //printf("ab: %g\n", analogBalance[c]);
3243 case 50728: /* AsShotNeutral */
3244 FORCC asn
[c
] = getreal(type
);
3246 case 50729: /* AsShotWhiteXY */
3249 xyz
[2] = 1 - xyz
[0] - xyz
[1];
3250 FORC3 xyz
[c
] /= kD65White
[c
];
3252 case 50740: /* DNGPrivateData */
3253 if (dng_version
) break;
3255 parse_minolta (j
= get4()+base
);
3257 fseek (ifp
, j
, SEEK_SET
);
3258 parse_tiff_ifd (base
);
3262 fRead
.NextShorts(fCR2Slice
, 3);
3265 case 50829: // Active Area
3266 fTopMargin
= fRead
.Next(tag
.type
);
3267 fLeftMargin
= fRead
.Next(tag
.type
);
3268 fInputHeight
= fRead
.Next(tag
.type
) - fTopMargin
;
3269 fInputWidth
= fRead
.Next(tag
.type
) - fLeftMargin
;
3272 case 64772: /* Kodak P-series */
3273 fseek (ifp
, 16, SEEK_CUR
);
3274 data_offset
= get4();
3275 fseek (ifp
, 28, SEEK_CUR
);
3276 data_offset
+= get4();
3277 load_raw
= &CLASS packed_12_load_raw
;
3280 fRead
.Seek(nextOffset
, SEEK_SET
);
3286 if (sony_length
&& (buf
= (unsigned *) malloc(sony_length
))) {
3287 fseek(ifp
, sony_offset
, SEEK_SET
);
3288 fread(buf
, sony_length
, 1, ifp
);
3289 sony_decrypt(buf
, sony_length
/ 4, 1, sony_key
);
3291 if ((ifp
= tmpfile())) {
3292 fwrite(buf
, sony_length
, 1, ifp
);
3293 fseek(ifp
, 0, SEEK_SET
);
3294 parse_tiff_ifd(-sony_offset
);
3302 for (uint32 i
= 0; i
< fColors
; i
++) {
3303 for (uint32 c
= 0; c
< fColors
; c
++) {
3304 cameraCalibration
[i
][c
] *= analogBalance
[i
];
3308 if (useColorMatrix
) {
3309 for (uint32 c
= 0; c
< fColors
; c
++) {
3310 for (uint32 i
= 0; i
< 3; i
++) {
3311 cameraXYZ
[c
][i
] = 0;
3312 for (uint32 j
= 0; j
< fColors
; j
++) {
3313 cameraXYZ
[c
][i
] += cameraCalibration
[c
][j
]
3314 * colorMatrix
[j
][i
] * xyz
[i
];
3318 _CameraXYZCoefficients(cameraXYZ
);
3323 FORCC pre_multipliers
[c
] = 1 / asn
[c
];
3325 if (!useColorMatrix
) {
3326 for (uint32 c
= 0; c
< fColors
; c
++) {
3327 fMeta
.pre_multipliers
[c
] /= cameraCalibration
[c
][c
];
3336 DCRaw::_ParseTIFFImageFileDirectory(off_t baseOffset
)
3338 while (fNumImages
< kImageBufferCount
) {
3344 status_t status
= _ParseTIFFImageFileDirectory(baseOffset
, offset
);
3356 DCRaw::_ParseTIFF(off_t baseOffset
)
3358 fRead
.Stream().Seek(baseOffset
, SEEK_SET
);
3362 if (endian
!= 'MM' && endian
!= 'II')
3363 return B_NO_TRANSLATOR
;
3365 #if B_HOST_IS_LENDIAN
3366 fRead
.SetSwap(endian
== 'MM');
3368 fRead
.SetSwap(endian
== 'II');
3372 // dummy, not used, should be 42 for actual TIFF images,
3373 // but may vary for RAW images
3375 _ParseTIFFImageFileDirectory(baseOffset
);
3378 uint32 maxSamples
= 0;
3380 if (fThumbIndex
>= 0 && _Thumb().data_offset
) {
3381 fRead
.Seek(_Thumb().data_offset
, SEEK_SET
);
3384 if (_LosslessJPEGInit(&jh
, true)) {
3385 _Thumb().bits_per_sample
= jh
.bits
;
3386 _Thumb().width
= jh
.wide
;
3387 _Thumb().height
= jh
.high
;
3388 _Thumb().bits_per_sample
= 16;
3392 // identify RAW image in list of images retrieved
3394 for (uint32 i
= 0; i
< fNumImages
; i
++) {
3395 if (maxSamples
< fImages
[i
].samples
)
3396 maxSamples
= fImages
[i
].samples
;
3398 if ((fImages
[i
].compression
!= COMPRESSION_OLD_JPEG
3399 || fImages
[i
].samples
!= 3)
3400 && _SupportsCompression(fImages
[i
])) {
3401 fImages
[i
].is_raw
= true;
3403 if (fRawIndex
< 0 || fImages
[i
].width
* fImages
[i
].height
3404 > _Raw().width
* _Raw().height
) {
3406 //fuji_secondary = _Raw().samples == 2;
3412 || (!fDNGVersion
&& _Raw().samples
== 3 && _Raw().bits_per_sample
== 8))
3413 throw (status_t
)B_NO_TRANSLATOR
;
3415 if (fRawIndex
>= 0) {
3416 fMeta
.raw_width
= _Raw().width
;
3417 fMeta
.raw_height
= _Raw().height
;
3421 fuji_width
*= (raw_width
+1)/2;
3422 if (tiff_ifd
[0].flip
) tiff_flip
= tiff_ifd
[0].flip
;
3423 if (raw
>= 0 && !load_raw
)
3424 switch (tiff_compress
) {
3426 load_raw
= tiff_bps
> 8 ?
3427 &CLASS unpacked_load_raw
: &CLASS eight_bit_load_raw
;
3428 if (tiff_ifd
[raw
].bytes
* 5 == raw_width
* raw_height
* 8)
3429 load_raw
= &CLASS olympus_e300_load_raw
;
3430 if (tiff_bps
== 12 && tiff_ifd
[raw
].phint
== 2)
3431 load_raw
= &CLASS olympus_cseries_load_raw
;
3433 case 6: case 7: case 99:
3434 load_raw
= &CLASS lossless_jpeg_load_raw
; break;
3436 load_raw
= &CLASS kodak_262_load_raw
; break;
3438 load_raw
= &CLASS packed_12_load_raw
; break;
3440 load_raw
= &CLASS pentax_k10_load_raw
; break;
3442 switch (tiff_ifd
[raw
].phint
) {
3443 case 2: load_raw
= &CLASS kodak_rgb_load_raw
; fFilters
= 0; break;
3444 case 6: load_raw
= &CLASS kodak_ycbcr_load_raw
; fFilters
= 0; break;
3445 case 32803: load_raw
= &CLASS kodak_65000_load_raw
;
3448 if (tiff_samples
== 3 && tiff_bps
== 8)
3449 if (!dng_version
) is_raw
= 0;
3454 thumb_misc
|= tiff_ifd
[thm
].samples
<< 5;
3455 switch (tiff_ifd
[thm
].comp
) {
3457 write_thumb
= &CLASS layer_thumb
;
3460 if (tiff_ifd
[thm
].bps
> 8)
3461 thumb_load_raw
= &CLASS kodak_thumb_load_raw
;
3463 write_thumb
= &CLASS ppm_thumb
;
3466 thumb_load_raw
= tiff_ifd
[thm
].phint
== 6 ?
3467 &CLASS kodak_ycbcr_load_raw
: &CLASS kodak_rgb_load_raw
;
3481 fRead
.Seek(0, SEEK_SET
);
3483 status_t status
= B_NO_TRANSLATOR
;
3485 fRead(header
, sizeof(header
));
3487 // check for TIFF-like files first
3489 uint16 endian
= *(uint16
*)&header
;
3490 if (endian
== 'II' || endian
== 'MM')
3491 status
= _ParseTIFF(0);
3496 // brush up some variables for later use
3498 fInputWidth
= _Raw().width
;
3499 fInputHeight
= _Raw().height
;
3503 if ((_Raw().width
| _Raw().height
) < 0)
3504 _Raw().width
= _Raw().height
= 0;
3505 if (fMeta
.maximum
== 0)
3506 fMeta
.maximum
= (1 << _Raw().bits_per_sample
) - 1;
3508 if (fFilters
== ~(uint32
)0)
3509 fFilters
= 0x94949494;
3510 if (fFilters
&& fColors
== 3) {
3511 for (int32 i
= 0; i
< 32; i
+= 4) {
3512 if ((fFilters
>> i
& 15) == 9)
3514 if ((fFilters
>> i
& 15) == 6)
3520 _AdobeCoefficients(fMeta
.manufacturer
, fMeta
.model
);
3522 // remove invalid images
3526 for (int32 i
= 0; i
< (int32
)fNumImages
; i
++) {
3527 if (fImages
[i
].width
== 0 || fImages
[i
].height
== 0
3528 || fImages
[i
].data_offset
== 0) {
3532 else if (i
< fRawIndex
)
3534 if (i
== fThumbIndex
)
3536 else if (i
< fThumbIndex
)
3539 if (i
< (int32
)fNumImages
) {
3540 memmove(&fImages
[i
], &fImages
[i
+ 1],
3541 sizeof(image_data_info
) * (fNumImages
- i
));
3544 } else if (fImages
[i
].is_raw
)
3548 // This is to prevent us from identifying TIFF images
3550 return B_NO_TRANSLATOR
;
3552 fMeta
.flip
= _Raw().flip
;
3558 DCRaw::ReadImageAt(uint32 index
, uint8
*& outputBuffer
, size_t& bufferSize
)
3560 if (index
>= fNumImages
)
3563 _CorrectIndex(index
);
3565 image_data_info
& image
= fImages
[index
];
3567 fShrink
= (fHalfSize
|| fThreshold
) && fFilters
;
3568 fOutputWidth
= (fInputWidth
+ fShrink
) >> fShrink
;
3569 fOutputHeight
= (fInputHeight
+ fShrink
) >> fShrink
;
3571 if (image
.flip
> 4) {
3573 image
.output_width
= fOutputHeight
;
3574 image
.output_height
= fOutputWidth
;
3576 image
.output_width
= fOutputWidth
;
3577 image
.output_height
= fOutputHeight
;
3581 bufferSize
= fOutputWidth
* 4 * fOutputHeight
;
3583 fImageData
= (uint16 (*)[4])calloc(fOutputWidth
* fOutputHeight
3584 * sizeof(*fImageData
) + 0, 1); //meta_length, 1);
3585 if (fImageData
== NULL
)
3586 throw (status_t
)B_NO_MEMORY
;
3588 bufferSize
= image
.bytes
+ sizeof(tiff_header
) + 10;
3589 // TIFF header plus EXIF identifier
3592 outputBuffer
= (uint8
*)malloc(bufferSize
);
3593 if (outputBuffer
== NULL
) {
3596 throw (status_t
)B_NO_MEMORY
;
3599 fRead
.Seek(image
.data_offset
, SEEK_SET
);
3605 //if (dark_frame) subtract (dark_frame);
3606 //quality = 2 + !fuji_width;
3608 if (fDocumentMode
< 2)
3611 _CameraToCIELab(NULL
, NULL
);
3613 if (fFilters
&& !fDocumentMode
) {
3617 else if (quality
< 3 || colors
> 3)
3624 if (fHightlight
> 1)
3625 _RecoverHighlights();
3626 if (use_fuji_rotate
) fuji_rotate();
3627 if (mix_green
&& (colors
= 3))
3628 for (i
=0; i
< height
*width
; i
++)
3629 image
[i
][1] = (image
[i
][1] + image
[i
][3]) >> 1;
3633 //if (use_fuji_rotate) stretch();
3635 _WriteRGB32(image
, outputBuffer
);
3637 _WriteJPEG(image
, outputBuffer
);
3648 DCRaw::GetMetaInfo(image_meta_info
& metaInfo
) const
3655 DCRaw::CountImages() const
3662 DCRaw::ImageAt(uint32 index
, image_data_info
& info
) const
3664 if (index
>= fNumImages
)
3667 _CorrectIndex(index
);
3669 info
= fImages
[index
];
3675 DCRaw::GetEXIFTag(off_t
& offset
, size_t& length
, bool& bigEndian
) const
3677 if (fEXIFOffset
< 0)
3678 return B_ENTRY_NOT_FOUND
;
3680 offset
= fEXIFOffset
;
3681 length
= fEXIFLength
;
3683 #if B_HOST_IS_LENDIAN
3684 bigEndian
= fRead
.IsSwapping();
3686 bigEndian
= !fRead
.IsSwapping();
3693 DCRaw::SetProgressMonitor(monitor_hook hook
, void* data
)
3695 fProgressMonitor
= hook
;
3696 fProgressData
= data
;
3701 DCRaw::SetHalfSize(bool half
)