1 // ==========================================================
2 // RAW camera image loader
3 //
4 // Design and implementation by
5 // - Herv� Drolon (drolon@infonie.fr)
6 //
7 // This file is part of FreeImage 3
8 //
9 // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
10 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
11 // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
12 // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
13 // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
14 // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
15 // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
16 // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
17 // THIS DISCLAIMER.
18 //
19 // Use at your own risk!
20 // ==========================================================
21 
22 #include "../LibRawLite/libraw/libraw.h"
23 
24 #include "FreeImage.h"
25 #include "Utilities.h"
26 #include "../Metadata/FreeImageTag.h"
27 
28 // ==========================================================
29 // Plugin Interface
30 // ==========================================================
31 
32 static int s_format_id;
33 
34 // ==========================================================
35 // Internal functions
36 // ==========================================================
37 
38 // ----------------------------------------------------------
39 //   FreeImage datastream wrapper
40 // ----------------------------------------------------------
41 
42 class LibRaw_freeimage_datastream : public LibRaw_abstract_datastream {
43 private:
44 	FreeImageIO *_io;
45 	fi_handle _handle;
46 	long _eof;
47 	INT64 _fsize;
48 
49 public:
LibRaw_freeimage_datastream(FreeImageIO * io,fi_handle handle)50 	LibRaw_freeimage_datastream(FreeImageIO *io, fi_handle handle) : _io(io), _handle(handle) {
51 		long start_pos = io->tell_proc(handle);
52 		io->seek_proc(handle, 0, SEEK_END);
53 		_eof = io->tell_proc(handle);
54 		_fsize = _eof - start_pos;
55 		io->seek_proc(handle, start_pos, SEEK_SET);
56 	}
57 
~LibRaw_freeimage_datastream()58 	~LibRaw_freeimage_datastream() {
59 	}
60 
valid()61     int valid() {
62 		return (_io && _handle);
63 	}
64 
read(void * buffer,size_t size,size_t count)65     int read(void *buffer, size_t size, size_t count) {
66 		if(substream) return substream->read(buffer, size, count);
67 		return _io->read_proc(buffer, (unsigned)size, (unsigned)count, _handle);
68 	}
69 
seek(INT64 offset,int origin)70     int seek(INT64 offset, int origin) {
71         if(substream) return substream->seek(offset, origin);
72 		return _io->seek_proc(_handle, (long)offset, origin);
73 	}
74 
tell()75     INT64 tell() {
76 		if(substream) return substream->tell();
77         return _io->tell_proc(_handle);
78     }
79 
size()80 	INT64 size() {
81 		return _fsize;
82 	}
83 
get_char()84     int get_char() {
85 		int c = 0;
86 		if(substream) return substream->get_char();
87 		if(!_io->read_proc(&c, 1, 1, _handle)) return -1;
88 		return c;
89    }
90 
gets(char * buffer,int length)91 	char* gets(char *buffer, int length) {
92 		if (substream) return substream->gets(buffer, length);
93 		memset(buffer, 0, length);
94 		for(int i = 0; i < length; i++) {
95 			if(!_io->read_proc(&buffer[i], 1, 1, _handle))
96 				return NULL;
97 			if(buffer[i] == 0x0A)
98 				break;
99 		}
100 		return buffer;
101 	}
102 
scanf_one(const char * fmt,void * val)103 	int scanf_one(const char *fmt, void* val) {
104 		std::string buffer;
105 		char element = 0;
106 		bool bDone = false;
107 		if(substream) return substream->scanf_one(fmt,val);
108 		do {
109 			if(_io->read_proc(&element, 1, 1, _handle) == 1) {
110 				switch(element) {
111 					case '0':
112 					case '\n':
113 					case ' ':
114 					case '\t':
115 						bDone = true;
116 						break;
117 					default:
118 						break;
119 				}
120 				buffer.append(&element, 1);
121 			} else {
122 				return 0;
123 			}
124 		} while(!bDone);
125 
126 		return sscanf(buffer.c_str(), fmt, val);
127 	}
128 
eof()129 	int eof() {
130 		if(substream) return substream->eof();
131         return (_io->tell_proc(_handle) >= _eof);
132     }
133 
make_jas_stream()134 	void * make_jas_stream() {
135 		return NULL;
136 	}
137 };
138 
139 // ----------------------------------------------------------
140 
141 /**
142 Convert a processed raw data array to a FIBITMAP
143 @param RawProcessor LibRaw handle containing the processed raw image
144 @return Returns the converted dib if successfull, returns NULL otherwise
145 */
146 static FIBITMAP *
libraw_ConvertProcessedRawToDib(LibRaw * RawProcessor)147 libraw_ConvertProcessedRawToDib(LibRaw *RawProcessor) {
148 	FIBITMAP *dib = NULL;
149     int width, height, colors, bpp;
150 
151 	try {
152 		int bgr = 0;	// pixel copy order: RGB if (bgr == 0) and BGR otherwise
153 
154 		// get image info
155 		RawProcessor->get_mem_image_format(&width, &height, &colors, &bpp);
156 
157 		// only 3-color images supported...
158 		if(colors != 3) {
159 			throw "LibRaw : only 3-color images supported";
160 		}
161 
162 		if(bpp == 16) {
163 			// allocate output dib
164 			dib = FreeImage_AllocateT(FIT_RGB16, width, height);
165 			if(!dib) {
166 				throw FI_MSG_ERROR_DIB_MEMORY;
167 			}
168 
169 		} else if(bpp == 8) {
170 #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
171 			bgr = 1;	// only useful for FIT_BITMAP types
172 #endif
173 
174 			// allocate output dib
175 			dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24);
176 			if(!dib) {
177 				throw FI_MSG_ERROR_DIB_MEMORY;
178 			}
179 		}
180 
181 		// copy post-processed bitmap data into FIBITMAP buffer
182 		if(RawProcessor->copy_mem_image(FreeImage_GetBits(dib), FreeImage_GetPitch(dib), bgr) != LIBRAW_SUCCESS) {
183 			throw "LibRaw : failed to copy data into dib";
184 		}
185 
186 		// flip vertically
187 		FreeImage_FlipVertical(dib);
188 
189 		return dib;
190 
191 	} catch(const char *text) {
192 		FreeImage_Unload(dib);
193 		FreeImage_OutputMessageProc(s_format_id, text);
194 		return NULL;
195 	}
196 }
197 
198 
199 /**
200 Convert a processed raw image to a FIBITMAP
201 @param image Processed raw image
202 @return Returns the converted dib if successfull, returns NULL otherwise
203 @see libraw_LoadEmbeddedPreview
204 */
205 static FIBITMAP *
libraw_ConvertProcessedImageToDib(libraw_processed_image_t * image)206 libraw_ConvertProcessedImageToDib(libraw_processed_image_t *image) {
207 	FIBITMAP *dib = NULL;
208 
209 	try {
210 		unsigned width = image->width;
211 		unsigned height = image->height;
212 		unsigned bpp = image->bits;
213 		if(bpp == 16) {
214 			// allocate output dib
215 			dib = FreeImage_AllocateT(FIT_RGB16, width, height);
216 			if(!dib) {
217 				throw FI_MSG_ERROR_DIB_MEMORY;
218 			}
219 			// write data
220 			WORD *raw_data = (WORD*)image->data;
221 			for(unsigned y = 0; y < height; y++) {
222 				FIRGB16 *output = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y);
223 				for(unsigned x = 0; x < width; x++) {
224 					output[x].red   = raw_data[0];
225 					output[x].green = raw_data[1];
226 					output[x].blue  = raw_data[2];
227 					raw_data += 3;
228 				}
229 			}
230 		} else if(bpp == 8) {
231 			// allocate output dib
232 			dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24);
233 			if(!dib) {
234 				throw FI_MSG_ERROR_DIB_MEMORY;
235 			}
236 			// write data
237 			BYTE *raw_data = (BYTE*)image->data;
238 			for(unsigned y = 0; y < height; y++) {
239 				RGBTRIPLE *output = (RGBTRIPLE*)FreeImage_GetScanLine(dib, height - 1 - y);
240 				for(unsigned x = 0; x < width; x++) {
241 					output[x].rgbtRed   = raw_data[0];
242 					output[x].rgbtGreen = raw_data[1];
243 					output[x].rgbtBlue  = raw_data[2];
244 					raw_data += 3;
245 				}
246 			}
247 		}
248 
249 		return dib;
250 
251 	} catch(const char *text) {
252 		FreeImage_Unload(dib);
253 		FreeImage_OutputMessageProc(s_format_id, text);
254 		return NULL;
255 	}
256 }
257 
258 /**
259 Get the embedded JPEG preview image from RAW picture with included Exif Data.
260 @param RawProcessor Libraw handle
261 @param flags JPEG load flags
262 @return Returns the loaded dib if successfull, returns NULL otherwise
263 */
264 static FIBITMAP *
libraw_LoadEmbeddedPreview(LibRaw * RawProcessor,int flags)265 libraw_LoadEmbeddedPreview(LibRaw *RawProcessor, int flags) {
266 	FIBITMAP *dib = NULL;
267 	libraw_processed_image_t *thumb_image = NULL;
268 
269 	try {
270 		// unpack data
271 		if(RawProcessor->unpack_thumb() != LIBRAW_SUCCESS) {
272 			// run silently "LibRaw : failed to run unpack_thumb"
273 			return NULL;
274 		}
275 
276 		// retrieve thumb image
277 		int error_code = 0;
278 		thumb_image = RawProcessor->dcraw_make_mem_thumb(&error_code);
279 		if(thumb_image) {
280 			if(thumb_image->type != LIBRAW_IMAGE_BITMAP) {
281 				// attach the binary data to a memory stream
282 				FIMEMORY *hmem = FreeImage_OpenMemory((BYTE*)thumb_image->data, (DWORD)thumb_image->data_size);
283 				// get the file type
284 				FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0);
285 				if(fif == FIF_JPEG) {
286 					// rotate according to Exif orientation
287 					flags |= JPEG_EXIFROTATE;
288 				}
289 				// load an image from the memory stream
290 				dib = FreeImage_LoadFromMemory(fif, hmem, flags);
291 				// close the stream
292 				FreeImage_CloseMemory(hmem);
293 			} else if((flags & FIF_LOAD_NOPIXELS) != FIF_LOAD_NOPIXELS) {
294 				// convert processed data to output dib
295 				dib = libraw_ConvertProcessedImageToDib(thumb_image);
296 			}
297 		} else {
298 			throw "LibRaw : failed to run dcraw_make_mem_thumb";
299 		}
300 
301 		// clean-up and return
302 		RawProcessor->dcraw_clear_mem(thumb_image);
303 
304 		return dib;
305 
306 	} catch(const char *text) {
307 		// clean-up and return
308 		if(thumb_image) {
309 			RawProcessor->dcraw_clear_mem(thumb_image);
310 		}
311 		if(text != NULL) {
312 			FreeImage_OutputMessageProc(s_format_id, text);
313 		}
314 	}
315 
316 	return NULL;
317 }
318 /**
319 Load raw data and convert to FIBITMAP
320 @param RawProcessor Libraw handle
321 @param bitspersample Output bitdepth (8- or 16-bit)
322 @return Returns the loaded dib if successfull, returns NULL otherwise
323 */
324 static FIBITMAP *
libraw_LoadRawData(LibRaw * RawProcessor,int bitspersample)325 libraw_LoadRawData(LibRaw *RawProcessor, int bitspersample) {
326 	FIBITMAP *dib = NULL;
327 
328 	try {
329 		// set decoding parameters
330 		// -----------------------
331 
332 		// (-6) 16-bit or 8-bit
333 		RawProcessor->imgdata.params.output_bps = bitspersample;
334 		// (-g power toe_slope)
335 		if(bitspersample == 16) {
336 			// set -g 1 1 for linear curve
337 			RawProcessor->imgdata.params.gamm[0] = 1;
338 			RawProcessor->imgdata.params.gamm[1] = 1;
339 		} else if(bitspersample == 8) {
340 			// by default settings for rec. BT.709 are used: power 2.222 (i.e. gamm[0]=1/2.222) and slope 4.5
341 			RawProcessor->imgdata.params.gamm[0] = 1/2.222;
342 			RawProcessor->imgdata.params.gamm[1] = 4.5;
343 		}
344 		// (-W) Don't use automatic increase of brightness by histogram
345 		RawProcessor->imgdata.params.no_auto_bright = 1;
346 		// (-a) Use automatic white balance obtained after averaging over the entire image
347 		RawProcessor->imgdata.params.use_auto_wb = 1;
348 		// (-q 3) Adaptive homogeneity-directed demosaicing algorithm (AHD)
349 		RawProcessor->imgdata.params.user_qual = 3;
350 
351 		// -----------------------
352 
353 		// unpack data
354 		if(RawProcessor->unpack() != LIBRAW_SUCCESS) {
355 			throw "LibRaw : failed to unpack data";
356 		}
357 
358 		// process data (... most consuming task ...)
359 		if(RawProcessor->dcraw_process() != LIBRAW_SUCCESS) {
360 			throw "LibRaw : failed to process data";
361 		}
362 
363 		// retrieve processed image
364 		dib = libraw_ConvertProcessedRawToDib(RawProcessor);
365 
366 		return dib;
367 
368 	} catch(const char *text) {
369 		FreeImage_OutputMessageProc(s_format_id, text);
370 		return NULL;
371 	}
372 }
373 
374 /**
375 Load the Bayer matrix (unprocessed raw data) as a FIT_UINT16 image.
376 Note that some formats don't have a Bayer matrix (e.g. Foveon, Canon sRAW, demosaiced DNG files).
377 @param RawProcessor Libraw handle
378 @return Returns the loaded dib if successfull, returns NULL otherwise
379 */
380 static FIBITMAP *
libraw_LoadUnprocessedData(LibRaw * RawProcessor)381 libraw_LoadUnprocessedData(LibRaw *RawProcessor) {
382 	FIBITMAP *dib = NULL;
383 
384 	try {
385 		// unpack data
386 		if(RawProcessor->unpack() != LIBRAW_SUCCESS) {
387 			throw "LibRaw : failed to unpack data";
388 		}
389 
390 		// check for a supported Bayer format
391 		if(!(RawProcessor->imgdata.idata.filters || RawProcessor->imgdata.idata.colors == 1)) {
392 			throw "LibRaw : only Bayer-pattern RAW files are supported";
393 		}
394 
395 		// allocate output dib
396 		const unsigned width = RawProcessor->imgdata.sizes.raw_width;
397 		const unsigned height = RawProcessor->imgdata.sizes.raw_height;
398 		const size_t line_size = width * sizeof(WORD);
399 		const WORD *src_bits = (WORD*)RawProcessor->imgdata.rawdata.raw_image;
400 
401 		if(src_bits) {
402 			dib = FreeImage_AllocateT(FIT_UINT16, width, height);
403 		}
404 		if(!dib) {
405 			throw FI_MSG_ERROR_DIB_MEMORY;
406 		}
407 
408 		// retrieve the raw image
409 		for(unsigned y = 0; y < height; y++) {
410 			WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y);
411 			memcpy(dst_bits, src_bits, line_size);
412 			src_bits += width;
413 		}
414 
415 		// store metadata needed for post-processing
416 		{
417 			char value[512];
418 
419 			const libraw_image_sizes_t *sizes = &RawProcessor->imgdata.sizes;
420 
421 			// image output width & height
422 			{
423 				sprintf(value, "%d", sizes->iwidth);
424 				FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Output.Width", value);
425 
426 				sprintf(value, "%d", sizes->iheight);
427 				FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Output.Height", value);
428 			}
429 
430 			// image output frame
431 			{
432 				const unsigned f_left = sizes->left_margin;
433 				const unsigned f_top = sizes->top_margin;
434 				const unsigned f_width = sizes->width;
435 				const unsigned f_height = sizes->height;
436 
437 				sprintf(value, "%d", f_left);
438 				FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Left", value);
439 
440 				sprintf(value, "%d", f_top);
441 				FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Top", value);
442 
443 				sprintf(value, "%d", f_width);
444 				FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Width", value);
445 
446 				sprintf(value, "%d", f_height);
447 				FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.Frame.Height", value);
448 			}
449 
450 			// Bayer pattern
451 			// Mask describing the order of color pixels in the matrix.
452 			// This field describe 16 pixels (8 rows with two pixels in each, from left to right and from top to bottom).
453 
454 			if(RawProcessor->imgdata.idata.filters) {
455 				// description of colors numbered from 0 to 3 (RGBG,RGBE,GMCY, or GBTG)
456 				char *cdesc = RawProcessor->imgdata.idata.cdesc;
457 				if(!cdesc[3]) {
458 					cdesc[3] = 'G';
459 				}
460 				char *pattern = &value[0];
461 				for(int i = 0; i < 16; i++) {
462 					pattern[i] = cdesc[ RawProcessor->fcol(i >> 1, i & 1) ];
463 				}
464 				pattern[16] = 0;
465 
466 				FreeImage_SetMetadataKeyValue(FIMD_COMMENTS, dib, "Raw.BayerPattern", value);
467 			}
468 		}
469 
470 		return dib;
471 
472 	} catch(const char *text) {
473 		FreeImage_Unload(dib);
474 		FreeImage_OutputMessageProc(s_format_id, text);
475 		return NULL;
476 	}
477 }
478 
479 // ==========================================================
480 // Plugin Implementation
481 // ==========================================================
482 
483 static const char * DLL_CALLCONV
Format()484 Format() {
485 	return "RAW";
486 }
487 
488 static const char * DLL_CALLCONV
Description()489 Description() {
490 	return "RAW camera image";
491 }
492 
493 static const char * DLL_CALLCONV
Extension()494 Extension() {
495 	/**
496 	Below are known RAW file extensions that you can check using FreeImage_GetFIFFromFormat.
497 	If a file extension is not listed, that doesn't mean that you cannot load it.
498 	Using FreeImage_GetFileType is the best way to know if a RAW file format is supported.
499 	*/
500 	static const char *raw_extensions =
501 		"3fr,"   // Hasselblad Digital Camera Raw Image Format.
502 		"arw,"   // Sony Digital Camera Raw Image Format for Alpha devices.
503 		"bay,"   // Casio Digital Camera Raw File Format.
504 		"bmq,"   // NuCore Raw Image File.
505 		"cap,"   // Phase One Digital Camera Raw Image Format.
506 		"cine,"  // Phantom Software Raw Image File.
507 		"cr2,"   // Canon Digital Camera RAW Image Format version 2.0. These images are based on the TIFF image standard.
508 		"crw,"   // Canon Digital Camera RAW Image Format version 1.0.
509 		"cs1,"   // Sinar Capture Shop Raw Image File.
510 		"dc2,"   // Kodak DC25 Digital Camera File.
511 		"dcr,"   // Kodak Digital Camera Raw Image Format for these models: Kodak DSC Pro SLR/c, Kodak DSC Pro SLR/n, Kodak DSC Pro 14N, Kodak DSC PRO 14nx.
512 		"drf,"   // Kodak Digital Camera Raw Image Format.
513 		"dsc,"   // Kodak Digital Camera Raw Image Format.
514 		"dng,"   // Adobe Digital Negative: DNG is publicly available archival format for the raw files generated by digital cameras. By addressing the lack of an open standard for the raw files created by individual camera models, DNG helps ensure that photographers will be able to access their files in the future.
515 		"erf,"   // Epson Digital Camera Raw Image Format.
516 		"fff,"   // Imacon Digital Camera Raw Image Format.
517 		"ia,"    // Sinar Raw Image File.
518 		"iiq,"   // Phase One Digital Camera Raw Image Format.
519 		"k25,"   // Kodak DC25 Digital Camera Raw Image Format.
520 		"kc2,"   // Kodak DCS200 Digital Camera Raw Image Format.
521 		"kdc,"   // Kodak Digital Camera Raw Image Format.
522 		"mdc,"   // Minolta RD175 Digital Camera Raw Image Format.
523 		"mef,"   // Mamiya Digital Camera Raw Image Format.
524 		"mos,"   // Leaf Raw Image File.
525 		"mrw,"   // Minolta Dimage Digital Camera Raw Image Format.
526 		"nef,"   // Nikon Digital Camera Raw Image Format.
527 		"nrw,"   // Nikon Digital Camera Raw Image Format.
528 		"orf,"   // Olympus Digital Camera Raw Image Format.
529 		"pef,"   // Pentax Digital Camera Raw Image Format.
530 		"ptx,"   // Pentax Digital Camera Raw Image Format.
531 		"pxn,"   // Logitech Digital Camera Raw Image Format.
532 		"qtk,"   // Apple Quicktake 100/150 Digital Camera Raw Image Format.
533 		"raf,"   // Fuji Digital Camera Raw Image Format.
534 		"raw,"   // Panasonic Digital Camera Image Format.
535 		"rdc,"   // Digital Foto Maker Raw Image File.
536 		"rw2,"   // Panasonic LX3 Digital Camera Raw Image Format.
537 		"rwl,"	 // Leica Camera Raw Image Format.
538 		"rwz,"   // Rawzor Digital Camera Raw Image Format.
539 		"sr2,"   // Sony Digital Camera Raw Image Format.
540 		"srf,"   // Sony Digital Camera Raw Image Format for DSC-F828 8 megapixel digital camera or Sony DSC-R1.
541 		"srw,"   // Samsung Raw Image Format.
542 		"sti,"   // Sinar Capture Shop Raw Image File.
543 		"x3f";   // Sigma Digital Camera Raw Image Format for devices based on Foveon X3 direct image sensor.
544 	return raw_extensions;
545 }
546 
547 static const char * DLL_CALLCONV
RegExpr()548 RegExpr() {
549 	return NULL;
550 }
551 
552 static const char * DLL_CALLCONV
MimeType()553 MimeType() {
554 	return "image/x-dcraw";
555 }
556 
557 static BOOL
HasMagicHeader(FreeImageIO * io,fi_handle handle)558 HasMagicHeader(FreeImageIO *io, fi_handle handle) {
559 	const unsigned signature_size = 32;
560 	BYTE signature[signature_size] = { 0 };
561 	/*
562 	note: classic TIFF signature is
563 	{ 0x49, 0x49, 0x2A, 0x00 } Classic TIFF, little-endian
564 	{ 0x4D, 0x4D, 0x00, 0x2A } Classic TIFF, big-endian
565 	*/
566 	// Canon (CR2), little-endian byte order
567 	const BYTE CR2_II[] = { 0x49, 0x49, 0x2A, 0x00, 0x10, 0x00, 0x00, 0x00, 0x43, 0x52, 0x02, 0x00 };
568 	// Canon (CRW), little-endian byte order
569 	const BYTE CRW_II[] = { 0x49, 0x49, 0x1A, 0x00, 0x00, 0x00, 0x48, 0x45, 0x41, 0x50, 0x43, 0x43, 0x44, 0x52, 0x02, 0x00 };
570 	// Minolta (MRW)
571 	const BYTE MRW[] = { 0x00, 0x4D, 0x52, 0x4D, 0x00 };
572 	// Olympus (ORF), little-endian byte order
573 	const BYTE ORF_IIRS[] = { 0x49, 0x49, 0x52, 0x53, 0x08, 0x00, 0x00, 0x00 };
574 	const BYTE ORF_IIRO[] = { 0x49, 0x49, 0x52, 0x4F, 0x08, 0x00, 0x00, 0x00 };
575 	// Olympus (ORF), big-endian byte order
576 	const BYTE ORF_MMOR[] = { 0x4D, 0x4D, 0x4F, 0x52, 0x00, 0x00, 0x00, 0x08 };
577 	// Fujifilm (RAF)
578 	const BYTE RAF[] = { 0x46, 0x55, 0x4A, 0x49, 0x46, 0x49, 0x4C, 0x4D, 0x43, 0x43, 0x44, 0x2D, 0x52, 0x41, 0x57, 0x20 };
579 	// Panasonic (RW2) or Leica (RWL), little-endian byte order
580 	const BYTE RWx_II[] = { 0x49, 0x49, 0x55, 0x00, 0x18, 0x00, 0x00, 0x00, 0x88, 0xE7, 0x74, 0xD8, 0xF8, 0x25, 0x1D, 0x4D, 0x94, 0x7A, 0x6E, 0x77, 0x82, 0x2B, 0x5D, 0x6A };
581 	// Panasonic (RAW) or Leica (RAW), little-endian byte order
582 	const BYTE RAW_II[] = { 0x49, 0x49, 0x55, 0x00, 0x08, 0x00, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00 };
583 	// Foveon (X3F)
584 	const BYTE X3F[] = { 0x46, 0x4F, 0x56, 0x62 };
585 
586 	if(io->read_proc(signature, 1, signature_size, handle) != signature_size) {
587 		return FALSE;
588 	}
589 	if(memcmp(CR2_II, signature, 12) == 0)
590 		return TRUE;
591 	if(memcmp(CRW_II, signature, 16) == 0)
592 		return TRUE;
593 	if(memcmp(MRW, signature, 5) == 0)
594 		return TRUE;
595 	if(memcmp(ORF_IIRS, signature, 8) == 0)
596 		return TRUE;
597 	if(memcmp(ORF_IIRO, signature, 8) == 0)
598 		return TRUE;
599 	if(memcmp(ORF_MMOR, signature, 8) == 0)
600 		return TRUE;
601 	if(memcmp(RAF, signature, 16) == 0)
602 		return TRUE;
603 	if(memcmp(RWx_II, signature, 24) == 0)
604 		return TRUE;
605 	if(memcmp(RAW_II, signature, 18) == 0)
606 		return TRUE;
607 	if(memcmp(X3F, signature, 4) == 0)
608 		return TRUE;
609 
610 	return FALSE;
611 }
612 
613 static BOOL DLL_CALLCONV
Validate(FreeImageIO * io,fi_handle handle)614 Validate(FreeImageIO *io, fi_handle handle) {
615 	// some RAW files have a magic signature (most of them have a TIFF signature)
616 	// try to check this in order to speed up the file identification
617 	{
618 		long tell = io->tell_proc(handle);
619 		if( HasMagicHeader(io, handle) ) {
620 			return TRUE;
621 		} else {
622 			io->seek_proc(handle, tell, SEEK_SET);
623 		}
624 	}
625 
626 	// no magic signature : we need to open the file (it will take more time to identify it)
627 	// do not declare RawProcessor on the stack as it may be huge (300 KB)
628 	{
629 		LibRaw *RawProcessor = new(std::nothrow) LibRaw;
630 
631 		if(RawProcessor) {
632 			BOOL bSuccess = TRUE;
633 
634 			// wrap the input datastream
635 			LibRaw_freeimage_datastream datastream(io, handle);
636 
637 			// open the datastream
638 			if(RawProcessor->open_datastream(&datastream) != LIBRAW_SUCCESS) {
639 				bSuccess = FALSE;	// LibRaw : failed to open input stream (unknown format)
640 			}
641 
642 			// clean-up internal memory allocations
643 			RawProcessor->recycle();
644 			delete RawProcessor;
645 
646 			return bSuccess;
647 		}
648 	}
649 
650 	return FALSE;
651 }
652 
653 static BOOL DLL_CALLCONV
SupportsExportDepth(int depth)654 SupportsExportDepth(int depth) {
655 	return FALSE;
656 }
657 
658 static BOOL DLL_CALLCONV
SupportsExportType(FREE_IMAGE_TYPE type)659 SupportsExportType(FREE_IMAGE_TYPE type) {
660 	return FALSE;
661 }
662 
663 static BOOL DLL_CALLCONV
SupportsICCProfiles()664 SupportsICCProfiles() {
665 	return TRUE;
666 }
667 
668 static BOOL DLL_CALLCONV
SupportsNoPixels()669 SupportsNoPixels() {
670 	return TRUE;
671 }
672 
673 // ----------------------------------------------------------
674 
675 static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO * io,fi_handle handle,int page,int flags,void * data)676 Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
677 	FIBITMAP *dib = NULL;
678 	LibRaw *RawProcessor = NULL;
679 
680 	BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
681 
682 	try {
683 		// do not declare RawProcessor on the stack as it may be huge (300 KB)
684 		RawProcessor = new(std::nothrow) LibRaw;
685 		if(!RawProcessor) {
686 			throw FI_MSG_ERROR_MEMORY;
687 		}
688 
689 		// wrap the input datastream
690 		LibRaw_freeimage_datastream datastream(io, handle);
691 
692 		// set decoding parameters
693 		// the following parameters affect data reading
694 		// --------------------------------------------
695 
696 		// (-s [0..N-1]) Select one raw image from input file
697 		RawProcessor->imgdata.params.shot_select = 0;
698 		// (-w) Use camera white balance, if possible (otherwise, fallback to auto_wb)
699 		RawProcessor->imgdata.params.use_camera_wb = 1;
700 		// (-M) Use any color matrix from the camera metadata. This option only affects Olympus, Leaf, and Phase One cameras.
701 		RawProcessor->imgdata.params.use_camera_matrix = 1;
702 		// (-h) outputs the image in 50% size
703 		RawProcessor->imgdata.params.half_size = ((flags & RAW_HALFSIZE) == RAW_HALFSIZE) ? 1 : 0;
704 
705 		// open the datastream
706 		if(RawProcessor->open_datastream(&datastream) != LIBRAW_SUCCESS) {
707 			throw "LibRaw : failed to open input stream (unknown format)";
708 		}
709 
710 		if(header_only) {
711 			// header only mode
712 			dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, RawProcessor->imgdata.sizes.width, RawProcessor->imgdata.sizes.height);
713 		}
714 		else if((flags & RAW_UNPROCESSED) == RAW_UNPROCESSED) {
715 			// load raw data without post-processing (i.e. as a Bayer matrix)
716 			dib = libraw_LoadUnprocessedData(RawProcessor);
717 		}
718 		else if((flags & RAW_PREVIEW) == RAW_PREVIEW) {
719 			// try to get the embedded JPEG
720 			dib = libraw_LoadEmbeddedPreview(RawProcessor, 0);
721 			if(!dib) {
722 				// no JPEG preview: try to load as 8-bit/sample (i.e. RGB 24-bit)
723 				dib = libraw_LoadRawData(RawProcessor, 8);
724 			}
725 		}
726 		else if((flags & RAW_DISPLAY) == RAW_DISPLAY) {
727 			// load raw data as 8-bit/sample (i.e. RGB 24-bit)
728 			dib = libraw_LoadRawData(RawProcessor, 8);
729 		}
730 		else {
731 			// default: load raw data as linear 16-bit/sample (i.e. RGB 48-bit)
732 			dib = libraw_LoadRawData(RawProcessor, 16);
733 		}
734 
735 		// save ICC profile if present
736 		if(dib && (NULL != RawProcessor->imgdata.color.profile)) {
737 			FreeImage_CreateICCProfile(dib, RawProcessor->imgdata.color.profile, RawProcessor->imgdata.color.profile_length);
738 		}
739 
740 		// try to get JPEG embedded Exif metadata
741 		if(dib && !((flags & RAW_PREVIEW) == RAW_PREVIEW)) {
742 			FIBITMAP *metadata_dib = libraw_LoadEmbeddedPreview(RawProcessor, FIF_LOAD_NOPIXELS);
743 			if(metadata_dib) {
744 				FreeImage_CloneMetadata(dib, metadata_dib);
745 				FreeImage_Unload(metadata_dib);
746 			}
747 		}
748 
749 		// clean-up internal memory allocations
750 		RawProcessor->recycle();
751 		delete RawProcessor;
752 
753 		return dib;
754 
755 	} catch(const char *text) {
756 		if(RawProcessor) {
757 			RawProcessor->recycle();
758 			delete RawProcessor;
759 		}
760 		if(dib) {
761 			FreeImage_Unload(dib);
762 		}
763 		FreeImage_OutputMessageProc(s_format_id, text);
764 	}
765 
766 	return NULL;
767 }
768 
769 // ==========================================================
770 //   Init
771 // ==========================================================
772 
773 void DLL_CALLCONV
InitRAW(Plugin * plugin,int format_id)774 InitRAW(Plugin *plugin, int format_id) {
775 	s_format_id = format_id;
776 
777 	plugin->format_proc = Format;
778 	plugin->description_proc = Description;
779 	plugin->extension_proc = Extension;
780 	plugin->regexpr_proc = RegExpr;
781 	plugin->open_proc = NULL;
782 	plugin->close_proc = NULL;
783 	plugin->pagecount_proc = NULL;
784 	plugin->pagecapability_proc = NULL;
785 	plugin->load_proc = Load;
786 	plugin->save_proc = NULL;
787 	plugin->validate_proc = Validate;
788 	plugin->mime_proc = MimeType;
789 	plugin->supports_export_bpp_proc = SupportsExportDepth;
790 	plugin->supports_export_type_proc = SupportsExportType;
791 	plugin->supports_icc_profiles_proc = SupportsICCProfiles;
792 	plugin->supports_no_pixels_proc = SupportsNoPixels;
793 }
794