xref: /haiku/src/add-ons/translators/raw/RAW.cpp (revision 1acbe440b8dd798953bec31d18ee589aa3f71b73)
1 /*
2  * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
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.
9  */
10 
11 
12 #include "RAW.h"
13 #include "ReadHelper.h"
14 
15 #include <Message.h>
16 #include <TranslationErrors.h>
17 
18 #include <ctype.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 
24 //#define TRACE(x) printf x
25 #define TRACE(x)
26 //#define TAG(x) printf x
27 #define TAG(x)
28 
29 #define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
30 #define LIM(x,min,max) MAX(min,MIN(x,max))
31 #define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
32 #define CLIP(x) LIM(x,0,65535)
33 #define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
34 
35 #define FC(row,col) \
36 	(fFilters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
37 
38 
39 static const uint32 kImageBufferCount = 10;
40 static const uint32 kDecodeBufferCount = 2048;
41 
42 const double xyz_rgb[3][3] = {			/* XYZ from RGB */
43   { 0.412453, 0.357580, 0.180423 },
44   { 0.212671, 0.715160, 0.072169 },
45   { 0.019334, 0.119193, 0.950227 } };
46 const float d65_white[3] = { 0.950456, 1, 1.088754 };
47 
48 struct decode {
49 	struct decode *branch[2];
50 	int32	leaf;
51 };
52 
53 struct jhead {
54 	int		bits, high, wide, clrs, restart, vpred[4];
55 	struct decode *huff[4];
56 	uint16*	row;
57 };
58 
59 struct tiff_header {
60 	uint16	order, magic;
61 	int32	image_file_directory;
62 	uint16	pad, ntag;
63 	struct tiff_tag tag[15];
64 	int32	next_image_file_directory;
65 	uint16	pad2, nexif;
66 	struct tiff_tag exif[4];
67 	int16	bps[4];
68 	int32	rat[6];
69 	char make[64], model[64], soft[32], date[20];
70 };
71 
72 
73 template<class T> inline T
74 square(const T& value)
75 {
76 	return value * value;
77 }
78 
79 
80 //	#pragma mark -
81 
82 
83 DCRaw::DCRaw(BPositionIO& stream)
84 	:
85 	fRead(stream),
86 	fNumImages(0),
87 	fRawIndex(-1),
88 	fThumbIndex(-1),
89 	fDNGVersion(0),
90 	fIsTIFF(false),
91 	fThreshold(0),
92 	fHalfSize(true),
93 	fUseCameraWhiteBalance(true),
94 	fUseAutoWhiteBalance(true),
95 	fRawColor(true),
96 	fUseGamma(true),
97 	fBrightness(1.0f),
98 	fOutputColor(1),
99 	fHighlight(0),
100 	fDocumentMode(0),
101 	fOutputWidth(0),
102 	fOutputHeight(0),
103 	fInputWidth(0),
104 	fInputHeight(0),
105 	fTopMargin(0),
106 	fLeftMargin(0),
107 	fColors(3),
108 	fOutputProfile(NULL),
109 	fOutputBitsPerSample(8),
110 	fDecodeLeaf(0),
111 	fDecodeBitsZeroAfterMax(false),
112 	fFilters(~0)
113 {
114 	fImages = new image_data_info[kImageBufferCount];
115 	fDecodeBuffer = new decode[kDecodeBufferCount];
116 	fCurve = new uint16[0x1000];
117 	for (uint32 i = 0; i < 0x1000; i++) {
118 		fCurve[i] = i;
119 	}
120 
121 	cbrt = new float[0x10000];
122 	fHistogram = (int32 (*)[4])calloc(sizeof(int32) * 0x2000 * 4, 1);
123 
124 	memset(fImages, 0, sizeof(image_data_info) * kImageBufferCount);
125 	memset(&fMeta, 0, sizeof(image_meta_info));
126 	memset(fUserMultipliers, 0, sizeof(fUserMultipliers));
127 	memset(fWhite, 0, sizeof(fWhite));
128 
129 	fMeta.camera_multipliers[0] = -1;
130 	fCR2Slice[0] = 0;
131 }
132 
133 
134 DCRaw::~DCRaw()
135 {
136 	delete[] fImages;
137 	delete[] fDecodeBuffer;
138 	delete[] fCurve;
139 
140 	delete[] cbrt;
141 	free(fHistogram);
142 }
143 
144 
145 int32
146 DCRaw::_AllocateImage()
147 {
148 	if (fNumImages + 1 == kImageBufferCount)
149 		throw (status_t)B_ERROR;
150 
151 	return fNumImages++;
152 }
153 
154 
155 image_data_info&
156 DCRaw::_Raw()
157 {
158 	if (fRawIndex < 0)
159 		fRawIndex = _AllocateImage();
160 	if (fRawIndex < 0)
161 		throw (status_t)B_ERROR;
162 
163 	return fImages[fRawIndex];
164 }
165 
166 
167 image_data_info&
168 DCRaw::_Thumb()
169 {
170 	if (fThumbIndex < 0)
171 		fThumbIndex = _AllocateImage();
172 	if (fThumbIndex < 0)
173 		throw (status_t)B_ERROR;
174 
175 	return fImages[fThumbIndex];
176 }
177 
178 
179 //! Make sure that the raw image always comes first
180 void
181 DCRaw::_CorrectIndex(uint32& index) const
182 {
183 	if (fRawIndex > 0) {
184 		if (index == 0)
185 			index = fRawIndex;
186 		else if (index <= (uint32)fRawIndex)
187 			index--;
188 	}
189 }
190 
191 
192 inline uint16&
193 DCRaw::_Bayer(int32 column, int32 row)
194 {
195 	return fImageData[((row) >> fShrink) * fOutputWidth
196 		+ ((column) >> fShrink)][FC(row, column)];
197 }
198 
199 
200 inline int32
201 DCRaw::_FilterCoefficient(int32 x, int32 y)
202 {
203 	static const char filter[16][16] = {
204 		{ 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
205 		{ 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
206 		{ 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
207 		{ 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
208 		{ 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
209 		{ 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
210 		{ 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
211 		{ 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
212 		{ 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
213 		{ 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
214 		{ 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
215 		{ 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
216 		{ 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
217 		{ 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
218 		{ 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
219 		{ 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 }
220 	};
221 
222 	if (fFilters != 1)
223 		return FC(y, x);
224 
225 	return filter[(y + fTopMargin) & 15][(x + fLeftMargin) & 15];
226 }
227 
228 
229 inline int32
230 DCRaw::_FlipIndex(uint32 row, uint32 col, uint32 flip)
231 {
232 	if (flip & 4)
233 		SWAP(row, col);
234 	if (flip & 2)
235 		row = fInputHeight - 1 - row;
236 	if (flip & 1)
237 		col = fInputWidth - 1 - col;
238 
239 	return row * fInputWidth + col;
240 }
241 
242 
243 bool
244 DCRaw::_IsCanon() const
245 {
246 	return !strncasecmp(fMeta.manufacturer, "Canon", 5);
247 }
248 
249 
250 bool
251 DCRaw::_IsKodak() const
252 {
253 	return !strncasecmp(fMeta.manufacturer, "Kodak", 5);
254 }
255 
256 
257 bool
258 DCRaw::_IsNikon() const
259 {
260 	return !strncasecmp(fMeta.manufacturer, "Nikon", 5);
261 }
262 
263 
264 bool
265 DCRaw::_IsPentax() const
266 {
267 	return !strncasecmp(fMeta.manufacturer, "Pentax", 6);
268 }
269 
270 
271 bool
272 DCRaw::_IsSamsung() const
273 {
274 	return !strncasecmp(fMeta.manufacturer, "Samsung", 7);
275 }
276 
277 
278 void
279 DCRaw::_ParseThumbTag(off_t baseOffset, uint32 offsetTag, uint32 lengthTag)
280 {
281 	uint16 entries;
282 	fRead(entries);
283 
284 	while (entries--) {
285 		off_t nextOffset;
286 		tiff_tag tag;
287 		_ParseTIFFTag(baseOffset, tag, nextOffset);
288 
289 		if (tag.tag == offsetTag)
290 			_Thumb().data_offset = fRead.Next<uint32>();
291 		if (tag.tag == lengthTag)
292 			_Thumb().bytes = fRead.Next<uint32>();
293 
294 		fRead.Seek(nextOffset, SEEK_SET);
295 	}
296 }
297 
298 
299 void
300 DCRaw::_ParseManufacturerTag(off_t baseOffset)
301 {
302 	static const uchar xlat[2][256] = {
303 		{
304 			0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
305 			0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
306 			0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
307 			0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
308 			0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
309 			0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
310 			0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
311 			0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
312 			0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
313 			0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
314 			0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
315 			0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
316 			0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
317 			0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
318 			0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
319 			0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7
320 		},
321 		{
322 			0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
323 			0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
324 			0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
325 			0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
326 			0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
327 			0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
328 			0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
329 			0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
330 			0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
331 			0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
332 			0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
333 			0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
334 			0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
335 			0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
336 			0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
337 			0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f
338 		}
339 	};
340 
341 	uint32 ver97 = 0, serial = 0;
342 	uchar buf97[324], ci, cj, ck;
343 	bool originalSwap = fRead.IsSwapping();
344 	image_data_info& image = fImages[fNumImages];
345 
346 	// The MakerNote might have its own TIFF header (possibly with
347 	// its own byte-order!), or it might just be a table.
348 
349 	char type[10];
350 	fRead(type, sizeof(type));
351 
352 	if (!strncmp(type, "KDK", 3)
353 		|| !strncmp(type, "VER", 3)
354 		|| !strncmp(type, "IIII", 4)
355 		|| !strncmp(type, "MMMM", 4)) {
356 		// these aren't TIFF tables
357 		return;
358 	}
359 	if (!strncmp(type, "KC", 2)			// Konica KD-400Z, KD-510Z
360 		|| !strncmp(type, "MLY", 3)) {	// Minolta DiMAGE G series
361 		fRead.SetSwap(B_HOST_IS_LENDIAN != 0);
362 			// this chunk is always in big endian
363 
364 		uint32 whiteBalance[4] = {0, 0, 0, 0};
365 
366 		off_t offset;
367 	    while ((offset = fRead.Position()) < image.data_offset && offset < 16384) {
368 			whiteBalance[0] = whiteBalance[2];
369 			whiteBalance[2] = whiteBalance[1];
370 			whiteBalance[1] = whiteBalance[3];
371 
372 			whiteBalance[3] = fRead.Next<uint16>();
373 			if (whiteBalance[1] == 256 && whiteBalance[3] == 256
374 				&& whiteBalance[0] > 256 && whiteBalance[0] < 640
375 				&& whiteBalance[2] > 256 && whiteBalance[2] < 640) {
376 				for (uint32 i = 0; i < 4; i++) {
377 					fMeta.camera_multipliers[i] = whiteBalance[i];
378 				}
379 			}
380 		}
381 		goto quit;
382 	}
383 	if (!strcmp(type, "Nikon")) {
384 		baseOffset = fRead.Position();
385 
386 		uint16 endian;
387 		fRead(endian);
388 
389 #if B_HOST_IS_LENDIAN
390 		fRead.SetSwap(endian == 'MM');
391 #else
392 		fRead.SetSwap(endian == 'II');
393 #endif
394 
395 		if (fRead.Next<uint16>() != 42)
396 			goto quit;
397 
398 		uint32 offset = fRead.Next<uint32>();
399 		fRead.Seek(offset - 8, SEEK_CUR);
400 	} else if (!strncmp(type, "FUJIFILM", 8)
401 		|| !strncmp(type, "SONY", 4)
402 		|| !strcmp(type, "Panasonic")) {
403 		fRead.SetSwap(B_HOST_IS_BENDIAN != 0);
404 			// this chunk is always in little endian
405 		fRead.Seek(2, SEEK_CUR);
406 	} else if (!strcmp(type, "OLYMP")
407 		|| !strcmp(type, "LEICA")
408 		|| !strcmp(type, "Ricoh")
409 		|| !strcmp(type, "EPSON"))
410 		fRead.Seek(-2, SEEK_CUR);
411 	else if (!strcmp(type, "AOC") || !strcmp(type, "QVC"))
412 		fRead.Seek(-4, SEEK_CUR);
413 	else
414 		fRead.Seek(-10, SEEK_CUR);
415 
416 	uint16 entries;
417 	fRead(entries);
418 	if (entries > 1000)
419 		return;
420 
421 	while (entries--) {
422 		off_t nextOffset;
423 		tiff_tag tag;
424 		_ParseTIFFTag(baseOffset, tag, nextOffset);
425 		TAG(("Manufacturer tag %u (type %u, length %lu)\n", tag.tag, tag.type, tag.length));
426 
427 		if (strstr(fMeta.manufacturer, "PENTAX")) {
428 			if (tag.tag == 0x1b)
429 				tag.tag = 0x1018;
430 			if (tag.tag == 0x1c)
431 				tag.tag = 0x1017;
432 		} else if (tag.tag == 2 && strstr(fMeta.manufacturer, "NIKON")) {
433 			fRead.Next<uint16>();
434 				// ignored
435 			fMeta.iso_speed = fRead.Next<uint16>();
436 		}
437 
438 		if (tag.tag == 4 && tag.length == 27) {
439 			fRead.Next<uint32>();
440 				// ignored
441 			fMeta.iso_speed = 50 * pow(2, fRead.Next<uint16>() / 32.0 - 4);
442 			fRead.Next<uint16>();
443 				// ignored
444 			fMeta.aperture = pow(2, fRead.Next<uint16>() / 64.0);
445 			fMeta.shutter = pow(2, fRead.Next<int16>() / -32.0);
446 		}
447 		if (tag.tag == 8 && tag.type == 4)
448 			fMeta.shot_order = fRead.Next<uint32>();
449 		if (tag.tag == 0xc && tag.length == 4) {
450 			fMeta.camera_multipliers[0] = fRead.NextDouble(TIFF_FRACTION_TYPE);
451 			fMeta.camera_multipliers[2] = fRead.NextDouble(TIFF_FRACTION_TYPE);
452 		}
453 		if (tag.tag == 0x10 && tag.type == 4)
454 			fUniqueID = fRead.Next<uint32>();
455 		if (tag.tag == 0x11) {
456 			if (_ParseTIFFImageFileDirectory(baseOffset, fRead.Next<uint32>()) == B_OK)
457 				fNumImages++;
458 		}
459 		if (tag.tag == 0x14 && tag.length == 2560 && tag.type == 7) {
460 			fRead.Seek(1248, SEEK_CUR);
461 			goto get2_256;
462 		}
463 		if (tag.tag == 0x1d) {
464 			int c;
465 			while ((c = fRead.Next<uint8>()) && c != EOF) {
466 				serial = serial * 10 + (isdigit(c) ? c - '0' : c % 10);
467 			}
468 		}
469 		if (tag.tag == 0x81 && tag.type == 4) {
470 			_Raw().data_offset = fRead.Next<uint32>();
471 			fRead.Seek(_Raw().data_offset + 41, SEEK_SET);
472 			_Raw().height = fRead.Next<uint16>() * 2;
473 			_Raw().width  = fRead.Next<uint16>();
474 			fFilters = 0x61616161;
475 		}
476 		if ((tag.tag == 0x81 && tag.type == 7)
477 			|| (tag.tag == 0x100 && tag.type == 7)
478 			|| (tag.tag == 0x280 && tag.type == 1)) {
479 			_Thumb().data_offset = fRead.Position();
480 			_Thumb().bytes = tag.length;
481 		}
482 		if (tag.tag == 0x88 && tag.type == 4 && (_Thumb().data_offset = fRead.Next<uint32>())) {
483 			_Thumb().data_offset += baseOffset;
484 		}
485 		if (tag.tag == 0x89 && tag.type == 4)
486 			_Thumb().bytes = fRead.Next<uint32>();
487 		if (tag.tag == 0x8c)
488 			fCurveOffset = fRead.Position() + 2112;
489 		if (tag.tag == 0x96)
490 			fCurveOffset = fRead.Position() + 2;
491 		if (tag.tag == 0x97) {
492 			for (uint32 i = 0; i < 4; i++) {
493 				ver97 = (ver97 << 4) + fRead.Next<uint8>() - '0';
494 			}
495 			switch (ver97) {
496 				case 0x100:
497 					fRead.Seek(68, SEEK_CUR);
498 					for (uint32 i = 0; i < 4; i++) {
499 						fMeta.camera_multipliers[(i >> 1) | ((i & 1) << 1)]
500 							= fRead.Next<uint16>();
501 					}
502 					break;
503 				case 0x102:
504 					fRead.Seek(6, SEEK_CUR);
505 					goto get2_rggb;
506 				case 0x103:
507 					fRead.Seek(16, SEEK_CUR);
508 					for (uint32 i = 0; i < 4; i++) {
509 						fMeta.camera_multipliers[i] = fRead.Next<uint16>();
510 					}
511 					break;
512 			}
513 			if (ver97 >> 8 == 2) {
514 				if (ver97 != 0x205)
515 					fRead.Seek(280, SEEK_CUR);
516 				fRead(buf97, sizeof(buf97));
517 			}
518 		}
519 		if (tag.tag == 0xa7 && ver97 >> 8 == 2) {
520 			ci = xlat[0][serial & 0xff];
521 			cj = xlat[1][fRead.Next<uint8>() ^ fRead.Next<uint8>()
522 				^ fRead.Next<uint8>() ^ fRead.Next<uint8>()];
523 			ck = 0x60;
524 			for (uint32 i = 0; i < 324; i++) {
525 				buf97[i] ^= (cj += ci * ck++);
526 			}
527 			for (uint32 i = 0; i < 4; i++) {
528 				uint16* data = (uint16*)(buf97 + (ver97 == 0x205 ? 14 : 6) + i*2);
529 
530 				if (fRead.IsSwapping()) {
531 					fMeta.camera_multipliers[i ^ (i >> 1)] = __swap_int16(*data);
532 				} else {
533 					fMeta.camera_multipliers[i ^ (i >> 1)] = *data;
534 				}
535 			}
536 		}
537 		if (tag.tag == 0x200 && tag.length == 4) {
538 			fMeta.black = (fRead.Next<uint16>() + fRead.Next<uint16>()
539 				+ fRead.Next<uint16>() + fRead.Next<uint16>()) / 4;
540 		}
541 		if (tag.tag == 0x201 && tag.length == 4)
542 			goto get2_rggb;
543 		if (tag.tag == 0x401 && tag.length == 4) {
544 			fMeta.black = (fRead.Next<uint32>() + fRead.Next<uint32>()
545 				+ fRead.Next<uint32>() + fRead.Next<uint32>()) / 4;
546 		}
547 		if (tag.tag == 0xe01) {
548 			// Nikon Capture Note
549 			bool previousSwap = fRead.IsSwapping();
550 			fRead.SetSwap(B_HOST_IS_BENDIAN != 0);
551 				// this chunk is always in little endian
552 
553 			off_t offset = 22;
554 			fRead.Seek(offset, SEEK_CUR);
555 
556 			int32 i = 0;
557 
558 			for (; offset + 22 < tag.length; offset += 22 + i) {
559 				tag.tag = fRead.Next<uint32>();
560 				fRead.Seek(14, SEEK_CUR);
561 				i = fRead.Next<uint32>() - 4;
562 				if (tag.tag == 0x76a43207)
563 					fMeta.flip = fRead.Next<uint16>();
564 				else
565 					fRead.Seek(i, SEEK_CUR);
566 			}
567 
568 			fRead.SetSwap(previousSwap);
569 		}
570 		if (tag.tag == 0xe80 && tag.length == 256 && tag.type == 7) {
571 			fRead.Seek(48, SEEK_CUR);
572 			fMeta.camera_multipliers[0] = fRead.Next<uint16>() * 508 * 1.078 / 0x10000;
573 			fMeta.camera_multipliers[2] = fRead.Next<uint16>() * 382 * 1.173 / 0x10000;
574 		}
575 		if (tag.tag == 0xf00 && tag.type == 7) {
576 			if (tag.length == 614)
577 				fRead.Seek(176, SEEK_CUR);
578 			else if (tag.length == 734 || tag.length == 1502)
579 				fRead.Seek(148, SEEK_CUR);
580 			else
581 				goto next;
582 			goto get2_256;
583 		}
584 		if (tag.tag == 0x1011 && tag.length == 9 && fUseCameraWhiteBalance) {
585 			for (uint32 i = 0; i < 3; i++) {
586 				for (uint32 j = 0; j < 3; j++) {
587 					fMeta.rgb_camera[i][j] = fRead.Next<int16>() / 256.0;
588 				}
589 			}
590 			fRawColor = fMeta.rgb_camera[0][0] < 1;
591 		}
592 		if (tag.tag == 0x1012 && tag.length == 4) {
593 			fMeta.black = 0;
594 			for (uint32 i = 0; i < 4; i++) {
595 				fMeta.black += fRead.Next<uint16>() << 2;
596 			}
597 		}
598 		if (tag.tag == 0x1017)
599 			fMeta.camera_multipliers[0] = fRead.Next<uint16>() / 256.0;
600 		if (tag.tag == 0x1018)
601 			fMeta.camera_multipliers[2] = fRead.Next<uint16>() / 256.0;
602 
603 		if (tag.tag == 0x2011 && tag.length == 2) {
604 get2_256:
605 			bool previousSwap = fRead.IsSwapping();
606 			fRead.SetSwap(B_HOST_IS_LENDIAN != 0);
607 				// this chunk is always in big endian
608 
609 			fMeta.camera_multipliers[0] = fRead.Next<uint16>() / 256.0;
610 			fMeta.camera_multipliers[2] = fRead.Next<uint16>() / 256.0;
611 
612 			fRead.SetSwap(previousSwap);
613 		}
614 
615 		if (tag.tag == 0x2020)
616 			_ParseThumbTag(baseOffset, 257, 258);
617 		if (tag.tag == 0xb028) {
618 			fRead.Seek(fRead.Next<uint32>(), SEEK_SET);
619 			_ParseThumbTag(baseOffset, 136, 137);
620 		}
621 
622 		if (tag.tag == 0x4001) {
623 			{
624 				off_t offset = tag.length == 582 ? 50 : tag.length == 653 ? 68 : 126;
625 				fRead.Seek(offset, SEEK_CUR);
626 			}
627 get2_rggb:
628 			for (uint32 i = 0; i < 4; i++) {
629 				fMeta.camera_multipliers[i ^ (i >> 1)] = fRead.Next<uint16>();
630 			}
631 		}
632 
633 next:
634     	fRead.Seek(nextOffset, SEEK_SET);
635 	}
636 
637 quit:
638 	fRead.SetSwap(originalSwap);
639 }
640 
641 
642 void
643 DCRaw::_ParseEXIF(off_t baseOffset)
644 {
645 	bool kodak = !strncmp(fMeta.manufacturer, "EASTMAN", 7);
646 
647 	uint16 entries;
648 	fRead(entries);
649 
650 	while (entries--) {
651 		off_t nextOffset;
652 		tiff_tag tag;
653 		_ParseTIFFTag(baseOffset, tag, nextOffset);
654 		TAG(("EXIF tag %u (type %u, length %lu)\n", tag.tag, tag.type, tag.length));
655 
656 		switch (tag.tag) {
657 #if 0
658 			default:
659 				printf("  unhandled EXIF tag %u\n", tag.tag);
660 				break;
661 #endif
662 			case 33434:
663 				fMeta.shutter = fRead.NextDouble(TIFF_FRACTION_TYPE);
664 				break;
665 			case 33437:
666 				fMeta.aperture = fRead.NextDouble(TIFF_FRACTION_TYPE);
667 				break;
668 			case 34855:
669 				fMeta.iso_speed = fRead.Next<uint16>();
670 				break;
671 			case 36867:
672 			case 36868:
673 				fMeta.timestamp = _ParseTIFFTimestamp(false);
674 				break;
675 			case 37377:
676 			{
677 				double expo;
678 				if ((expo = -fRead.NextDouble(TIFF_FRACTION_TYPE)) < 128)
679 					fMeta.shutter = pow(2, expo);
680 				break;
681 			}
682 			case 37378:
683 				fMeta.aperture = pow(2, fRead.NextDouble(TIFF_FRACTION_TYPE) / 2);
684 				break;
685 			case 37386:
686 				fMeta.focal_length = fRead.NextDouble(TIFF_FRACTION_TYPE);
687 				break;
688 			case 37500:
689 				_ParseManufacturerTag(baseOffset);
690 				break;
691 			case 40962:
692 				if (kodak)
693 					_Raw().width = fRead.Next<uint32>();
694 				break;
695 			case 40963:
696 				if (kodak)
697 					_Raw().height = fRead.Next<uint32>();
698 				break;
699 			case 41730:
700 				if (fRead.Next<uint32>() == 0x20002) {
701 					fEXIFFilters = 0;
702 					for (uint32 c = 0; c < 8; c += 2) {
703 						fEXIFFilters |= fRead.Next<uint8>() * 0x01010101 << c;
704 					}
705 				}
706 				break;
707 		}
708 
709 		fRead.Seek(nextOffset, SEEK_SET);
710 	}
711 }
712 
713 
714 void
715 DCRaw::_ParseLinearTable(uint32 length)
716 {
717 	if (length > 0x1000)
718 		length = 0x1000;
719 
720 	fRead.NextShorts(fCurve, length);
721 
722 	for (uint32 i = length; i < 0x1000; i++) {
723 		fCurve[i] = fCurve[i - 1];
724 	}
725 
726 	fMeta.maximum = fCurve[0xfff];
727 }
728 
729 
730 /*!
731 	This (lengthy) method contains fixes for the values in the image data to
732 	be able to actually read the image data correctly.
733 */
734 void
735 DCRaw::_FixupValues()
736 {
737 	// PENTAX and SAMSUNG section
738 	// (Samsung sells rebranded Pentax cameras)
739 
740 	if (_IsPentax() || _IsSamsung()) {
741 		if (fInputWidth == 3936 && fInputHeight == 2624) {
742 			// Pentax K10D and Samsumg GX10
743 			fInputWidth = 3896;
744 			fInputHeight = 2616;
745 		}
746 	}
747 
748 	// CANON
749 
750 	if (_IsCanon()) {
751 		bool isCR2 = false;
752 		if (strstr(fMeta.model, "EOS D2000C")) {
753 			fFilters = 0x61616161;
754 			fMeta.black = fCurve[200];
755 		}
756 
757 		switch (_Raw().width) {
758 			case 2144:
759 				fInputHeight = 1550;
760 				fInputWidth = 2088;
761 				fTopMargin = 8;
762 				fLeftMargin = 4;
763 				if (!strcmp(fMeta.model, "PowerShot G1")) {
764 					fColors = 4;
765 					fFilters = 0xb4b4b4b4;
766 				}
767 				break;
768 
769 			case 2224:
770 				fInputHeight = 1448;
771 				fInputWidth = 2176;
772 				fTopMargin = 6;
773 				fLeftMargin = 48;
774 				break;
775 
776 			case 2376:
777 				fInputHeight = 1720;
778 				fInputWidth = 2312;
779 				fTopMargin = 6;
780 				fLeftMargin = 12;
781 				break;
782 
783 			case 2672:
784 				fInputHeight = 1960;
785 				fInputWidth = 2616;
786 				fTopMargin = 6;
787 				fLeftMargin = 12;
788 				break;
789 
790 			case 3152:
791 				fInputHeight = 2056;
792 				fInputWidth = 3088;
793 				fTopMargin = 12;
794 				fLeftMargin = 64;
795 				if (fUniqueID == 0x80000170)
796 					_AdobeCoefficients("Canon", "EOS 300D");
797 				fMeta.maximum = 0xfa0;
798 				break;
799 
800 			case 3160:
801 				fInputHeight = 2328;
802 				fInputWidth = 3112;
803 				fTopMargin = 12;
804 				fLeftMargin = 44;
805 				break;
806 
807 			case 3344:
808 				fInputHeight = 2472;
809 				fInputWidth = 3288;
810 				fTopMargin = 6;
811 				fLeftMargin = 4;
812 				break;
813 
814 			case 3516:
815 				fTopMargin = 14;
816 				fLeftMargin = 42;
817 				if (fUniqueID == 0x80000189)
818 					_AdobeCoefficients("Canon", "EOS 350D");
819 				isCR2 = true;
820 				break;
821 
822 			case 3596:
823 				fTopMargin = 12;
824 				fLeftMargin = 74;
825 				isCR2 = true;
826 				break;
827 
828 			case 3948:
829 				fTopMargin = 18;
830 				fLeftMargin = 42;
831 				fInputHeight -= 2;
832 				if (fUniqueID == 0x80000236)
833 					_AdobeCoefficients("Canon", "EOS 400D");
834 				isCR2 = true;
835 				break;
836 
837 			case 3984:
838 				fTopMargin  = 20;
839 				fLeftMargin = 76;
840 				fInputHeight -= 2;
841 				fMeta.maximum = 0x3bb0;
842 				isCR2 = true;
843 				break;
844 
845 			case 4476:
846 				fTopMargin  = 34;
847 				fLeftMargin = 90;
848 				fMeta.maximum = 0xe6c;
849 				isCR2 = true;
850 				break;
851 
852 			case 5108:
853 				fTopMargin  = 13;
854 				fLeftMargin = 98;
855 				fMeta.maximum = 0xe80;
856 				isCR2 = true;
857 				break;
858 		}
859 
860 		if (isCR2) {
861 			fInputHeight -= fTopMargin;
862 			fInputWidth -= fLeftMargin;
863 		}
864 	}
865 }
866 
867 
868 //	#pragma mark - Image Conversion
869 
870 
871 void
872 DCRaw::_ScaleColors()
873 {
874 	int dblack, c, val, sum[8];
875 	uint32 row, col, x, y;
876 	double dsum[8], dmin, dmax;
877 	float scale_mul[4];
878 
879 	if (fUseCameraWhiteBalance && fMeta.camera_multipliers[0] != -1) {
880 		memset(sum, 0, sizeof(sum));
881 		for (row = 0; row < 8; row++) {
882 			for (col = 0; col < 8; col++) {
883 				c = FC(row, col);
884 				if ((val = fWhite[row][col] - fMeta.black) > 0)
885 					sum[c] += val;
886 				sum[c + 4]++;
887 			}
888 		}
889 
890 		if (sum[0] && sum[1] && sum[2] && sum[3]) {
891 			for (int c = 0; c < 4; c++) {
892 				fMeta.pre_multipliers[c] = (float)sum[c+4] / sum[c];
893 			}
894 		} else if (fMeta.camera_multipliers[0] && fMeta.camera_multipliers[2]) {
895 			memcpy(fMeta.pre_multipliers, fMeta.camera_multipliers,
896 				sizeof(fMeta.pre_multipliers));
897 		} else
898 			fprintf(stderr, "Cannot use camera white balance.\n");
899 	} else if (fUseAutoWhiteBalance) {
900 		memset(dsum, 0, sizeof(dsum));
901 		for (row = 0; row < fOutputHeight - 7; row += 8) {
902 			for (col = 0; col < fOutputWidth - 7; col += 8) {
903 				memset(sum, 0, sizeof(sum));
904 				for (y = row; y < row + 8; y++) {
905 					for (x = col; x < col + 8; x++) {
906 						for (int c = 0; c < 4; c++) {
907 							val = fImageData[y * fOutputWidth + x][c];
908 							if (!val)
909 								continue;
910 							if (val > fMeta.maximum - 25)
911 								goto skip_block;
912 							val -= fMeta.black;
913 							if (val < 0)
914 								val = 0;
915 							sum[c] += val;
916 							sum[c+4]++;
917 						}
918 					}
919 				}
920 
921 				for (c=0; c < 8; c++) {
922 					dsum[c] += sum[c];
923 				}
924 
925 			skip_block:
926 				continue;
927 			}
928 		}
929 		for (int c = 0; c < 4; c++) {
930 			if (dsum[c])
931 				fMeta.pre_multipliers[c] = dsum[c + 4] / dsum[c];
932 		}
933 	}
934 
935 
936 	if (fUserMultipliers[0])
937 		memcpy(fMeta.pre_multipliers, fUserMultipliers, sizeof(fMeta.pre_multipliers));
938 	if (fMeta.pre_multipliers[3] == 0)
939 		fMeta.pre_multipliers[3] = fColors < 4 ? fMeta.pre_multipliers[1] : 1;
940 
941 	dblack = fMeta.black;
942 	if (fThreshold)
943 		_WaveletDenoise();
944 
945 	fMeta.maximum -= fMeta.black;
946 	for (dmin = DBL_MAX, dmax = c = 0; c < 4; c++) {
947 		if (dmin > fMeta.pre_multipliers[c])
948 			dmin = fMeta.pre_multipliers[c];
949 		if (dmax < fMeta.pre_multipliers[c])
950 			dmax = fMeta.pre_multipliers[c];
951 	}
952 
953 	if (!fHighlight)
954 		dmax = dmin;
955 
956 	for (int c = 0; c < 4; c++) {
957 		scale_mul[c] = (fMeta.pre_multipliers[c] /= dmax) * 65535.0 / fMeta.maximum;
958 	}
959 
960 #if 1
961 	if (1/*verbose*/) {
962 		fprintf(stderr, "Scaling with black %d, multipliers", dblack);
963 		for (int c = 0; c < 4; c++) {
964 			fprintf(stderr, " %f", fMeta.pre_multipliers[c]);
965 		}
966 		fputc('\n', stderr);
967 	}
968 #endif
969 
970 	for (row = 0; row < fOutputHeight; row++) {
971 		for (col = 0; col < fOutputWidth; col++) {
972 			for (int c = 0; c < 4; c++) {
973 				val = fImageData[row * fOutputWidth + col][c];
974 				if (!val)
975 					continue;
976 				val -= fMeta.black;
977 				val = int(val * scale_mul[c]);
978 				fImageData[row * fOutputWidth + col][c] = CLIP(val);
979 			}
980 		}
981 	}
982 }
983 
984 
985 void
986 DCRaw::_WaveletDenoise()
987 {
988 }
989 
990 
991 void
992 DCRaw::_PreInterpolate()
993 {
994 	uint32 row, col;
995 
996 	if (fShrink) {
997 		if (fHalfSize) {
998 			fInputHeight = fOutputHeight;
999 			fInputWidth = fOutputWidth;
1000 			fFilters = 0;
1001 		} else {
1002 			uint16 (*data)[4] = (uint16 (*)[4])calloc(fInputHeight
1003 				* fInputWidth, sizeof(*data));
1004 			if (data == NULL)
1005 				throw (status_t)B_NO_MEMORY;
1006 
1007 			for (row = 0; row < fInputHeight; row++) {
1008 				for (col = 0; col < fInputWidth; col++) {
1009 					data[row * fInputWidth + col][FC(row, col)] = _Bayer(col, row);
1010 				}
1011 			}
1012 
1013 			free(fImageData);
1014 			fImageData = data;
1015 			fShrink = 0;
1016 		}
1017 	}
1018 
1019 	if (fFilters && fColors == 3) {
1020 //		if ((mix_green = four_color_rgb))
1021 //			fColors++;
1022 //		else
1023 		{
1024 			for (row = FC(1,0) >> 1; row < fInputHeight; row += 2) {
1025 				for (col = FC(row, 1) & 1; col < fInputWidth; col += 2) {
1026 					fImageData[row * fInputWidth + col][1]
1027 						= fImageData[row * fInputWidth + col][3];
1028 				}
1029 			}
1030 			fFilters &= ~((fFilters & 0x55555555) << 1);
1031 		}
1032 	}
1033 }
1034 
1035 
1036 void
1037 DCRaw::_CameraToCIELab(ushort cam[4], float lab[3])
1038 {
1039 	if (cam == NULL) {
1040 		for (uint32 i = 0; i < 0x10000; i++) {
1041 			float r = i / 65535.0;
1042 			cbrt[i] = r > 0.008856 ? pow(r, 1 / 3.0) : 7.787 * r + 16 / 116.0;
1043 		}
1044 		for (uint32 i = 0; i < 3; i++) {
1045 			for (uint32 j = 0; j < fColors; j++) {
1046 				xyz_cam[i][j] = 0;
1047 				for (uint32 k = 0; k < 3; k++) {
1048 					xyz_cam[i][j] += xyz_rgb[i][k] * fMeta.rgb_camera[k][j] / d65_white[i];
1049 				}
1050 			}
1051 		}
1052 	} else {
1053 		float xyz[3];
1054 		xyz[0] = xyz[1] = xyz[2] = 0.5;
1055 		for (uint32 c = 0; c < fColors; c++) {
1056 			xyz[0] += xyz_cam[0][c] * cam[c];
1057 			xyz[1] += xyz_cam[1][c] * cam[c];
1058 			xyz[2] += xyz_cam[2][c] * cam[c];
1059 		}
1060 		xyz[0] = cbrt[CLIP((int) xyz[0])];
1061 		xyz[1] = cbrt[CLIP((int) xyz[1])];
1062 		xyz[2] = cbrt[CLIP((int) xyz[2])];
1063 		lab[0] = 116 * xyz[1] - 16;
1064 		lab[1] = 500 * (xyz[0] - xyz[1]);
1065 		lab[2] = 200 * (xyz[1] - xyz[2]);
1066 	}
1067 }
1068 
1069 
1070 void
1071 DCRaw::_CameraXYZCoefficients(double cam_xyz[4][3])
1072 {
1073 	double cam_rgb[4][3], inverse[4][3], num;
1074 	uint32 i, j, k;
1075 
1076 	// Multiply out XYZ colorspace
1077 	for (i = 0; i < fColors; i++)	{
1078 		for (j = 0; j < 3; j++) {
1079 			for (cam_rgb[i][j] = k = 0; k < 3; k++) {
1080 				cam_rgb[i][j] += cam_xyz[i][k] * xyz_rgb[k][j];
1081 			}
1082 		}
1083 	}
1084 
1085 	// Normalize cam_rgb so that cam_rgb * (1,1,1) is (1,1,1,1)
1086 	for (i = 0; i < fColors; i++) {
1087 		for (num = j = 0; j < 3; j++) {
1088 			num += cam_rgb[i][j];
1089 		}
1090 		for (j = 0; j < 3; j++) {
1091 			cam_rgb[i][j] /= num;
1092 		}
1093 		fMeta.pre_multipliers[i] = 1 / num;
1094 	}
1095 
1096 	_PseudoInverse(cam_rgb, inverse, fColors);
1097 
1098 	fRawColor = false;
1099 	for (i = 0; i < 3; i++) {
1100 		for (j=0; j < fColors; j++) {
1101 			fMeta.rgb_camera[i][j] = inverse[j][i];
1102 		}
1103 	}
1104 }
1105 
1106 
1107 /*!
1108 	Thanks to Adobe for providing these excellent CAM -> XYZ matrices!
1109 */
1110 void
1111 DCRaw::_AdobeCoefficients(char *make, char *model)
1112 {
1113 	static const struct {
1114 		const char *prefix;
1115 		short black, trans[12];
1116 	} table[] = {
1117 		{ "Canon EOS D2000", 0,
1118 		{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
1119 		{ "Canon EOS D6000", 0,
1120 		{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
1121 		{ "Canon EOS D30", 0,
1122 		{ 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } },
1123 		{ "Canon EOS D60", 0,
1124 		{ 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } },
1125 		{ "Canon EOS 5D", 0,
1126 		{ 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } },
1127 		{ "Canon EOS 20Da", 0,
1128 		{ 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } },
1129 		{ "Canon EOS 20D", 0,
1130 		{ 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } },
1131 		{ "Canon EOS 30D", 0,
1132 		{ 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } },
1133 		{ "Canon EOS 350D", 0,
1134 		{ 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } },
1135 		{ "Canon EOS 400D", 0,
1136 		{ 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } },
1137 		{ "Canon EOS-1Ds Mark II", 0,
1138 		{ 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } },
1139 		{ "Canon EOS-1D Mark II N", 0,
1140 		{ 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
1141 		{ "Canon EOS-1D Mark II", 0,
1142 		{ 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } },
1143 		{ "Canon EOS-1DS", 0,
1144 		{ 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } },
1145 		{ "Canon EOS-1D", 0,
1146 		{ 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } },
1147 		{ "Canon EOS", 0,
1148 		{ 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
1149 		{ "Canon PowerShot A50", 0,
1150 		{ -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } },
1151 		{ "Canon PowerShot A5", 0,
1152 		{ -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } },
1153 		{ "Canon PowerShot G1", 0,
1154 		{ -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } },
1155 		{ "Canon PowerShot G2", 0,
1156 		{ 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } },
1157 		{ "Canon PowerShot G3", 0,
1158 		{ 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } },
1159 		{ "Canon PowerShot G5", 0,
1160 		{ 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } },
1161 		{ "Canon PowerShot G6", 0,
1162 		{ 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } },
1163 		{ "Canon PowerShot Pro1", 0,
1164 		{ 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } },
1165 		{ "Canon PowerShot Pro70", 34,
1166 		{ -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } },
1167 		{ "Canon PowerShot Pro90", 0,
1168 		{ -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } },
1169 		{ "Canon PowerShot S30", 0,
1170 		{ 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } },
1171 		{ "Canon PowerShot S40", 0,
1172 		{ 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } },
1173 		{ "Canon PowerShot S45", 0,
1174 		{ 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } },
1175 		{ "Canon PowerShot S50", 0,
1176 		{ 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } },
1177 		{ "Canon PowerShot S60", 0,
1178 		{ 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } },
1179 		{ "Canon PowerShot S70", 0,
1180 		{ 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } },
1181 		{ "Canon PowerShot A610", 0, /* DJC */
1182 		{ 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } },
1183 		{ "Canon PowerShot A620", 0, /* DJC */
1184 		{ 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } },
1185 		{ "Canon PowerShot S3 IS", 0, /* DJC */
1186 		{ 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } },
1187 		{ "Contax N Digital", 0,
1188 		{ 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } },
1189 		{ "EPSON R-D1", 0,
1190 		{ 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } },
1191 		{ "FUJIFILM FinePix E550", 0,
1192 		{ 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
1193 		{ "FUJIFILM FinePix E900", 0,
1194 		{ 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } },
1195 		{ "FUJIFILM FinePix F8", 0,
1196 		{ 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
1197 		{ "FUJIFILM FinePix F7", 0,
1198 		{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
1199 		{ "FUJIFILM FinePix S20Pro", 0,
1200 		{ 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
1201 		{ "FUJIFILM FinePix S2Pro", 128,
1202 		{ 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } },
1203 		{ "FUJIFILM FinePix S3Pro", 0,
1204 		{ 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
1205 		{ "FUJIFILM FinePix S5000", 0,
1206 		{ 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } },
1207 		{ "FUJIFILM FinePix S5100", 0,
1208 		{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
1209 		{ "FUJIFILM FinePix S5500", 0,
1210 		{ 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
1211 		{ "FUJIFILM FinePix S5200", 0,
1212 		{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
1213 		{ "FUJIFILM FinePix S5600", 0,
1214 		{ 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
1215 		{ "FUJIFILM FinePix S6", 0,
1216 		{ 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } },
1217 		{ "FUJIFILM FinePix S7000", 0,
1218 		{ 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
1219 		{ "FUJIFILM FinePix S9000", 0,
1220 		{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
1221 		{ "FUJIFILM FinePix S9500", 0,
1222 		{ 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
1223 		{ "FUJIFILM FinePix S9100", 0,
1224 		{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
1225 		{ "FUJIFILM FinePix S9600", 0,
1226 		{ 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
1227 		{ "Imacon Ixpress", 0,	/* DJC */
1228 		{ 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } },
1229 		{ "KODAK NC2000", 0,	/* DJC */
1230 		{ 16475,-6903,-1218,-851,10375,477,2505,-7,1020 } },
1231 		{ "Kodak DCS315C", 8,
1232 		{ 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } },
1233 		{ "Kodak DCS330C", 8,
1234 		{ 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } },
1235 		{ "KODAK DCS420", 0,
1236 		{ 10868,-1852,-644,-1537,11083,484,2343,628,2216 } },
1237 		{ "KODAK DCS460", 0,
1238 		{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
1239 		{ "KODAK EOSDCS1", 0,
1240 		{ 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
1241 		{ "KODAK EOSDCS3B", 0,
1242 		{ 9898,-2700,-940,-2478,12219,206,1985,634,1031 } },
1243 		{ "Kodak DCS520C", 180,
1244 		{ 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
1245 		{ "Kodak DCS560C", 188,
1246 		{ 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
1247 		{ "Kodak DCS620C", 180,
1248 		{ 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } },
1249 		{ "Kodak DCS620X", 185,
1250 		{ 13095,-6231,154,12221,-21,-2137,895,4602,2258 } },
1251 		{ "Kodak DCS660C", 214,
1252 		{ 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } },
1253 		{ "Kodak DCS720X", 0,
1254 		{ 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } },
1255 		{ "Kodak DCS760C", 0,
1256 		{ 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } },
1257 		{ "Kodak DCS Pro SLR", 0,
1258 		{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
1259 		{ "Kodak DCS Pro 14nx", 0,
1260 		{ 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
1261 		{ "Kodak DCS Pro 14", 0,
1262 		{ 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } },
1263 		{ "Kodak ProBack645", 0,
1264 		{ 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } },
1265 		{ "Kodak ProBack", 0,
1266 		{ 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } },
1267 		{ "KODAK P712", 0,
1268 		{ 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } },
1269 		{ "KODAK P850", 0,
1270 		{ 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } },
1271 		{ "KODAK P880", 0,
1272 		{ 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } },
1273 		{ "Leaf CMost", 0,
1274 		{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
1275 		{ "Leaf Valeo 6", 0,
1276 		{ 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
1277 		{ "Leaf Aptus 65", 0,
1278 		{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
1279 		{ "Leaf Aptus 75", 0,
1280 		{ 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
1281 		{ "Leaf", 0,
1282 		{ 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
1283 		{ "Micron 2010", 110,	/* DJC */
1284 		{ 16695,-3761,-2151,155,9682,163,3433,951,4904 } },
1285 		{ "Minolta DiMAGE 5", 0,
1286 		{ 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } },
1287 		{ "Minolta DiMAGE 7Hi", 0,
1288 		{ 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } },
1289 		{ "Minolta DiMAGE 7", 0,
1290 		{ 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } },
1291 		{ "Minolta DiMAGE A1", 0,
1292 		{ 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } },
1293 		{ "MINOLTA DiMAGE A200", 0,
1294 		{ 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } },
1295 		{ "Minolta DiMAGE A2", 0,
1296 		{ 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } },
1297 		{ "Minolta DiMAGE Z2", 0,	/* DJC */
1298 		{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
1299 		{ "MINOLTA DYNAX 5", 0,
1300 		{ 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } },
1301 		{ "MINOLTA DYNAX 7", 0,
1302 		{ 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } },
1303 		{ "NIKON D100", 0,
1304 		{ 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } },
1305 		{ "NIKON D1H", 0,
1306 		{ 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } },
1307 		{ "NIKON D1X", 0,
1308 		{ 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } },
1309 		{ "NIKON D1", 0,	/* multiplied by 2.218750, 1.0, 1.148438 */
1310 		{ 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } },
1311 		{ "NIKON D2H", 0,
1312 		{ 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } },
1313 		{ "NIKON D2X", 0,
1314 		{ 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } },
1315 		{ "NIKON D40", 0,
1316 		{ 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } },
1317 		{ "NIKON D50", 0,
1318 		{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
1319 		{ "NIKON D70", 0,
1320 		{ 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
1321 		{ "NIKON D80", 0,
1322 		{ 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } },
1323 		{ "NIKON D200", 0,
1324 		{ 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
1325 		{ "NIKON E950", 0,		/* DJC */
1326 		{ -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
1327 		{ "NIKON E995", 0,	/* copied from E5000 */
1328 		{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
1329 		{ "NIKON E2500", 0,
1330 		{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
1331 		{ "NIKON E4300", 0, /* copied from Minolta DiMAGE Z2 */
1332 		{ 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
1333 		{ "NIKON E4500", 0,
1334 		{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
1335 		{ "NIKON E5000", 0,
1336 		{ -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
1337 		{ "NIKON E5400", 0,
1338 		{ 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } },
1339 		{ "NIKON E5700", 0,
1340 		{ -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } },
1341 		{ "NIKON E8400", 0,
1342 		{ 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } },
1343 		{ "NIKON E8700", 0,
1344 		{ 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
1345 		{ "NIKON E8800", 0,
1346 		{ 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } },
1347 		{ "OLYMPUS C5050", 0,
1348 		{ 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } },
1349 		{ "OLYMPUS C5060", 0,
1350 		{ 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } },
1351 		{ "OLYMPUS C7070", 0,
1352 		{ 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } },
1353 		{ "OLYMPUS C70", 0,
1354 		{ 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } },
1355 		{ "OLYMPUS C80", 0,
1356 		{ 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } },
1357 		{ "OLYMPUS E-10", 0,
1358 		{ 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } },
1359 		{ "OLYMPUS E-1", 0,
1360 		{ 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
1361 		{ "OLYMPUS E-20", 0,
1362 		{ 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } },
1363 		{ "OLYMPUS E-300", 0,
1364 		{ 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
1365 		{ "OLYMPUS E-330", 0,
1366 		{ 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } },
1367 		{ "OLYMPUS E-400", 0,
1368 		{ 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } },
1369 		{ "OLYMPUS E-500", 0,
1370 		{ 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } },
1371 		{ "OLYMPUS SP350", 0,
1372 		{ 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } },
1373 		{ "OLYMPUS SP3", 0,
1374 		{ 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } },
1375 		{ "OLYMPUS SP500UZ", 0,
1376 		{ 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } },
1377 		{ "OLYMPUS SP510UZ", 0,
1378 		{ 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } },
1379 		{ "PENTAX *ist DL2", 0,
1380 		{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
1381 		{ "PENTAX *ist DL", 0,
1382 		{ 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } },
1383 		{ "PENTAX *ist DS2", 0,
1384 		{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
1385 		{ "PENTAX *ist DS", 0,
1386 		{ 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } },
1387 		{ "PENTAX *ist D", 0,
1388 		{ 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } },
1389 		{ "PENTAX K10D", 0,
1390 		{ 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } },
1391 		{ "PENTAX K1", 0,
1392 		{ 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } },
1393 		{ "Panasonic DMC-FZ30", 0,
1394 		{ 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
1395 		{ "Panasonic DMC-FZ50", 0,	/* aka "LEICA V-LUX1" */
1396 		{ 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
1397 		{ "Panasonic DMC-L1", 0,	/* aka "LEICA DIGILUX 3" */
1398 		{ 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
1399 		{ "Panasonic DMC-LC1", 0,	/* aka "LEICA DIGILUX 2" */
1400 		{ 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
1401 		{ "Panasonic DMC-LX1", 0,	/* aka "LEICA D-LUX2" */
1402 		{ 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
1403 		{ "Panasonic DMC-LX2", 0,	/* aka "LEICA D-LUX3" */
1404 		{ 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
1405 		{ "SAMSUNG GX-1", 0,
1406 		{ 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
1407 		{ "Sinar", 0,		/* DJC */
1408 		{ 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } },
1409 		{ "SONY DSC-F828", 491,
1410 		{ 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } },
1411 		{ "SONY DSC-R1", 512,
1412 		{ 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } },
1413 		{ "SONY DSC-V3", 0,
1414 		{ 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } },
1415 		{ "SONY DSLR-A100", 0,
1416 		{ 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } }
1417 	};
1418 	double cam_xyz[4][3];
1419 
1420 	for (uint32 i = 0; i < sizeof table / sizeof *table; i++) {
1421 		if (!strncasecmp(model, table[i].prefix, strlen(table[i].prefix))) {
1422 			if (table[i].black)
1423 				fMeta.black = table[i].black;
1424 			for (uint32 j = 0; j < 12; j++) {
1425 				cam_xyz[0][j] = table[i].trans[j] / 10000.0;
1426 			}
1427 			_CameraXYZCoefficients(cam_xyz);
1428 			break;
1429 		}
1430 	}
1431 }
1432 
1433 
1434 void
1435 DCRaw::_BorderInterpolate(uint32 border)
1436 {
1437 	uint32 row, col, y, x, f, c, sum[8];
1438 
1439 	for (row = 0; row < fInputHeight; row++) {
1440 		for (col = 0; col < fInputWidth; col++) {
1441 			if (col == border && row >= border && row < fInputHeight - border)
1442 				col = fInputWidth - border;
1443 
1444 			memset(sum, 0, sizeof(sum));
1445 
1446 			for (y = row - 1; y != row + 2; y++) {
1447 				for (x = col - 1; x != col + 2; x++) {
1448 					if (y < fInputHeight && x < fInputWidth) {
1449 						f = _FilterCoefficient(x, y);
1450 						sum[f] += fImageData[y * fInputWidth + x][f];
1451 						sum[f + 4]++;
1452 					}
1453 				}
1454 			}
1455 
1456 			f = _FilterCoefficient(col, row);
1457 
1458 			for (c = 0; c < fColors; c++) {
1459 				if (c != f && sum[c + 4])
1460 					fImageData[row * fInputWidth + col][c] = sum[c] / sum[c+4];
1461 			}
1462 		}
1463 	}
1464 }
1465 
1466 
1467 /*!
1468    Adaptive Homogeneity-Directed interpolation is based on
1469    the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
1470 */
1471 void
1472 DCRaw::_AHDInterpolate()
1473 {
1474 #define TS 256		/* Tile Size */
1475 
1476 	int i, j, tr, tc, fc, c, d, val, hm[2];
1477 	uint32 top, left, row, col;
1478 	ushort (*pix)[4], (*rix)[3];
1479 	static const int dir[4] = { -1, 1, -TS, TS };
1480 	unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
1481 	float flab[3];
1482 	ushort (*rgb)[TS][TS][3];
1483 	short (*lab)[TS][TS][3];
1484 	char (*homo)[TS][TS], *buffer;
1485 
1486 	_BorderInterpolate(3);
1487 	buffer = (char *) malloc(26*TS*TS);		/* 1664 kB */
1488 	if (buffer == NULL)
1489 		throw (status_t)B_NO_MEMORY;
1490 
1491 	rgb = (ushort(*)[TS][TS][3])buffer;
1492 	lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
1493 	homo = (char (*)[TS][TS])(buffer + 24*TS*TS);
1494 
1495 	for (top = 0; top < fInputHeight; top += TS - 6) {
1496 		for (left = 0; left < fInputWidth; left += TS - 6) {
1497 			memset(rgb, 0, 12 * TS * TS);
1498 
1499 			/* Interpolate green horizontally and vertically: */
1500 			for (row = top < 2 ? 2 : top; row < top + TS && row < fInputHeight - 2; row++) {
1501 				col = left + (FC(row, left) == 1);
1502 				if (col < 2)
1503 					col += 2;
1504 				for (fc = FC(row, col); col < left + TS && col < fInputWidth - 2; col += 2) {
1505 					pix = fImageData + row * fInputWidth + col;
1506 					val = ((pix[-1][1] + pix[0][fc] + pix[1][1]) * 2
1507 						- pix[-2][fc] - pix[2][fc]) >> 2;
1508 					rgb[0][row - top][col - left][1] = ULIM(val, pix[-1][1], pix[1][1]);
1509 					val = ((pix[-fInputWidth][1] + pix[0][fc] + pix[fInputWidth][1]) * 2
1510 						- pix[-2 * fInputWidth][fc] - pix[2 * fInputWidth][fc]) >> 2;
1511 					rgb[1][row - top][col - left][1] = ULIM(val,
1512 						pix[-fInputWidth][1], pix[fInputWidth][1]);
1513 				}
1514 			}
1515 
1516 			/* Interpolate red and blue, and convert to CIELab: */
1517 			for (d = 0; d < 2; d++) {
1518 				for (row = top + 1; row < top + TS - 1 && row < fInputHeight - 1; row++) {
1519 					for (col = left + 1; col < left + TS - 1 && col < fInputWidth - 1; col++) {
1520 						pix = fImageData + row * fInputWidth + col;
1521 						rix = &rgb[d][row - top][col - left];
1522 						if ((c = 2 - FC(row, col)) == 1) {
1523 							c = FC(row + 1,col);
1524 							val = pix[0][1] + ((pix[-1][2-c] + pix[1][2 - c]
1525 								- rix[-1][1] - rix[1][1] ) >> 1);
1526 							rix[0][2-c] = CLIP(val);
1527 							val = pix[0][1] + ((pix[-fInputWidth][c]
1528 								+ pix[fInputWidth][c]
1529 								- rix[-TS][1] - rix[TS][1] ) >> 1);
1530 						} else {
1531 							val = rix[0][1] + ((pix[-fInputWidth - 1][c]
1532 								+ pix[-fInputWidth + 1][c]
1533 								+ pix[fInputWidth - 1][c] + pix[fInputWidth + 1][c]
1534 								- rix[-TS - 1][1] - rix[-TS + 1][1]
1535 								- rix[TS - 1][1] - rix[TS + 1][1] + 1) >> 2);
1536 						}
1537 						rix[0][c] = CLIP(val);
1538 						c = FC(row, col);
1539 						rix[0][c] = pix[0][c];
1540 						_CameraToCIELab(rix[0], flab);
1541 						for (c = 0; c < 3; c++) {
1542 							lab[d][row - top][col - left][c] = int16(64 * flab[c]);
1543 						}
1544 					}
1545 				}
1546 			}
1547 
1548 			/* Build homogeneity maps from the CIELab images: */
1549 			memset(homo, 0, 2 * TS * TS);
1550 			for (row = top + 2; row < top+TS-2 && row < fInputHeight; row++) {
1551 				tr = row - top;
1552 				for (col = left + 2; col < left + TS - 2 && col < fInputWidth; col++) {
1553 					tc = col - left;
1554 					for (d = 0; d < 2; d++) {
1555 						for (i = 0; i < 4; i++) {
1556 							ldiff[d][i] = ABS(lab[d][tr][tc][0]-lab[d][tr][tc+dir[i]][0]);
1557 						}
1558 					}
1559 
1560 					leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
1561 						MAX(ldiff[1][2],ldiff[1][3]));
1562 
1563 					for (d = 0; d < 2; d++) {
1564 						for (i = 0; i < 4; i++) {
1565 							if (i >> 1 == d || ldiff[d][i] <= leps) {
1566 								abdiff[d][i] = square(lab[d][tr][tc][1]-lab[d][tr][tc+dir[i]][1])
1567 									+ square(lab[d][tr][tc][2]-lab[d][tr][tc+dir[i]][2]);
1568 							}
1569 						}
1570 					}
1571 
1572 					abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
1573 						MAX(abdiff[1][2],abdiff[1][3]));
1574 
1575 					for (d=0; d < 2; d++) {
1576 						for (i=0; i < 4; i++) {
1577 							if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
1578 								homo[d][tr][tc]++;
1579 						}
1580 					}
1581 				}
1582 			}
1583 
1584 			/* Combine the most homogenous pixels for the final result: */
1585 			for (row = top + 3; row < top + TS - 3 && row < fInputHeight - 3; row++) {
1586 				tr = row - top;
1587 				for (col = left + 3; col < left + TS - 3 && col < fInputWidth - 3; col++) {
1588 					tc = col-left;
1589 					for (d = 0; d < 2; d++) {
1590 						for (hm[d] = 0, i = tr - 1; i <= tr + 1; i++) {
1591 							for (j = tc - 1; j <= tc + 1; j++) {
1592 								hm[d] += homo[d][i][j];
1593 							}
1594 						}
1595 					}
1596 					if (hm[0] != hm[1]) {
1597 						for (c = 0; c < 3; c++) {
1598 							fImageData[row * fInputWidth + col][c]
1599 								= rgb[hm[1] > hm[0]][tr][tc][c];
1600 						}
1601 					} else {
1602 						for (c = 0; c < 3; c++) {
1603 							fImageData[row * fInputWidth + col][c]
1604 								= (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
1605 						}
1606 					}
1607 				}
1608 			}
1609 		}
1610 	}
1611 	free(buffer);
1612 #undef TS
1613 }
1614 
1615 
1616 void
1617 DCRaw::_PseudoInverse(double (*in)[3], double (*out)[3], uint32 size)
1618 {
1619 	double work[3][6], num;
1620 	uint32 i, j, k;
1621 
1622 	for (i = 0; i < 3; i++) {
1623 		for (j = 0; j < 6; j++) {
1624 			work[i][j] = j == i + 3;
1625 		}
1626 		for (j = 0; j < 3; j++) {
1627 			for (k = 0; k < size; k++) {
1628 				work[i][j] += in[k][i] * in[k][j];
1629 			}
1630 		}
1631 	}
1632 
1633 	for (i = 0; i < 3; i++) {
1634 		num = work[i][i];
1635 		for (j = 0; j < 6; j++) {
1636 			work[i][j] /= num;
1637 		}
1638 		for (k = 0; k < 3; k++) {
1639 			if (k == i)
1640 				continue;
1641 
1642 			num = work[k][i];
1643 
1644 			for (j = 0; j < 6; j++) {
1645 				work[k][j] -= work[i][j] * num;
1646 			}
1647 		}
1648 	}
1649 
1650 	for (i = 0; i < size; i++) {
1651 		for (j = 0; j < 3; j++) {
1652 			for (out[i][j] = k =0; k < 3; k++) {
1653 				out[i][j] += work[j][k+3] * in[i][k];
1654 			}
1655 		}
1656 	}
1657 }
1658 
1659 
1660 void
1661 DCRaw::_ConvertToRGB()
1662 {
1663 	uint32 row, col, c, i, j, k;
1664 	float out[3], out_cam[3][4];
1665 	double num, inverse[3][3];
1666 	static const double xyzd50_srgb[3][3] =
1667 		{ { 0.436083, 0.385083, 0.143055 },
1668 		{ 0.222507, 0.716888, 0.060608 },
1669 		{ 0.013930, 0.097097, 0.714022 } };
1670 	static const double rgb_rgb[3][3] =
1671 		{ { 1,0,0 }, { 0,1,0 }, { 0,0,1 } };
1672 	static const double adobe_rgb[3][3] =
1673 		{ { 0.715146, 0.284856, 0.000000 },
1674 		{ 0.000000, 1.000000, 0.000000 },
1675 		{ 0.000000, 0.041166, 0.958839 } };
1676 	static const double wide_rgb[3][3] =
1677 		{ { 0.593087, 0.404710, 0.002206 },
1678 		{ 0.095413, 0.843149, 0.061439 },
1679 		{ 0.011621, 0.069091, 0.919288 } };
1680 	static const double prophoto_rgb[3][3] =
1681 		{ { 0.529317, 0.330092, 0.140588 },
1682 		{ 0.098368, 0.873465, 0.028169 },
1683 		{ 0.016879, 0.117663, 0.865457 } };
1684 	static const double (*out_rgb[])[3] =
1685 		{ rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb };
1686 	static const char *name[] =
1687 		{ "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" };
1688 	static const unsigned phead[] =
1689 		{ 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0,
1690 		0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d };
1691 	unsigned pbody[] =
1692 		{ 10, 0x63707274, 0, 36,	/* cprt */
1693 		0x64657363, 0, 40,	/* desc */
1694 		0x77747074, 0, 20,	/* wtpt */
1695 		0x626b7074, 0, 20,	/* bkpt */
1696 		0x72545243, 0, 14,	/* rTRC */
1697 		0x67545243, 0, 14,	/* gTRC */
1698 		0x62545243, 0, 14,	/* bTRC */
1699 		0x7258595a, 0, 20,	/* rXYZ */
1700 		0x6758595a, 0, 20,	/* gXYZ */
1701 		0x6258595a, 0, 20 };	/* bXYZ */
1702 	static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };
1703 	unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 };
1704 
1705 	memcpy(out_cam, fMeta.rgb_camera, sizeof(out_cam));
1706 	fRawColor |= fColors == 1 || fDocumentMode
1707 		|| fOutputColor < 1 || fOutputColor > 5;
1708 	if (!fRawColor) {
1709 		fOutputProfile = (uint32 *)calloc(phead[0], 1);
1710 		if (fOutputProfile == NULL)
1711 			throw (status_t)B_NO_MEMORY;
1712 
1713 		memcpy(fOutputProfile, phead, sizeof(phead));
1714 		if (fOutputColor == 5)
1715 			fOutputProfile[4] = fOutputProfile[5];
1716 
1717 		fOutputProfile[0] = 132 + 12 * pbody[0];
1718 		for (i = 0; i < pbody[0]; i++) {
1719 			fOutputProfile[fOutputProfile[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874;
1720 			pbody[i*3+2] = fOutputProfile[0];
1721 			fOutputProfile[0] += (pbody[i*3+3] + 3) & -4;
1722 		}
1723 
1724 		memcpy(fOutputProfile + 32, pbody, sizeof(pbody));
1725 		fOutputProfile[pbody[5] / 4 + 2] = strlen(name[fOutputColor - 1]) + 1;
1726 		memcpy((char *)fOutputProfile + pbody[8] + 8, pwhite, sizeof(pwhite));
1727 		if (fOutputBitsPerSample == 8) {
1728 #ifdef SRGB_GAMMA
1729 			pcurve[3] = 0x2330000;
1730 #else
1731 			pcurve[3] = 0x1f00000;
1732 #endif
1733 		}
1734 
1735 		for (i = 4; i < 7; i++) {
1736 			memcpy((char *)fOutputProfile + pbody[i*3+2], pcurve, sizeof(pcurve));
1737 		}
1738 
1739 		_PseudoInverse((double (*)[3])out_rgb[fOutputColor - 1], inverse, 3);
1740 
1741 		for (i = 0; i < 3; i++) {
1742 			for (j = 0; j < 3; j++) {
1743 				for (num = k=0; k < 3; k++) {
1744 					num += xyzd50_srgb[i][k] * inverse[j][k];
1745 				}
1746 				fOutputProfile[pbody[j * 3 + 23] / 4 + i + 2] = uint32(num * 0x10000 + 0.5);
1747 			}
1748 		}
1749 		for (i = 0; i < phead[0]/4; i++) {
1750 			fOutputProfile[i] = htonl(fOutputProfile[i]);
1751 		}
1752 		strcpy((char *)fOutputProfile + pbody[2] + 8, "auto-generated by dcraw");
1753 		strcpy((char *)fOutputProfile + pbody[5] + 12, name[fOutputColor - 1]);
1754 
1755 		for (i = 0; i < 3; i++) {
1756 			for (j = 0; j < fColors; j++) {
1757 				for (out_cam[i][j] = k = 0; k < 3; k++) {
1758 					out_cam[i][j] += out_rgb[fOutputColor-1][i][k] * fMeta.rgb_camera[k][j];
1759 				}
1760 			}
1761 		}
1762 	}
1763 
1764 	if (1/*verbose*/) {
1765 		fprintf(stderr, fRawColor ? "Building histograms...\n"
1766 			: "Converting to %s colorspace...\n", name[fOutputColor - 1]);
1767 	}
1768 
1769 	ushort* img = fImageData[0];
1770 	memset(fHistogram, 0, sizeof(int32) * 0x2000 * 4);
1771 
1772 	for (row = 0; row < fInputHeight; row++) {
1773 		for (col = 0; col < fInputWidth; col++, img += 4) {
1774 			if (!fRawColor) {
1775 				out[0] = out[1] = out[2] = 0;
1776 				for (c = 0; c < fColors; c++) {
1777 					out[0] += out_cam[0][c] * img[c];
1778 					out[1] += out_cam[1][c] * img[c];
1779 					out[2] += out_cam[2][c] * img[c];
1780 				}
1781 				for (c = 0; c < 3; c++) {
1782 					img[c] = CLIP((int)out[c]);
1783 				}
1784 			} else if (fDocumentMode)
1785 				img[0] = img[FC(row, col)];
1786 
1787 			for (c = 0; c < fColors; c++) {
1788 				fHistogram[img[c] >> 3][c]++;
1789 			}
1790 		}
1791 	}
1792 
1793 	if (fColors == 4 && fOutputColor)
1794 		fColors = 3;
1795 	if (fDocumentMode && fFilters)
1796 		fColors = 1;
1797 }
1798 
1799 
1800 void
1801 DCRaw::_GammaLookUpTable(uchar* lut)
1802 {
1803 	int32 percent, val, total, i;
1804 	float white = 0, r;
1805 
1806 	percent = int32(fInputWidth * fInputHeight * 0.01);
1807 		// 99th percentile white point
1808 
1809 	//  if (fuji_width) perc /= 2;
1810 	if (fHighlight)
1811 		percent = 0;
1812 
1813 	for (uint32 c = 0; c < fColors; c++) {
1814 		for (val = 0x2000, total = 0; --val > 32;) {
1815 			if ((total += fHistogram[val][c]) > percent)
1816 				break;
1817 		}
1818 		if (white < val)
1819 			white = val;
1820 	}
1821 
1822 	white *= 8 / fBrightness;
1823 
1824 	for (i = 0; i < 0x10000; i++) {
1825 		r = i / white;
1826 		val = int32(256 * (!fUseGamma ? r :
1827 #ifdef SRGB_GAMMA
1828 			r <= 0.00304 ? r*12.92 : pow(r,2.5/6)*1.055-0.055));
1829 #else
1830 			r <= 0.018 ? r*4.5 : pow(r,0.45)*1.099-0.099));
1831 #endif
1832 		if (val > 255)
1833 			val = 255;
1834 		lut[i] = val;
1835 	}
1836 }
1837 
1838 
1839 //	#pragma mark - Lossless JPEG
1840 
1841 
1842 void
1843 DCRaw::_InitDecoder()
1844 {
1845 	memset(fDecodeBuffer, 0, sizeof(decode) * kDecodeBufferCount);
1846 	fFreeDecode = fDecodeBuffer;
1847 }
1848 
1849 
1850 /*!
1851 	Construct a decode tree according the specification in *source.
1852 	The first 16 bytes specify how many codes should be 1-bit, 2-bit
1853 	3-bit, etc.  Bytes after that are the leaf values.
1854 
1855 	For example, if the source is
1856 
1857 	{ 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
1858 	  0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff  },
1859 
1860 	then the code is
1861 
1862 	00		0x04
1863 	010		0x03
1864 	011		0x05
1865 	100		0x06
1866 	101		0x02
1867 	1100		0x07
1868 	1101		0x01
1869 	11100		0x08
1870 	11101		0x09
1871 	11110		0x00
1872 	111110		0x0a
1873 	1111110		0x0b
1874 	1111111		0xff
1875  */
1876 uchar *
1877 DCRaw::_MakeDecoder(const uchar* source, int level)
1878 {
1879 	if (level == 0)
1880 		fDecodeLeaf = 0;
1881 
1882 	if ((uint8*)fFreeDecode > (uint8*)fDecodeBuffer + sizeof(decode) * kDecodeBufferCount) {
1883 		fprintf(stderr, "decoder table overflow\n");
1884 		throw (status_t)B_ERROR;
1885 	}
1886 
1887 	struct decode* current = fFreeDecode++;
1888 
1889 	int i, next;
1890 	for (i = next = 0; i <= fDecodeLeaf && next < 16; ) {
1891 		i += source[next++];
1892 	}
1893 
1894 	if (i > fDecodeLeaf) {
1895 		if (level < next) {
1896 			current->branch[0] = fFreeDecode;
1897 			_MakeDecoder(source, level + 1);
1898 			current->branch[1] = fFreeDecode;
1899 			_MakeDecoder(source, level + 1);
1900 		} else
1901 			current->leaf = source[16 + fDecodeLeaf++];
1902 	}
1903 
1904 	return (uchar*)source + 16 + fDecodeLeaf;
1905 }
1906 
1907 
1908 /*
1909    Not a full implementation of Lossless JPEG, just
1910    enough to decode Canon, Kodak and Adobe DNG images.
1911  */
1912 
1913 
1914 void
1915 DCRaw::_InitDecodeBits()
1916 {
1917 	fDecodeBits = fDecodeBitsRead = 0;
1918 	fDecodeBitsReset = false;
1919 }
1920 
1921 
1922 /*!
1923 	_GetDecodeBits(n) where 0 <= n <= 25 returns an n-bit integer
1924  */
1925 uint32
1926 DCRaw::_GetDecodeBits(uint32 numBits)
1927 {
1928 	if (numBits == 0 || fDecodeBitsReset)
1929 		return 0;
1930 
1931 	while (fDecodeBitsRead < numBits) {
1932 		uint8 c = fRead.Next<uint8>();
1933 		if ((fDecodeBitsReset = fDecodeBitsZeroAfterMax && c == 0xff && fRead.Next<uint8>()))
1934 			return 0;
1935 		fDecodeBits = (fDecodeBits << 8) + c;
1936 		fDecodeBitsRead += 8;
1937 	}
1938 
1939 	fDecodeBitsRead -= numBits;
1940 
1941 	return fDecodeBits << (32 - numBits - fDecodeBitsRead) >> (32 - numBits);
1942 }
1943 
1944 
1945 status_t
1946 DCRaw::_LosslessJPEGInit(struct jhead* jh, bool infoOnly)
1947 {
1948 	int i, tag, len;
1949 
1950 	_InitDecoder();
1951 
1952 	for (i = 0; i < 4; i++) {
1953 		jh->huff[i] = fFreeDecode;
1954 	}
1955 
1956 	jh->restart = INT_MAX;
1957 
1958 	uchar data[0x10000], *dp;
1959 	fRead(data, 2);
1960 	if (data[1] != 0xd8)
1961 		return B_ERROR;
1962 
1963 	do {
1964 		fRead(data, 4);
1965 		tag = data[0] << 8 | data[1];
1966 		len = (data[2] << 8 | data[3]) - 2;
1967 		if (tag <= 0xff00)
1968 			return B_ERROR;
1969 
1970 		fRead(data, len);
1971 		switch (tag) {
1972 			case 0xffc0:
1973 			case 0xffc3:
1974 				jh->bits = data[0];
1975 				jh->high = data[1] << 8 | data[2];
1976 				jh->wide = data[3] << 8 | data[4];
1977 				jh->clrs = data[5];
1978 				break;
1979 			case 0xffc4:
1980 				if (infoOnly)
1981 					break;
1982 
1983 				for (dp = data; dp < data+len && *dp < 4; ) {
1984 					jh->huff[*dp] = fFreeDecode;
1985 					dp = _MakeDecoder(++dp, 0);
1986 				}
1987 				break;
1988 			case 0xffdd:
1989 				jh->restart = data[0] << 8 | data[1];
1990 				break;
1991 		}
1992 	} while (tag != 0xffda);
1993 
1994 	if (infoOnly)
1995 		return B_OK;
1996 
1997 	jh->row = (ushort *)calloc(jh->wide*jh->clrs, 2);
1998 	if (jh->row == NULL)
1999 		throw (status_t)B_NO_MEMORY;
2000 
2001 	fDecodeBitsZeroAfterMax = true;
2002 	return B_OK;
2003 }
2004 
2005 
2006 int
2007 DCRaw::_LosslessJPEGDiff(struct decode *dindex)
2008 {
2009 	while (dindex->branch[0]) {
2010 		dindex = dindex->branch[_GetDecodeBits(1)];
2011 	}
2012 
2013 	int length = dindex->leaf;
2014 	if (length == 16 && (!fDNGVersion || fDNGVersion >= 0x1010000))
2015 		return -32768;
2016 
2017 	int diff = _GetDecodeBits(length);
2018 	if ((diff & (1 << (length - 1))) == 0)
2019 		diff -= (1 << length) - 1;
2020 
2021 	return diff;
2022 }
2023 
2024 
2025 void
2026 DCRaw::_LosslessJPEGRow(struct jhead *jh, int jrow)
2027 {
2028 	if (jrow * jh->wide % jh->restart == 0) {
2029 		for (uint32 i = 0; i < 4; i++) {
2030 			jh->vpred[i] = 1 << (jh->bits - 1);
2031 		}
2032 		if (jrow) {
2033 			uint16 mark = 0;
2034 			int c;
2035 			do {
2036 				mark = (mark << 8) + (c = fRead.Next<uint8>());
2037 			} while (c != EOF && mark >> 4 != 0xffd);
2038 		}
2039 		_InitDecodeBits();
2040 	}
2041 
2042 	uint16* outp = jh->row;
2043 
2044 	for (int32 col = 0; col < jh->wide; col++) {
2045 		for (int32 c = 0; c < jh->clrs; c++) {
2046 			int32 diff = _LosslessJPEGDiff(jh->huff[c]);
2047 			*outp = col ? outp[-jh->clrs]+diff : (jh->vpred[c] += diff);
2048 			outp++;
2049 		}
2050 	}
2051 }
2052 
2053 
2054 //	#pragma mark - RAW loaders
2055 
2056 
2057 /*!
2058 	This is, for example, used in PENTAX RAW images
2059 */
2060 void
2061 DCRaw::_LoadRAWPacked12(const image_data_info& image)
2062 {
2063 	uint32 rawWidth = _Raw().width;
2064 	uint32 column, row;
2065 
2066 	_InitDecodeBits();
2067 
2068 	for (row = 0; row < fInputHeight; row++) {
2069 		for (column = 0; column < fInputWidth; column++) {
2070 			//uint16 bits = _GetDecodeBits(12);
2071 			_Bayer(column, row) = _GetDecodeBits(12);
2072 			//fImageData[((row) >> fShrink)*fOutputWidth + ((column) >> fShrink)][FC(row,column)] = bits;
2073 		}
2074 		for (column = fInputWidth * 3 / 2; column < rawWidth; column++) {
2075 			_GetDecodeBits(8);
2076 		}
2077 	}
2078 }
2079 
2080 
2081 void
2082 DCRaw::_MakeCanonDecoder(uint32 table)
2083 {
2084 	static const uchar kFirstTree[3][29] = {
2085 		{ 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
2086 			0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
2087 		{ 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0,
2088 			0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff },
2089 		{ 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0,
2090 			0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff },
2091 	};
2092 	static const uchar kSecondTree[3][180] = {
2093 		{ 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139,
2094 			0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08,
2095 			0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0,
2096 			0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42,
2097 			0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57,
2098 			0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9,
2099 			0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98,
2100 			0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6,
2101 			0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4,
2102 			0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7,
2103 			0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1,
2104 			0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64,
2105 			0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba,
2106 			0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4,
2107 			0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff },
2108 		{ 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140,
2109 			0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06,
2110 			0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32,
2111 			0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51,
2112 			0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26,
2113 			0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59,
2114 			0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9,
2115 			0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99,
2116 			0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85,
2117 			0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8,
2118 			0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a,
2119 			0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9,
2120 			0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8,
2121 			0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8,
2122 			0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff },
2123 		{ 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117,
2124 			0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08,
2125 			0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22,
2126 			0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34,
2127 			0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41,
2128 			0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48,
2129 			0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69,
2130 			0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8,
2131 			0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94,
2132 			0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a,
2133 			0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6,
2134 			0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62,
2135 			0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5,
2136 			0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3,
2137 			0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff }
2138 	};
2139 
2140 	if (table > 2)
2141 		table = 2;
2142 
2143 	_InitDecoder();
2144 
2145 	_MakeDecoder(kFirstTree[table], 0);
2146 	fSecondDecode = fFreeDecode;
2147 	_MakeDecoder(kSecondTree[table], 0);
2148 }
2149 
2150 
2151 /*!
2152 	Return 0 if the image starts with compressed data,
2153 	1 if it starts with uncompressed low-order bits.
2154 
2155 	In Canon compressed data, 0xff is always followed by 0x00.
2156  */
2157 bool
2158 DCRaw::_CanonHasLowBits()
2159 {
2160 	bool hasLowBits = true;
2161 	uchar test[0x4000 - 540];
2162 
2163 	fRead.Seek(540, SEEK_SET);
2164 	fRead(test, sizeof(test));
2165 
2166 	for (uint32 i = 0; i < sizeof(test) - 1; i++)
2167 		if (test[i] == 0xff) {
2168 			if (test[i + 1])
2169 				return 1;
2170 			hasLowBits = 0;
2171     }
2172 
2173 	return hasLowBits;
2174 }
2175 
2176 void
2177 dump_to_disk(void* data, size_t length)
2178 {
2179 	FILE* file = fopen("/tmp/RAW.out", "wb");
2180 	if (file == NULL)
2181 		return;
2182 
2183 	fwrite(data, length, 1, file);
2184 	fclose(file);
2185 }
2186 
2187 void
2188 DCRaw::_LoadRAWCanonCompressed(const image_data_info& image)
2189 {
2190 	uint32 rawWidth = _Raw().width;
2191 	int carry = 0, pnum = 0, base[2];
2192 
2193 	_MakeCanonDecoder(image.compression);
2194 
2195 	uint16* pixel = (uint16 *)calloc(rawWidth * 8, sizeof(*pixel));
2196 	if (pixel == NULL)
2197 		throw (status_t)B_NO_MEMORY;
2198 
2199 	bool hasLowBits = _CanonHasLowBits();
2200 	if (!hasLowBits)
2201 		fMeta.maximum = 0x3ff;
2202 
2203 	fRead.Seek(540 + (hasLowBits ? _Raw().height * rawWidth / 4 : 0),
2204 		SEEK_SET);
2205 
2206 	fDecodeBitsZeroAfterMax = true;
2207 	_InitDecodeBits();
2208 
2209 	for (uint32 row = 0; row < _Raw().height; row += 8) {
2210 		for (uint32 block = 0; block < rawWidth >> 3; block++) {
2211 			int diffbuf[64];
2212 			memset(diffbuf, 0, sizeof diffbuf);
2213 			struct decode* decode = fDecodeBuffer;
2214 
2215 			for (uint32 i = 0; i < 64; i++) {
2216 				struct decode* dindex = decode;
2217 				while (dindex->branch[0]) {
2218 					dindex = dindex->branch[_GetDecodeBits(1)];
2219 				}
2220 				int leaf = dindex->leaf;
2221 				decode = fSecondDecode;
2222 				if (leaf == 0 && i)
2223 					break;
2224 				if (leaf == 0xff)
2225 					continue;
2226 				i += leaf >> 4;
2227 
2228 				int len = leaf & 15;
2229 				if (len == 0)
2230 					continue;
2231 				int diff = _GetDecodeBits(len);
2232 				if ((diff & (1 << (len-1))) == 0)
2233 					diff -= (1 << len) - 1;
2234 				if (i < 64)
2235 					diffbuf[i] = diff;
2236 			}
2237 
2238 			diffbuf[0] += carry;
2239 			carry = diffbuf[0];
2240 
2241 			for (uint32 i = 0; i < 64; i++) {
2242 				if (pnum++ % _Raw().width == 0)
2243 					base[0] = base[1] = 512;
2244 				pixel[(block << 6) + i] = (base[i & 1] += diffbuf[i]);
2245 			}
2246 		}
2247 
2248 		if (hasLowBits) {
2249 			off_t savedOffset = fRead.Position();
2250 			fRead.Seek(26 + row * _Raw().width / 4, SEEK_SET);
2251 
2252 			uint16* pixelRow = pixel;
2253 			for (uint32 i = 0; i < rawWidth * 2; i++) {
2254 				uint8 c = fRead.Next<uint8>();
2255 
2256 				for (uint32 r = 0; r < 8; r += 2, pixelRow++) {
2257 					uint32 val = (*pixelRow << 2) + ((c >> r) & 3);
2258 					if (rawWidth == 2672 && val < 512)
2259 						val += 2;
2260 					*pixelRow = val;
2261 				}
2262 			}
2263 
2264 			fRead.Seek(savedOffset, SEEK_SET);
2265 		}
2266 
2267 		for (uint32 r = 0; r < 8; r++) {
2268 			uint32 irow = row - fTopMargin + r;
2269 			if (irow >= fInputHeight)
2270 				continue;
2271 
2272 			for (uint32 col = 0; col < rawWidth; col++) {
2273 				uint32 icol = col - fLeftMargin;
2274 				if (icol < fInputWidth)
2275 					_Bayer(icol, irow) = pixel[r * rawWidth + col];
2276 				else
2277 					fMeta.black += pixel[r * rawWidth + col];
2278 			}
2279 		}
2280 	}
2281 
2282 	free(pixel);
2283 
2284 	if (rawWidth > fInputWidth)
2285 		fMeta.black /= (rawWidth - fInputWidth) * fInputHeight;
2286 }
2287 
2288 
2289 void
2290 DCRaw::_LoadRAWLosslessJPEG(const image_data_info& image)
2291 {
2292 	int jwide, jrow, jcol, val, jidx, i, j, row = 0, col = 0;
2293 	uint32 rawWidth = _Raw().width;
2294 	int min = INT_MAX;
2295 
2296 	struct jhead jh;
2297 	if (_LosslessJPEGInit(&jh, false) != B_OK)
2298 		throw (status_t)B_NO_TRANSLATOR;
2299 
2300 	jwide = jh.wide * jh.clrs;
2301 
2302 	for (jrow = 0; jrow < jh.high; jrow++) {
2303 		_LosslessJPEGRow(&jh, jrow);
2304 
2305 		for (jcol = 0; jcol < jwide; jcol++) {
2306 			val = jh.row[jcol];
2307 			if (jh.bits <= 12)
2308 				val = fCurve[val];
2309 
2310 			if (fCR2Slice[0]) {
2311 				jidx = jrow * jwide + jcol;
2312 				i = jidx / (fCR2Slice[1] * jh.high);
2313 				if ((j = i >= fCR2Slice[0]))
2314 					i  = fCR2Slice[0];
2315 				jidx -= i * (fCR2Slice[1] * jh.high);
2316 				row = jidx / fCR2Slice[1 + j];
2317 				col = jidx % fCR2Slice[1 + j] + i * fCR2Slice[1];
2318 			}
2319 
2320 			if (_Raw().width == 3984 && (col -= 2) < 0) {
2321 				col += rawWidth;
2322 				row--;
2323 			}
2324 
2325 			if (uint32(row - fTopMargin) < fInputHeight) {
2326 				if (uint32(col - fLeftMargin) < fInputWidth) {
2327 					_Bayer(col - fLeftMargin, row - fTopMargin) = val;
2328 					if (min > val)
2329 						min = val;
2330 				} else
2331 					fMeta.black += val;
2332 			}
2333 			if (++col >= (int32)rawWidth) {
2334 				col = 0;
2335 				row++;
2336 			}
2337 		}
2338 	}
2339 
2340 	dump_to_disk(fImageData, fInputWidth * fColors * 100);
2341 	free(jh.row);
2342 
2343 	if (rawWidth > fInputWidth)
2344 		fMeta.black /= (rawWidth - fInputWidth) * fInputHeight;
2345 	if (_IsKodak())
2346 		fMeta.black = min;
2347 }
2348 
2349 
2350 void
2351 DCRaw::_LoadRAW(const image_data_info& image)
2352 {
2353 	if (_IsCanon()) {
2354 		if (fIsTIFF)
2355 			_LoadRAWLosslessJPEG(image);
2356 		else
2357 			_LoadRAWCanonCompressed(image);
2358 	} else {
2359 		switch (image.compression) {
2360 			case 32773:
2361 				_LoadRAWPacked12(image);
2362 				break;
2363 
2364 			default:
2365 				printf("unknown compression: %ld\n", image.compression);
2366 				throw (status_t)B_NO_TRANSLATOR;
2367 				break;
2368 		}
2369 	}
2370 }
2371 
2372 
2373 //	#pragma mark - Image writers
2374 
2375 
2376 void
2377 DCRaw::_WriteRGB32(image_data_info& image, uint8* outputBuffer)
2378 {
2379 	uint8* line, lookUpTable[0x10000];
2380 
2381 	uint32 width = image.flip & 4 ? fOutputHeight : fOutputWidth;
2382 	uint32 height = image.flip & 4 ? fOutputWidth : fOutputHeight;
2383 	uint32 outputRow = (4 * fOutputBitsPerSample / 8) * width;
2384 	uint32 outputOffset = 0;
2385 
2386 	line = (uint8 *)malloc(outputRow);
2387 	if (line == NULL)
2388 		throw (status_t)B_NO_MEMORY;
2389 
2390 	memset(line, 0, outputRow);
2391 
2392 	if (fOutputBitsPerSample == 8)
2393 		_GammaLookUpTable(lookUpTable);
2394 
2395 	int32 sourceOffset = _FlipIndex(0, 0, image.flip);
2396 	int32 colStep = _FlipIndex(0, 1, image.flip) - sourceOffset;
2397 	int32 rowStep = _FlipIndex(1, 0, image.flip)
2398 		- _FlipIndex(0, width, image.flip);
2399 
2400 	TRACE(("flip = %ld, sourceOffset = %ld, colStep = %ld, rowStep = %ld, "
2401 		"input: %lu x %lu, output: %lu x %lu\n", image.flip, sourceOffset,
2402 		colStep, rowStep, fInputWidth, fInputHeight, width,
2403 		height));
2404 
2405 	if (fOutputBitsPerSample == 8) {
2406 		for (uint32 row = 0; row < height; row++, sourceOffset += rowStep) {
2407 			for (uint32 col = 0; col < width; col++, sourceOffset += colStep) {
2408 				line[col * 4 + 2] = lookUpTable[fImageData[sourceOffset][0]];
2409 				line[col * 4 + 1] = lookUpTable[fImageData[sourceOffset][1]];
2410 				line[col * 4 + 0] = lookUpTable[fImageData[sourceOffset][2]];
2411 			}
2412 
2413 			memcpy(&outputBuffer[outputOffset], line, outputRow);
2414 			outputOffset += outputRow;
2415 		}
2416 	} else {
2417 #if 0
2418 		uint16* ppm2 = (uint16*)line;
2419 		for (row = 0; row < fOutputHeight; row++, soff += rstep) {
2420 			for (col = 0; col < fOutputWidth; col++, soff += cstep) {
2421 				FORCC ppm2[col*colors+c] =     image[soff][c];
2422 			}
2423 			if (!output_tiff && htons(0x55aa) != 0x55aa)
2424 				swab (ppm2, ppm2, width*colors*2);
2425 			fwrite (ppm, colors*output_bps/8, width, ofp);
2426 		}
2427 #endif
2428 	}
2429 
2430 	free(line);
2431 }
2432 
2433 
2434 void
2435 DCRaw::_WriteJPEG(image_data_info& image, uint8* outputBuffer)
2436 {
2437 	fRead(outputBuffer, image.bytes);
2438 
2439 	if (outputBuffer[0] != 0xff || outputBuffer[1] != 0xd8)
2440 		throw (status_t)B_NO_TRANSLATOR;
2441 
2442 #if 0
2443 	uint8* thumb = (uint8*)malloc(image.bytes);
2444 	if (thumb == NULL)
2445 		throw (status_t)B_NO_MEMORY;
2446 
2447 	fRead(thumb, image.bytes);
2448 
2449 	uint8* data = (uint8*)fImageData;
2450 	data[0] = 0xff;
2451 	data[1] = 0xd8;
2452 
2453 	if (strcmp((char *)thumb + 6, "Exif")) {
2454 		// TODO: no EXIF data - write them ourselves
2455 	}
2456 
2457 	memcpy(&data[2], thumb + 2, image.bytes - 2);
2458 	free(thumb);
2459 #endif
2460 }
2461 
2462 
2463 //	#pragma mark - TIFF
2464 
2465 
2466 time_t
2467 DCRaw::_ParseTIFFTimestamp(bool reversed)
2468 {
2469 	char str[20];
2470 	str[19] = 0;
2471 
2472 	if (reversed) {
2473 		for (int i = 19; i--; ) {
2474 			str[i] = fRead.Next<uint8>();
2475 		}
2476 	} else
2477 		fRead(str, 19);
2478 
2479 	struct tm t;
2480 	memset(&t, 0, sizeof t);
2481 
2482 	if (sscanf(str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
2483 			&t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
2484 		return 0;
2485 
2486 	t.tm_year -= 1900;
2487 	t.tm_mon -= 1;
2488 
2489 	return mktime(&t);
2490 }
2491 
2492 
2493 /*!
2494 	Reads a TIFF tag and positions the file stream to its data section
2495 */
2496 void
2497 DCRaw::_ParseTIFFTag(off_t baseOffset, tiff_tag& tag, off_t& offset)
2498 {
2499 	fRead(tag.tag);
2500 	fRead(tag.type);
2501 	fRead(tag.length);
2502 
2503 	offset = fRead.Position() + 4;
2504 
2505 	uint32 length = tag.length;
2506 
2507 	switch (tag.type) {
2508 		case TIFF_UINT16_TYPE:
2509 		case TIFF_INT16_TYPE:
2510 			length *= 2;
2511 			break;
2512 
2513 		case TIFF_UINT32_TYPE:
2514 		case TIFF_INT32_TYPE:
2515 		case TIFF_FLOAT_TYPE:
2516 			length *= 4;
2517 			break;
2518 
2519 		case TIFF_UFRACTION_TYPE:
2520 		case TIFF_FRACTION_TYPE:
2521 		case TIFF_DOUBLE_TYPE:
2522 			length *= 8;
2523 			break;
2524 
2525 		default:
2526 			break;
2527 	}
2528 
2529 	if (length > 4) {
2530 		uint32 position;
2531 		fRead(position);
2532 
2533 		fRead.Seek(baseOffset + position, SEEK_SET);
2534 	}
2535 }
2536 
2537 
2538 status_t
2539 DCRaw::_ParseTIFFImageFileDirectory(off_t baseOffset, uint32 offset)
2540 {
2541 	double analogBalance[] = {1, 1, 1, 1};
2542 	double xyz[] = {1, 1, 1, 1};
2543 	bool useColorMatrix = false;
2544 	double cameraCalibration[4][4], colorMatrix[4][3], cam_xyz[4][3];
2545 
2546 	for (int32 j = 0; j < 4; j++) {
2547 		for (int32 i = 0; i < 4; i++) {
2548 			cameraCalibration[j][i] = i == j;
2549 		}
2550 	}
2551 
2552 	fRead.Seek(baseOffset + offset, SEEK_SET);
2553 
2554 	uint16 tags;
2555 	fRead(tags);
2556 	if (tags > 512)
2557 		return B_BAD_DATA;
2558 
2559 	image_data_info& image = fImages[fNumImages];
2560 
2561 	while (tags--) {
2562 		off_t nextOffset;
2563 		tiff_tag tag;
2564 		_ParseTIFFTag(baseOffset, tag, nextOffset);
2565 		TAG(("TIFF tag: %u\n", tag.tag));
2566 
2567 		switch (tag.tag) {
2568 #if 0
2569 			default:
2570 				printf("tag %u NOT HANDLED!\n", tag.tag);
2571 				break;
2572 #endif
2573 
2574 			case 17:
2575 			case 18:
2576 				if (tag.type == 3 && tag.length == 1)
2577 					fMeta.camera_multipliers[(tag.tag - 17) * 2] = fRead.Next<uint16>() / 256.0;
2578 				break;
2579 
2580 			case 23:	// ISO speed
2581 				fMeta.iso_speed = fRead.Next(tag.type);
2582 				break;
2583 
2584 			case 36:
2585 			case 37:
2586 			case 38:
2587 				fMeta.camera_multipliers[tag.tag - 0x24] = fRead.Next<uint16>();
2588 				break;
2589 
2590 			case 39:
2591 				if (tag.length < 50 || fMeta.camera_multipliers[0])
2592 					break;
2593 
2594 				fRead.Stream().Seek(12, SEEK_CUR);
2595 				for (uint32 i = 0; i < 3; i++) {
2596 					fMeta.camera_multipliers[i] = fRead.Next<uint16>();
2597 				}
2598 				break;
2599 
2600 			case 2:		// image width
2601 			case 256:
2602 				image.width = fRead.Next(tag.type);
2603 				break;
2604 
2605 			case 3:		// image height
2606 			case 257:
2607 				image.height = fRead.Next(tag.type);
2608 				break;
2609 
2610 			case 258:	// bits per sample
2611 				image.samples = tag.length;
2612 				image.bits_per_sample = fRead.Next<uint16>();
2613 				break;
2614 
2615 			case 259:	// compression
2616 				image.compression = fRead.Next<uint16>();
2617 				break;
2618 
2619 			case 262:	// Photometric Interpretation
2620 				image.photometric_interpretation = fRead.Next<uint16>();
2621 				break;
2622 
2623 			case 271:	// manufacturer
2624 				fRead(fMeta.manufacturer, 64);
2625 				break;
2626 
2627 			case 272:	// model
2628 				fRead(fMeta.model, 64);
2629 				break;
2630 
2631 			case 273:	// Strip Offset
2632 			case 513:
2633 				image.data_offset = baseOffset + fRead.Next<uint32>();
2634 				if (!image.bits_per_sample) {
2635 					fRead.Stream().Seek(image.data_offset, SEEK_SET);
2636 					jhead jh;
2637 					if (_LosslessJPEGInit(&jh, true) == B_OK) {
2638 						image.compression = 6;
2639 						image.width = jh.wide << (jh.clrs == 2);
2640 						image.height = jh.high;
2641 						image.bits_per_sample = jh.bits;
2642 						image.samples = jh.clrs;
2643 					}
2644 				}
2645 				break;
2646 
2647 			case 274:	// Orientation
2648 				image.flip = "50132467"[fRead.Next<uint16>() & 7] - '0';
2649 				break;
2650 
2651 			case 277:	// Samples Per Pixel
2652 				image.samples = fRead.Next(tag.type);
2653 				break;
2654 
2655 			case 279:	// Strip Byte Counts
2656 			case 514:
2657 				image.bytes = fRead.Next<uint32>();
2658 				break;
2659 
2660 			case 305:	// Software
2661 				fRead(fMeta.software, 64);
2662 				if (!strncmp(fMeta.software, "Adobe", 5)
2663 					|| !strncmp(fMeta.software, "dcraw", 5)
2664 					|| !strncmp(fMeta.software, "Bibble", 6)
2665 					|| !strncmp(fMeta.software, "Nikon Scan", 10)
2666 					|| !strcmp(fMeta.software,"Digital Photo Professional"))
2667 					throw (status_t)B_NO_TRANSLATOR;
2668 				break;
2669 
2670 			case 306:	// Date/Time
2671 				fMeta.timestamp = _ParseTIFFTimestamp(false);
2672 				break;
2673 
2674 #if 0
2675 			case 323:	// Tile Length
2676 				tile_length = fRead.Next(type);
2677 				break;
2678 
2679 			case 324:	// Tile Offsets
2680 				image.data_offset = tag.length > 1
2681 					? fRead.Stream().Position() : fRead.Next<uint32>();
2682 				if (tag.length == 4)
2683 					load_raw = &CLASS sinar_4shot_load_raw;
2684 				break;
2685 #endif
2686 
2687 			case 330:	// Sub IFDs
2688 				if (!strcmp(fMeta.model, "DSLR-A100") && image.width == 3872) {
2689 					// TODO: this might no longer work!
2690 					image.data_offset = fRead.Next<uint32>() + baseOffset;
2691 					break;
2692 				}
2693 
2694 				while (tag.length--) {
2695 					off_t nextOffset = fRead.Position() + sizeof(uint32);
2696 
2697 					fRead.Seek(fRead.Next<uint32>() + baseOffset, SEEK_SET);
2698 					if (_ParseTIFFImageFileDirectory(baseOffset) != B_OK)
2699 						break;
2700 
2701 					fNumImages++;
2702 					fRead.Seek(nextOffset, SEEK_SET);
2703 				}
2704 				break;
2705 
2706 #if 0
2707 			case 400:
2708 				strcpy(fMeta.manufacturer, "Sarnoff");
2709 				maximum = 0xfff;
2710 				break;
2711 #endif
2712 
2713 #if 0
2714 			case 29184:
2715 				sony_offset = get4();
2716 				break;
2717 			case 29185:
2718 				sony_length = get4();
2719 				break;
2720 			case 29217:
2721 				sony_key = get4();
2722 				break;
2723 #endif
2724 
2725 			case 29443:
2726 				for (uint32 i = 0; i < 4; i++) {
2727 					fMeta.camera_multipliers[i ^ (i < 2)] = fRead.Next<uint16>();
2728 				}
2729 				break;
2730 
2731 			case 33405:	// Model 2
2732 				fRead(fMeta.model + 64, 64);
2733 				break;
2734 
2735 #if 0
2736 			case 33422:	// CFA Pattern
2737 			case 64777:	// Kodak P-series
2738 			{
2739 				if ((plen=len) > 16) plen = 16;
2740 				fread (cfa_pat, 1, plen, ifp);
2741 				for (colors=cfa=i=0; i < plen; i++) {
2742 				  colors += !(cfa & (1 << cfa_pat[i]));
2743 				  cfa |= 1 << cfa_pat[i];
2744 				}
2745 				if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3);	/* CMY */
2746 				if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4);	/* GMCY */
2747 				goto guess_cfa_pc;
2748 				break;
2749 			}
2750 
2751 			case 33424:
2752 				fseek(ifp, get4()+base, SEEK_SET);
2753 				parse_kodak_ifd (base);
2754 				break;
2755 #endif
2756 
2757 			case 33434:	// Exposure Time
2758 				fMeta.shutter = fRead.NextDouble(TIFF_FRACTION_TYPE);
2759 				break;
2760 
2761 			case 33437:	// Aperture
2762 				fMeta.aperture = fRead.NextDouble(TIFF_FRACTION_TYPE);
2763 				break;
2764 
2765 			case 34306:	// Leaf white balance
2766 				for (uint32 i = 0; i < 4; i++) {
2767 					fMeta.camera_multipliers[i ^ 1] = 4096.0 / fRead.Next<uint16>();
2768 				}
2769 				break;
2770 
2771 #if 0
2772 			case 34307:	// Leaf Catch Light color matrix
2773 				fread (software, 1, 7, ifp);
2774 				if (strncmp(software,"MATRIX",6))
2775 					break;
2776 				colors = 4;
2777 				for (fRawColor = i=0; i < 3; i++) {
2778 					FORC4 fscanf (ifp, "%f", &rgb_cam[i][c^1]);
2779 					if (!use_camera_wb)
2780 						continue;
2781 					num = 0;
2782 					FORC4 num += rgb_cam[i][c];
2783 					FORC4 rgb_cam[i][c] /= num;
2784 				}
2785 				break;
2786 			case 34310:	// Leaf metadata
2787 				parse_mos (ftell(ifp));
2788 			case 34303:
2789 				strcpy(image.manufacturer, "Leaf");
2790 				break;
2791 #endif
2792 
2793 			case 34665:	// EXIF tag
2794 				fRead.Seek(fRead.Next<uint32>() + baseOffset, SEEK_SET);
2795 				_ParseEXIF(baseOffset);
2796 				break;
2797 
2798 #if 0
2799 			case 34675:	// InterColorProfile
2800 			case 50831:	// AsShotICCProfile
2801 				profile_offset = fRead.Stream().Position();
2802 				profile_length = tag.length;
2803 				break;
2804 
2805 			case 37122:	// Compressed Bits Per Pixel
2806 				kodak_cbpp = fRead.Next<uint32>();
2807 				break;
2808 #endif
2809 
2810 			case 37386:	// Focal Length
2811 				fMeta.focal_length = fRead.NextDouble(TIFF_FRACTION_TYPE);
2812 				break;
2813 
2814 			case 37393:	// Image Number
2815 				fMeta.shot_order = fRead.Next(tag.type);
2816 				break;
2817 
2818 #if 0
2819 			case 37400:	// old Kodak KDC tag
2820 				for (fRawColor = i=0; i < 3; i++) {
2821 					getrat();
2822 					FORC3 rgb_cam[i][c] = getrat();
2823 				}
2824 				break;
2825 
2826 			case 46275:	// Imacon tags
2827 				strcpy (make, "Imacon");
2828 				data_offset = ftell(ifp);
2829 				ima_len = len;
2830 				break;
2831       case 46279:
2832 	fseek (ifp, 78, SEEK_CUR);
2833 	raw_width  = get4();
2834 	raw_height = get4();
2835 	left_margin = get4() & 7;
2836 	width = raw_width - left_margin - (get4() & 7);
2837 	top_margin = get4() & 7;
2838 	height = raw_height - top_margin - (get4() & 7);
2839 	fseek (ifp, 52, SEEK_CUR);
2840 	FORC3 cam_multipliers[c] = getreal(11);
2841 	fseek (ifp, 114, SEEK_CUR);
2842 	flip = (get2() >> 7) * 90;
2843 	if (width * height * 6 == ima_len) {
2844 	  if (flip % 180 == 90) SWAP(width,height);
2845 	  filters = flip = 0;
2846 	}
2847 	break;
2848       case 50454:			/* Sinar tag */
2849       case 50455:
2850 	if (!(cbuf = (char *) malloc(len))) break;
2851 	fread (cbuf, 1, len, ifp);
2852 	for (cp = cbuf-1; cp && cp < cbuf+len; cp = strchr(cp,'\n'))
2853 	  if (!strncmp (++cp,"Neutral ",8))
2854 	    sscanf (cp+8, "%f %f %f", cam_multipliers, cam_multipliers+1, cam_multipliers+2);
2855 	free (cbuf);
2856 	break;
2857 #endif
2858 
2859 			case 50706:	// DNG Version
2860 				for (int32 i = 0; i < 4; i++) {
2861 					fDNGVersion = (fDNGVersion << 8) + fRead.Next<uint8>();
2862 				}
2863 				break;
2864 
2865 #if 0
2866 			case 50710:	// CFAPlaneColor
2867 				if (len > 4)
2868 					len = 4;
2869 				colors = len;
2870 				fread(cfa_pc, 1, colors, ifp);
2871 			guess_cfa_pc:
2872 				FORCC tab[cfa_pc[c]] = c;
2873 				cdesc[c] = 0;
2874 				for (i=16; i--; )
2875 					filters = filters << 2 | tab[cfa_pat[i % plen]];
2876 				break;
2877 			case 50711:	// CFALayout
2878 				if (get2() == 2) {
2879 					fuji_width = 1;
2880 					filters = 0x49494949;
2881 				}
2882 				break;
2883 #endif
2884 
2885 			case 291:	// Linearization Table
2886 			case 50712:
2887 				_ParseLinearTable(tag.length);
2888 				break;
2889 
2890 			case 50714:			/* BlackLevel */
2891 			case 50715:			/* BlackLevelDeltaH */
2892 			case 50716:			/* BlackLevelDeltaV */
2893 			{
2894 				double black = 0.0;
2895 				for (uint32 i = 0; i < tag.length; i++) {
2896 					black += fRead.NextDouble(tag.type);
2897 				}
2898 				fMeta.black += int32(black / tag.length + 0.5);
2899 				break;
2900 			}
2901 
2902 			case 50717:	// White Level
2903 				fMeta.maximum = fRead.Next(tag.type);
2904 				break;
2905 
2906 			case 50718:	// Default Scale
2907 				fMeta.pixel_aspect = fRead.NextDouble(TIFF_FRACTION_TYPE);
2908 				fMeta.pixel_aspect /= fRead.NextDouble(TIFF_FRACTION_TYPE);
2909 				break;
2910 
2911 			case 50721:	// Color Matrix
2912 			case 50722:
2913 				for (uint32 c = 0; c < fColors; c++) {
2914 					for (uint32 j = 0; j < 3; j++) {
2915 						colorMatrix[c][j] = fRead.NextDouble(TIFF_FRACTION_TYPE);
2916 					}
2917 				}
2918 				useColorMatrix = true;
2919 				break;
2920 
2921 			case 50723:	// Camera Calibration
2922 			case 50724:
2923 				for (uint32 i = 0; i < fColors; i++) {
2924 					for (uint32 c = 0; c < fColors; c++) {
2925 						cameraCalibration[i][c] = fRead.NextDouble(
2926 							TIFF_FRACTION_TYPE);
2927 					}
2928 				}
2929 				//break;
2930 			case 50727:	// Analog Balance
2931 				for (uint32 c = 0; c < fColors; c++) {
2932 					analogBalance[c] = fRead.NextDouble(TIFF_FRACTION_TYPE);
2933 					//printf("ab: %g\n", analogBalance[c]);
2934 				}
2935 				break;
2936 #if 0
2937       case 50728:			/* AsShotNeutral */
2938 	FORCC asn[c] = getreal(type);
2939 	break;
2940       case 50729:			/* AsShotWhiteXY */
2941 	xyz[0] = getrat();
2942 	xyz[1] = getrat();
2943 	xyz[2] = 1 - xyz[0] - xyz[1];
2944 	FORC3 xyz[c] /= d65_white[c];
2945 	break;
2946       case 50740:			/* DNGPrivateData */
2947 	if (dng_version) break;
2948 	i = order;
2949 	parse_minolta (j = get4()+base);
2950 	order = i;
2951 	fseek (ifp, j, SEEK_SET);
2952 	parse_tiff_ifd (base);
2953 	break;
2954 #endif
2955 			case 50752:
2956 				fRead.NextShorts(fCR2Slice, 3);
2957 				break;
2958 
2959 			case 50829:	// Active Area
2960 				fTopMargin = fRead.Next(tag.type);
2961 				fLeftMargin = fRead.Next(tag.type);
2962 				fInputHeight = fRead.Next(tag.type) - fTopMargin;
2963 				fInputWidth = fRead.Next(tag.type) - fLeftMargin;
2964 				break;
2965 #if 0
2966       case 64772:			/* Kodak P-series */
2967 	fseek (ifp, 16, SEEK_CUR);
2968 	data_offset = get4();
2969 	fseek (ifp, 28, SEEK_CUR);
2970 	data_offset += get4();
2971 	load_raw = &CLASS packed_12_load_raw;
2972 #endif
2973 		}
2974 		fRead.Seek(nextOffset, SEEK_SET);
2975 	}
2976 
2977 	// handle SONY tags
2978 
2979 #if 0
2980 	if (sony_length && (buf = (unsigned *) malloc(sony_length))) {
2981 		fseek(ifp, sony_offset, SEEK_SET);
2982 		fread(buf, sony_length, 1, ifp);
2983 		sony_decrypt(buf, sony_length / 4, 1, sony_key);
2984 		sfp = ifp;
2985 		if ((ifp = tmpfile())) {
2986 			fwrite(buf, sony_length, 1, ifp);
2987 			fseek(ifp, 0, SEEK_SET);
2988 			parse_tiff_ifd(-sony_offset);
2989 			fclose(ifp);
2990 		}
2991 		ifp = sfp;
2992 		free(buf);
2993 	}
2994 #endif
2995 
2996 	for (uint32 i = 0; i < fColors; i++) {
2997 		for (uint32 c = 0; c < fColors; c++) {
2998 			cameraCalibration[i][c] *= analogBalance[i];
2999 		}
3000 	}
3001 
3002 	if (useColorMatrix) {
3003 		for (uint32 c = 0; c < fColors; c++) {
3004 			for (uint32 i = 0; i < 3; i++) {
3005 				cam_xyz[c][i] = 0;
3006 				for (uint32 j = 0; j < fColors; j++) {
3007 					cam_xyz[c][i] += cameraCalibration[c][j]
3008 						* colorMatrix[j][i] * xyz[i];
3009 				}
3010 			}
3011 		}
3012 		_CameraXYZCoefficients(cam_xyz);
3013 	}
3014 
3015 #if 0
3016 	if (asn[0])
3017     	FORCC pre_multipliers[c] = 1 / asn[c];
3018 #endif
3019 	if (!useColorMatrix) {
3020 		for (uint32 c = 0; c < fColors; c++) {
3021 			fMeta.pre_multipliers[c] /= cameraCalibration[c][c];
3022 		}
3023 	}
3024 
3025 	return B_OK;
3026 }
3027 
3028 
3029 status_t
3030 DCRaw::_ParseTIFFImageFileDirectory(off_t baseOffset)
3031 {
3032 	while (fNumImages < kImageBufferCount) {
3033 		int32 offset;
3034 		fRead(offset);
3035 		if (offset == 0)
3036 			break;
3037 
3038 		status_t status = _ParseTIFFImageFileDirectory(baseOffset, offset);
3039 		if (status < B_OK)
3040 			return status;
3041 
3042 		fNumImages++;
3043 	}
3044 
3045 	return B_OK;
3046 }
3047 
3048 
3049 status_t
3050 DCRaw::_ParseTIFF(off_t baseOffset)
3051 {
3052 	fRead.Stream().Seek(baseOffset, SEEK_SET);
3053 
3054 	uint16 endian;
3055 	fRead(endian);
3056 	if (endian != 'MM' && endian != 'II')
3057 		return B_NO_TRANSLATOR;
3058 
3059 #if B_HOST_IS_LENDIAN
3060 	fRead.SetSwap(endian == 'MM');
3061 #else
3062 	fRead.SetSwap(endian == 'II');
3063 #endif
3064 
3065 	fRead(endian);
3066 		// dummy, not used, should be 42 for actual TIFF images,
3067 		// but may vary for RAW images
3068 
3069 	_ParseTIFFImageFileDirectory(baseOffset);
3070 	fIsTIFF = true;
3071 
3072 	uint32 maxSamples = 0;
3073 
3074 	if (fThumbIndex >= 0 && _Thumb().data_offset) {
3075 		fRead.Seek(_Thumb().data_offset, SEEK_SET);
3076 
3077 		jhead jh;
3078 		if (_LosslessJPEGInit(&jh, true)) {
3079 			_Thumb().bits_per_sample = jh.bits;
3080 			_Thumb().width = jh.wide;
3081 			_Thumb().height = jh.high;
3082 			_Thumb().bits_per_sample = 16;
3083 		}
3084 	}
3085 
3086 	// identify RAW image in list of images retrieved
3087 
3088 	for (uint32 i = 0; i < fNumImages; i++) {
3089 		if (maxSamples < fImages[i].samples)
3090 			maxSamples = fImages[i].samples;
3091 
3092 		if (fImages[i].compression != 6 || fImages[i].samples != 3) {
3093 			fImages[i].is_raw = true;
3094 
3095 			if (fRawIndex < 0 || fImages[i].width * fImages[i].height
3096 					> _Raw().width * _Raw().height) {
3097 				fRawIndex = i;
3098 				//fuji_secondary = _Raw().samples == 2;
3099 			}
3100 		}
3101 	}
3102 
3103 	if (fRawIndex < 0 || (!fDNGVersion && _Raw().samples == 3 && _Raw().bits_per_sample == 8))
3104 		throw (status_t)B_NO_TRANSLATOR;
3105 
3106 	if (fRawIndex >= 0) {
3107 		fMeta.raw_width = _Raw().width;
3108 		fMeta.raw_height = _Raw().height;
3109 	}
3110 
3111 #if 0
3112   fuji_width *= (raw_width+1)/2;
3113   if (tiff_ifd[0].flip) tiff_flip = tiff_ifd[0].flip;
3114   if (raw >= 0 && !load_raw)
3115     switch (tiff_compress) {
3116       case 0:  case 1:
3117 	load_raw = tiff_bps > 8 ?
3118 	  &CLASS unpacked_load_raw : &CLASS eight_bit_load_raw;
3119 	if (tiff_ifd[raw].bytes * 5 == raw_width * raw_height * 8)
3120 	  load_raw = &CLASS olympus_e300_load_raw;
3121 	if (tiff_bps == 12 && tiff_ifd[raw].phint == 2)
3122 	  load_raw = &CLASS olympus_cseries_load_raw;
3123 	break;
3124       case 6:  case 7:  case 99:
3125 	load_raw = &CLASS lossless_jpeg_load_raw;		break;
3126       case 262:
3127 	load_raw = &CLASS kodak_262_load_raw;			break;
3128       case 32773:
3129 	load_raw = &CLASS packed_12_load_raw;			break;
3130       case 65535:
3131 	load_raw = &CLASS pentax_k10_load_raw;			break;
3132       case 65000:
3133 	switch (tiff_ifd[raw].phint) {
3134 	  case 2: load_raw = &CLASS kodak_rgb_load_raw;   fFilters = 0;  break;
3135 	  case 6: load_raw = &CLASS kodak_ycbcr_load_raw; fFilters = 0;  break;
3136 	  case 32803: load_raw = &CLASS kodak_65000_load_raw;
3137 	}
3138     }
3139   if (tiff_samples == 3 && tiff_bps == 8)
3140     if (!dng_version) is_raw = 0;
3141 #endif
3142 
3143 #if 0
3144   if (thm >= 0) {
3145     thumb_misc |= tiff_ifd[thm].samples << 5;
3146     switch (tiff_ifd[thm].comp) {
3147       case 0:
3148 	write_thumb = &CLASS layer_thumb;
3149 	break;
3150       case 1:
3151 	if (tiff_ifd[thm].bps > 8)
3152 	  thumb_load_raw = &CLASS kodak_thumb_load_raw;
3153 	else
3154 	  write_thumb = &CLASS ppm_thumb;
3155 	break;
3156       case 65000:
3157 	thumb_load_raw = tiff_ifd[thm].phint == 6 ?
3158 		&CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw;
3159     }
3160   }
3161 #endif
3162 	return B_OK;
3163 }
3164 
3165 
3166 //	#pragma mark -
3167 
3168 
3169 status_t
3170 DCRaw::Identify()
3171 {
3172 	fRead.Seek(0, SEEK_SET);
3173 
3174 	status_t status = B_NO_TRANSLATOR;
3175 	char header[32];
3176 	fRead(header, sizeof(header));
3177 
3178 	// check for TIFF-like files first
3179 
3180 	uint16 endian = *(uint16*)&header;
3181 	if (endian == 'II' || endian == 'MM')
3182 		status = _ParseTIFF(0);
3183 
3184 	if (status < B_OK)
3185 		return status;
3186 
3187 	// brush up some variables for later use
3188 
3189 	fInputWidth = _Raw().width;
3190 	fInputHeight = _Raw().height;
3191 
3192 	_FixupValues();
3193 
3194 	if ((_Raw().width | _Raw().height) < 0)
3195 		_Raw().width = _Raw().height = 0;
3196 	if (fMeta.maximum == 0)
3197 		fMeta.maximum = (1 << _Raw().bits_per_sample) - 1;
3198 
3199 	if (fFilters == ~0UL)
3200 		fFilters = 0x94949494;
3201 	if (fFilters && fColors == 3) {
3202 		for (int32 i = 0; i < 32; i += 4) {
3203 			if ((fFilters >> i & 15) == 9)
3204 				fFilters |= 2 << i;
3205 			if ((fFilters >> i & 15) == 6)
3206 				fFilters |= 8 << i;
3207 		}
3208 	}
3209 
3210 	if (fRawColor)
3211 		_AdobeCoefficients(fMeta.manufacturer, fMeta.model);
3212 
3213 	// remove invalid images
3214 
3215 	int32 rawCount = 0;
3216 
3217 	for (int32 i = 0; i < (int32)fNumImages; i++) {
3218 		if (fImages[i].width == 0 || fImages[i].height == 0 || fImages[i].data_offset == 0) {
3219 			fNumImages--;
3220 			if (i == fRawIndex)
3221 				fRawIndex = -1;
3222 			else if (i < fRawIndex)
3223 				fRawIndex--;
3224 			if (i == fThumbIndex)
3225 				fThumbIndex = -1;
3226 			else if (i < fThumbIndex)
3227 				fThumbIndex--;
3228 
3229 			if (i < (int32)fNumImages) {
3230 				memmove(&fImages[i], &fImages[i + 1],
3231 					sizeof(image_data_info) * (fNumImages - i));
3232 			}
3233 			i--;
3234 		} else if (fImages[i].is_raw)
3235 			rawCount++;
3236 	}
3237 
3238 	// This is to prevent us from identifying TIFF images
3239 	if (rawCount == 0)
3240 		return B_NO_TRANSLATOR;
3241 
3242 	return B_OK;
3243 }
3244 
3245 
3246 status_t
3247 DCRaw::ReadImageAt(uint32 index, uint8*& outputBuffer, size_t& bufferSize)
3248 {
3249 	if (index >= fNumImages)
3250 		return B_BAD_VALUE;
3251 
3252 	_CorrectIndex(index);
3253 
3254 	image_data_info& image = fImages[index];
3255 
3256 	fShrink = (fHalfSize || fThreshold) && fFilters;
3257 	fOutputWidth = (fInputWidth + fShrink) >> fShrink;
3258 	fOutputHeight = (fInputHeight + fShrink) >> fShrink;
3259 
3260 	if (image.flip & 4) {
3261 		// image is rotated
3262 		image.output_width = fOutputHeight;
3263 		image.output_height = fOutputWidth;
3264 	} else {
3265 		image.output_width = fOutputWidth;
3266 		image.output_height = fOutputHeight;
3267 	}
3268 
3269 	if (image.is_raw) {
3270 		bufferSize = fOutputWidth * 4 * fOutputHeight;
3271 
3272 		fImageData = (uint16 (*)[4])calloc(fOutputWidth * fOutputHeight
3273 			* sizeof(*fImageData) + 0, 1); //meta_length, 1);
3274 		if (fImageData == NULL)
3275 			throw (status_t)B_NO_MEMORY;
3276 	} else {
3277 		bufferSize = image.bytes + sizeof(tiff_header) + 10;
3278 			// TIFF header plus EXIF identifier
3279 	}
3280 
3281 	outputBuffer = (uint8*)malloc(bufferSize);
3282 	if (outputBuffer == NULL)
3283 		throw (status_t)B_NO_MEMORY;
3284 
3285 	fRead.Seek(image.data_offset, SEEK_SET);
3286 
3287 	if (image.is_raw) {
3288 		_LoadRAW(image);
3289 
3290 		//bad_pixels();
3291 		//if (dark_frame) subtract (dark_frame);
3292 		//quality = 2 + !fuji_width;
3293 
3294 		if (fDocumentMode < 2)
3295 			_ScaleColors();
3296 		_PreInterpolate();
3297 		_CameraToCIELab(NULL, NULL);
3298 
3299 		if (fFilters && !fDocumentMode) {
3300 #if 0
3301 			if (quality == 0)
3302 				lin_interpolate();
3303 			else if (quality < 3 || colors > 3)
3304 				vng_interpolate();
3305 #endif
3306 			_AHDInterpolate();
3307 		}
3308 
3309 #if 0
3310 		if (fHightlight > 1)
3311 			_RecoverHighlights();
3312 		if (use_fuji_rotate) fuji_rotate();
3313 		if (mix_green && (colors = 3))
3314 			for (i=0; i < height*width; i++)
3315 				image[i][1] = (image[i][1] + image[i][3]) >> 1;
3316 #endif
3317 
3318 		_ConvertToRGB();
3319 		//if (use_fuji_rotate) stretch();
3320 
3321 		_WriteRGB32(image, outputBuffer);
3322 	} else {
3323 		_WriteJPEG(image, outputBuffer);
3324 	}
3325 
3326 	return B_OK;
3327 }
3328 
3329 
3330 void
3331 DCRaw::GetMetaInfo(image_meta_info& metaInfo) const
3332 {
3333 	metaInfo = fMeta;
3334 }
3335 
3336 
3337 uint32
3338 DCRaw::CountImages() const
3339 {
3340 	return fNumImages;
3341 }
3342 
3343 
3344 status_t
3345 DCRaw::ImageAt(uint32 index, image_data_info& info) const
3346 {
3347 	if (index >= fNumImages)
3348 		return B_BAD_VALUE;
3349 
3350 	_CorrectIndex(index);
3351 
3352 	info = fImages[index];
3353 	return B_OK;
3354 }
3355 
3356