PageRenderTime 88ms CodeModel.GetById 34ms app.highlight 49ms RepoModel.GetById 1ms app.codeStats 1ms

/src/FreeImage/Source/FreeImage/PluginRAW.cpp

https://bitbucket.org/cabalistic/ogredeps/
C++ | 542 lines | 367 code | 63 blank | 112 comment | 78 complexity | e24cd14a4c012a281abae53e16a24505 MD5 | raw file
  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
 32static int s_format_id;
 33
 34// ==========================================================
 35// Internal functions
 36// ==========================================================
 37
 38// ----------------------------------------------------------
 39//   FreeImage datastream wrapper
 40// ----------------------------------------------------------
 41
 42class LibRaw_freeimage_datastream : public LibRaw_abstract_datastream {
 43private: 
 44	FreeImageIO *_io;
 45	fi_handle _handle;
 46	long _eof;
 47
 48public:
 49	LibRaw_freeimage_datastream(FreeImageIO *io, fi_handle handle) : _io(io), _handle(handle) {
 50		long start_pos = io->tell_proc(handle);
 51		io->seek_proc(handle, 0, SEEK_END);
 52		_eof = io->tell_proc(handle);
 53		io->seek_proc(handle, start_pos, SEEK_SET);
 54	}
 55	~LibRaw_freeimage_datastream() {
 56	}
 57	virtual void * make_jas_stream() {
 58		return NULL;
 59	}
 60    virtual int valid() { 
 61		return (_io && _handle);
 62	}
 63    virtual int read(void *buffer, size_t size, size_t count) { 
 64		if(substream) return substream->read(buffer, size, count);
 65		return _io->read_proc(buffer, (unsigned)size, (unsigned)count, _handle);
 66	}	
 67    virtual int eof() { 
 68        if(substream) return substream->eof();
 69        return (_io->tell_proc(_handle) >= _eof);
 70    }
 71    virtual int seek(INT64 offset, int origin) { 
 72        if(substream) return substream->seek(offset, origin);
 73		return _io->seek_proc(_handle, (long)offset, origin);
 74	} 
 75    virtual INT64 tell() { 
 76		if(substream) return substream->tell();
 77        return _io->tell_proc(_handle);
 78    }
 79    virtual int get_char() { 
 80		int c = 0;
 81		if(substream) return substream->get_char();
 82		if(!_io->read_proc(&c, 1, 1, _handle)) return -1;
 83		return c;
 84   }
 85	virtual char* gets(char *buffer, int length) { 
 86		if (substream) return substream->gets(buffer, length);
 87		memset(buffer, 0, length);
 88		for(int i = 0; i < length; i++) {
 89			if(!_io->read_proc(&buffer[i], 1, 1, _handle))
 90				return NULL;
 91			if(buffer[i] == 0x0A)
 92				break;
 93		}
 94		return buffer;
 95	}
 96	virtual int scanf_one(const char *fmt, void* val) {
 97		std::string buffer;
 98		char element = 0;
 99		bool bDone = false;
100		if(substream) return substream->scanf_one(fmt,val);				
101		do {
102			if(_io->read_proc(&element, 1, 1, _handle) == 1) {
103				switch(element) {
104					case '0':
105					case '\n':
106					case ' ':
107					case '\t':
108						bDone = true;
109						break;
110					default:
111						break;
112				}
113				buffer.append(&element, 1);
114			} else {
115				return 0;
116			}
117		} while(!bDone);
118
119		return sscanf(buffer.c_str(), fmt, val);
120	}
121};
122
123// ----------------------------------------------------------
124
125/**
126Convert a processed raw data array to a FIBITMAP
127@param image Processed raw image
128@return Returns the converted dib if successfull, returns NULL otherwise
129*/
130static FIBITMAP * 
131libraw_ConvertToDib(libraw_processed_image_t *image) {
132	FIBITMAP *dib = NULL;
133	try {
134		unsigned width = image->width;
135		unsigned height = image->height;
136		unsigned bpp = image->bits;
137		if(bpp == 16) {
138			// allocate output dib
139			dib = FreeImage_AllocateT(FIT_RGB16, width, height);
140			if(!dib) {
141				throw FI_MSG_ERROR_DIB_MEMORY;
142			}
143			// write data
144			WORD *raw_data = (WORD*)image->data;
145			for(unsigned y = 0; y < height; y++) {
146				FIRGB16 *output = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y);
147				for(unsigned x = 0; x < width; x++) {
148					output[x].red   = raw_data[0];
149					output[x].green = raw_data[1];
150					output[x].blue  = raw_data[2];
151					raw_data += 3;
152				}
153			}
154		} else if(bpp == 8) {
155			// allocate output dib
156			dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24);
157			if(!dib) {
158				throw FI_MSG_ERROR_DIB_MEMORY;
159			}
160			// write data
161			BYTE *raw_data = (BYTE*)image->data;
162			for(unsigned y = 0; y < height; y++) {
163				RGBTRIPLE *output = (RGBTRIPLE*)FreeImage_GetScanLine(dib, height - 1 - y);
164				for(unsigned x = 0; x < width; x++) {
165					output[x].rgbtRed   = raw_data[0];
166					output[x].rgbtGreen = raw_data[1];
167					output[x].rgbtBlue  = raw_data[2];
168					raw_data += 3;
169				}
170			}
171		}
172
173	} catch(const char *text) {
174		FreeImage_OutputMessageProc(s_format_id, text);
175	}
176
177	return dib;
178}
179
180/** 
181Get the embedded JPEG preview image from RAW picture with included Exif Data. 
182@param RawProcessor Libraw handle
183@param flags JPEG load flags
184@return Returns the loaded dib if successfull, returns NULL otherwise
185*/
186static FIBITMAP * 
187libraw_LoadEmbeddedPreview(LibRaw& RawProcessor, int flags) {
188	FIBITMAP *dib = NULL;
189	libraw_processed_image_t *thumb_image = NULL;
190	
191	try {
192		// unpack data
193		if(RawProcessor.unpack_thumb() != LIBRAW_SUCCESS) {
194			// run silently "LibRaw : failed to run unpack_thumb"
195			return NULL;
196		}
197
198		// retrieve thumb image
199		int error_code = 0;
200		thumb_image = RawProcessor.dcraw_make_mem_thumb(&error_code);
201		if(thumb_image) {
202			if(thumb_image->type != LIBRAW_IMAGE_BITMAP) {
203				// attach the binary data to a memory stream
204				FIMEMORY *hmem = FreeImage_OpenMemory((BYTE*)thumb_image->data, (DWORD)thumb_image->data_size);
205				// get the file type
206				FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0);
207				if(fif == FIF_JPEG) {
208					// rotate according to Exif orientation
209					flags |= JPEG_EXIFROTATE;
210				}
211				// load an image from the memory stream
212				dib = FreeImage_LoadFromMemory(fif, hmem, flags);
213				// close the stream
214				FreeImage_CloseMemory(hmem);
215			} else {
216				// convert processed data to output dib
217				dib = libraw_ConvertToDib(thumb_image);
218			}
219		} else {
220			throw "LibRaw : failed to run dcraw_make_mem_thumb";
221		}
222
223		// clean-up and return
224		RawProcessor.dcraw_clear_mem(thumb_image);
225
226		return dib;
227
228	} catch(const char *text) {
229		// clean-up and return
230		if(thumb_image) {
231			RawProcessor.dcraw_clear_mem(thumb_image);
232		}
233		if(text != NULL) {
234			FreeImage_OutputMessageProc(s_format_id, text);
235		}
236	}
237
238	return NULL;
239}
240/**
241Load raw data and convert to FIBITMAP
242@param RawProcessor Libraw handle
243@param bitspersample Output bitdepth (8- or 16-bit)
244@return Returns the loaded dib if successfull, returns NULL otherwise
245*/
246static FIBITMAP * 
247libraw_LoadRawData(LibRaw& RawProcessor, int bitspersample) {
248	FIBITMAP *dib = NULL;
249	libraw_processed_image_t *processed_image = NULL;
250
251	try {
252		// set decoding parameters
253		// -----------------------
254		
255		// (-6) 16-bit or 8-bit
256		RawProcessor.imgdata.params.output_bps = bitspersample;
257		// (-g power toe_slope)
258		if(bitspersample == 16) {
259			// set -g 1 1 for linear curve
260			RawProcessor.imgdata.params.gamm[0] = 1;
261			RawProcessor.imgdata.params.gamm[1] = 1;
262		} else if(bitspersample == 8) {
263			// by default settings for rec. BT.709 are used: power 2.222 (i.e. gamm[0]=1/2.222) and slope 4.5
264			RawProcessor.imgdata.params.gamm[0] = 1/2.222;
265			RawProcessor.imgdata.params.gamm[1] = 4.5;
266		}
267		// (-W) Don't use automatic increase of brightness by histogram
268		RawProcessor.imgdata.params.no_auto_bright = 1;
269		// (-a) Use automatic white balance obtained after averaging over the entire image
270		RawProcessor.imgdata.params.use_auto_wb = 1;
271		// (-q 3) Adaptive homogeneity-directed demosaicing algorithm (AHD)
272		RawProcessor.imgdata.params.user_qual = 3;
273
274		// -----------------------
275
276		// unpack data
277		if(RawProcessor.unpack() != LIBRAW_SUCCESS) {
278			throw "LibRaw : failed to unpack data";
279		}
280
281		// process data (... most consuming task ...)
282		if(RawProcessor.dcraw_process() != LIBRAW_SUCCESS) {
283			throw "LibRaw : failed to process data";
284		}
285
286		// retrieve processed image
287		int error_code = 0;
288		processed_image = RawProcessor.dcraw_make_mem_image(&error_code);
289		if(processed_image) {
290			// type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check
291			if(processed_image->type != LIBRAW_IMAGE_BITMAP) {
292				throw "invalid image type";
293			}
294			// only 3-color images supported...
295			if(processed_image->colors != 3) {
296				throw "only 3-color images supported";
297			}
298		} else {
299			throw "LibRaw : failed to run dcraw_make_mem_image";
300		}
301
302		// convert processed data to output dib
303		dib = libraw_ConvertToDib(processed_image);
304	
305		// clean-up and return
306		RawProcessor.dcraw_clear_mem(processed_image);
307
308		return dib;
309
310	} catch(const char *text) {
311		// clean-up and return
312		if(processed_image) {
313			RawProcessor.dcraw_clear_mem(processed_image);
314		}
315		FreeImage_OutputMessageProc(s_format_id, text);
316	}
317
318	return NULL;
319}
320
321// ==========================================================
322// Plugin Implementation
323// ==========================================================
324
325static const char * DLL_CALLCONV
326Format() {
327	return "RAW";
328}
329
330static const char * DLL_CALLCONV
331Description() {
332	return "RAW camera image";
333}
334
335static const char * DLL_CALLCONV
336Extension() {
337	/**
338	Below are known RAW file extensions that you can check using FreeImage_GetFIFFromFormat. 
339	If a file extension is not listed, that doesn't mean that you cannot load it. 
340	Using FreeImage_GetFileType is the best way to know if a RAW file format is supported. 
341	*/
342	static const char *raw_extensions = 
343		"3fr,"   // Hasselblad Digital Camera Raw Image Format.
344		"arw,"   // Sony Digital Camera Raw Image Format for Alpha devices.
345		"bay,"   // Casio Digital Camera Raw File Format.
346		"bmq,"   // NuCore Raw Image File.
347		"cap,"   // Phase One Digital Camera Raw Image Format.
348		"cine,"  // Phantom Software Raw Image File.
349		"cr2,"   // Canon Digital Camera RAW Image Format version 2.0. These images are based on the TIFF image standard.
350		"crw,"   // Canon Digital Camera RAW Image Format version 1.0. 
351		"cs1,"   // Sinar Capture Shop Raw Image File.
352		"dc2,"   // Kodak DC25 Digital Camera File.
353		"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.
354		"drf,"   // Kodak Digital Camera Raw Image Format.
355		"dsc,"   // Kodak Digital Camera Raw Image Format.
356		"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. 
357		"erf,"   // Epson Digital Camera Raw Image Format.
358		"fff,"   // Imacon Digital Camera Raw Image Format.
359		"ia,"    // Sinar Raw Image File.
360		"iiq,"   // Phase One Digital Camera Raw Image Format.
361		"k25,"   // Kodak DC25 Digital Camera Raw Image Format.
362		"kc2,"   // Kodak DCS200 Digital Camera Raw Image Format.
363		"kdc,"   // Kodak Digital Camera Raw Image Format.
364		"mdc,"   // Minolta RD175 Digital Camera Raw Image Format.
365		"mef,"   // Mamiya Digital Camera Raw Image Format.
366		"mos,"   // Leaf Raw Image File.
367		"mrw,"   // Minolta Dimage Digital Camera Raw Image Format.
368		"nef,"   // Nikon Digital Camera Raw Image Format.
369		"nrw,"   // Nikon Digital Camera Raw Image Format.
370		"orf,"   // Olympus Digital Camera Raw Image Format.
371		"pef,"   // Pentax Digital Camera Raw Image Format.
372		"ptx,"   // Pentax Digital Camera Raw Image Format.
373		"pxn,"   // Logitech Digital Camera Raw Image Format.
374		"qtk,"   // Apple Quicktake 100/150 Digital Camera Raw Image Format.
375		"raf,"   // Fuji Digital Camera Raw Image Format.
376		"raw,"   // Panasonic Digital Camera Image Format.
377		"rdc,"   // Digital Foto Maker Raw Image File.
378		"rw2,"   // Panasonic LX3 Digital Camera Raw Image Format.
379		"rwl,"	 // Leica Camera Raw Image Format.
380		"rwz,"   // Rawzor Digital Camera Raw Image Format.
381		"sr2,"   // Sony Digital Camera Raw Image Format.
382		"srf,"   // Sony Digital Camera Raw Image Format for DSC-F828 8 megapixel digital camera or Sony DSC-R1.
383		"srw,"   // Samsung Raw Image Format.
384		"sti";   // Sinar Capture Shop Raw Image File.
385//		"x3f"   // Sigma Digital Camera Raw Image Format for devices based on Foveon X3 direct image sensor.
386	return raw_extensions;
387}
388
389static const char * DLL_CALLCONV
390RegExpr() {
391	return NULL;
392}
393
394static const char * DLL_CALLCONV
395MimeType() {
396	return "image/x-dcraw";
397}
398
399static BOOL DLL_CALLCONV
400Validate(FreeImageIO *io, fi_handle handle) {
401	LibRaw RawProcessor;
402	BOOL bSuccess = TRUE;
403	
404	// wrap the input datastream
405	LibRaw_freeimage_datastream datastream(io, handle);
406
407	// open the datastream
408	if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) {
409		bSuccess = FALSE;	// LibRaw : failed to open input stream (unknown format)
410	}
411
412	// clean-up internal memory allocations
413	RawProcessor.recycle();
414
415	return bSuccess;
416}
417
418static BOOL DLL_CALLCONV
419SupportsExportDepth(int depth) {
420	return FALSE;
421}
422
423static BOOL DLL_CALLCONV 
424SupportsExportType(FREE_IMAGE_TYPE type) {
425	return FALSE;
426}
427
428static BOOL DLL_CALLCONV
429SupportsICCProfiles() {
430	return TRUE;
431}
432
433static BOOL DLL_CALLCONV
434SupportsNoPixels() {
435	return TRUE;
436}
437
438// ----------------------------------------------------------
439
440static FIBITMAP * DLL_CALLCONV
441Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
442	FIBITMAP *dib = NULL;
443	LibRaw RawProcessor;
444
445	BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
446
447	try {
448		// wrap the input datastream
449		LibRaw_freeimage_datastream datastream(io, handle);
450
451		// set decoding parameters
452		// the following parameters affect data reading
453		// --------------------------------------------
454
455		// (-s [0..N-1]) Select one raw image from input file
456		RawProcessor.imgdata.params.shot_select = 0;
457		// (-w) Use camera white balance, if possible (otherwise, fallback to auto_wb)
458		RawProcessor.imgdata.params.use_camera_wb = 1;
459		// (-h) outputs the image in 50% size
460		RawProcessor.imgdata.params.half_size = ((flags & RAW_HALFSIZE) == RAW_HALFSIZE) ? 1 : 0;
461
462		// open the datastream
463		if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) {
464			throw "LibRaw : failed to open input stream (unknown format)";
465		}
466
467		if(header_only) {
468			// header only mode
469			dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, RawProcessor.imgdata.sizes.width, RawProcessor.imgdata.sizes.height);
470		}
471		else if((flags & RAW_PREVIEW) == RAW_PREVIEW) {
472			// try to get the embedded JPEG
473			dib = libraw_LoadEmbeddedPreview(RawProcessor, 0);
474			if(!dib) {
475				// no JPEG preview: try to load as 8-bit/sample (i.e. RGB 24-bit)
476				dib = libraw_LoadRawData(RawProcessor, 8);
477			}
478		} 
479		else if((flags & RAW_DISPLAY) == RAW_DISPLAY) {
480			// load raw data as 8-bit/sample (i.e. RGB 24-bit)
481			dib = libraw_LoadRawData(RawProcessor, 8);
482		} 
483		else {
484			// default: load raw data as linear 16-bit/sample (i.e. RGB 48-bit)
485			dib = libraw_LoadRawData(RawProcessor, 16);
486		}
487
488		// save ICC profile if present
489		if(dib && (NULL != RawProcessor.imgdata.color.profile)) {
490			FreeImage_CreateICCProfile(dib, RawProcessor.imgdata.color.profile, RawProcessor.imgdata.color.profile_length);
491		}
492
493		// try to get JPEG embedded Exif metadata
494		if(dib && !((flags & RAW_PREVIEW) == RAW_PREVIEW)) {
495			FIBITMAP *metadata_dib = libraw_LoadEmbeddedPreview(RawProcessor, FIF_LOAD_NOPIXELS);
496			if(metadata_dib) {
497				FreeImage_CloneMetadata(dib, metadata_dib);
498				FreeImage_Unload(metadata_dib);
499			}
500		}
501
502		// clean-up internal memory allocations
503		RawProcessor.recycle();
504
505		return dib;
506
507	} catch(const char *text) {
508		if(dib) {
509			FreeImage_Unload(dib);
510		}
511		RawProcessor.recycle();
512		FreeImage_OutputMessageProc(s_format_id, text);
513	}
514
515	return NULL;
516}
517
518// ==========================================================
519//   Init
520// ==========================================================
521
522void DLL_CALLCONV
523InitRAW(Plugin *plugin, int format_id) {
524	s_format_id = format_id;
525
526	plugin->format_proc = Format;
527	plugin->description_proc = Description;
528	plugin->extension_proc = Extension;
529	plugin->regexpr_proc = RegExpr;
530	plugin->open_proc = NULL;
531	plugin->close_proc = NULL;
532	plugin->pagecount_proc = NULL;
533	plugin->pagecapability_proc = NULL;
534	plugin->load_proc = Load;
535	plugin->save_proc = NULL;
536	plugin->validate_proc = Validate;
537	plugin->mime_proc = MimeType;
538	plugin->supports_export_bpp_proc = SupportsExportDepth;
539	plugin->supports_export_type_proc = SupportsExportType;
540	plugin->supports_icc_profiles_proc = SupportsICCProfiles;
541	plugin->supports_no_pixels_proc = SupportsNoPixels;
542}