Example #1
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	FIBITMAP *dib = NULL;
	LibRaw RawProcessor;

	BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;

	try {
		// wrap the input datastream
		LibRaw_freeimage_datastream datastream(io, handle);

		// set decoding parameters
		// the following parameters affect data reading
		// --------------------------------------------

		// (-s [0..N-1]) Select one raw image from input file
		RawProcessor.imgdata.params.shot_select = 0;
		// (-w) Use camera white balance, if possible (otherwise, fallback to auto_wb)
		RawProcessor.imgdata.params.use_camera_wb = 1;
		// (-h) outputs the image in 50% size
		RawProcessor.imgdata.params.half_size = ((flags & RAW_HALFSIZE) == RAW_HALFSIZE) ? 1 : 0;

		// open the datastream
		if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) {
			throw "LibRaw : failed to open input stream (unknown format)";
		}

		if(header_only) {
			// header only mode
			dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, RawProcessor.imgdata.sizes.width, RawProcessor.imgdata.sizes.height);
		}
		else if((flags & RAW_PREVIEW) == RAW_PREVIEW) {
			// try to get the embedded JPEG
			dib = libraw_LoadEmbeddedPreview(RawProcessor, 0);
			if(!dib) {
				// no JPEG preview: try to load as 8-bit/sample (i.e. RGB 24-bit)
				dib = libraw_LoadRawData(RawProcessor, 8);
			}
		} 
		else if((flags & RAW_DISPLAY) == RAW_DISPLAY) {
			// load raw data as 8-bit/sample (i.e. RGB 24-bit)
			dib = libraw_LoadRawData(RawProcessor, 8);
		} 
		else {
			// default: load raw data as linear 16-bit/sample (i.e. RGB 48-bit)
			dib = libraw_LoadRawData(RawProcessor, 16);
		}

		// save ICC profile if present
		if(dib && (NULL != RawProcessor.imgdata.color.profile)) {
			FreeImage_CreateICCProfile(dib, RawProcessor.imgdata.color.profile, RawProcessor.imgdata.color.profile_length);
		}

		// try to get JPEG embedded Exif metadata
		if(dib && !((flags & RAW_PREVIEW) == RAW_PREVIEW)) {
			FIBITMAP *metadata_dib = libraw_LoadEmbeddedPreview(RawProcessor, FIF_LOAD_NOPIXELS);
			if(metadata_dib) {
				FreeImage_CloneMetadata(dib, metadata_dib);
				FreeImage_Unload(metadata_dib);
			}
		}

		// clean-up internal memory allocations
		RawProcessor.recycle();

		return dib;

	} catch(const char *text) {
		if(dib) {
			FreeImage_Unload(dib);
		}
		RawProcessor.recycle();
		FreeImage_OutputMessageProc(s_format_id, text);
	}

	return NULL;
}
Example #2
0
FIBITMAP * DLL_CALLCONV
FreeImage_ConvertToRGB16(FIBITMAP *dib) {
	FIBITMAP *src = NULL;
	FIBITMAP *dst = NULL;

	if(!FreeImage_HasPixels(dib)) return NULL;

	const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib);

	// check for allowed conversions 
	switch(src_type) {
		case FIT_BITMAP:
		{
			// convert to 24-bit if needed
			if((FreeImage_GetBPP(dib) == 24) || (FreeImage_GetBPP(dib) == 32)) {
				src = dib;
			} else {
				src = FreeImage_ConvertTo24Bits(dib);
				if(!src) return NULL;
			}
			break;
		}
		case FIT_UINT16:
			// allow conversion from unsigned 16-bit
			src = dib;
			break;
		case FIT_RGB16:
			// RGB16 type : clone the src
			return FreeImage_Clone(dib);
			break;
		case FIT_RGBA16:
			// allow conversion from 64-bit RGBA (ignore the alpha channel)
			src = dib;
			break;
		default:
			return NULL;
	}

	// allocate dst image

	const unsigned width = FreeImage_GetWidth(src);
	const unsigned height = FreeImage_GetHeight(src);

	dst = FreeImage_AllocateT(FIT_RGB16, width, height);
	if(!dst) {
		if(src != dib) {
			FreeImage_Unload(src);
		}
		return NULL;
	}

	// copy metadata from src to dst
	FreeImage_CloneMetadata(dst, src);

	// convert from src type to RGB16

	switch(src_type) {
		case FIT_BITMAP:
		{
			// Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit)
			const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);

			for(unsigned y = 0; y < height; y++) {
				const BYTE *src_bits = (BYTE*)FreeImage_GetScanLine(src, y);
				FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y);
				for(unsigned x = 0; x < width; x++) {
					dst_bits[x].red   = src_bits[FI_RGBA_RED] << 8;
					dst_bits[x].green = src_bits[FI_RGBA_GREEN] << 8;
					dst_bits[x].blue  = src_bits[FI_RGBA_BLUE] << 8;
					src_bits += bytespp;
				}
			}
		}
		break;

		case FIT_UINT16:
		{
			for(unsigned y = 0; y < height; y++) {
				const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, y);
				FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y);
				for(unsigned x = 0; x < width; x++) {
					// convert by copying greyscale channel to each R, G, B channels
					dst_bits[x].red   = src_bits[x];
					dst_bits[x].green = src_bits[x];
					dst_bits[x].blue  = src_bits[x];
				}
			}
		}
		break;

		case FIT_RGBA16:
		{
			for(unsigned y = 0; y < height; y++) {
				const FIRGBA16 *src_bits = (FIRGBA16*)FreeImage_GetScanLine(src, y);
				FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y);
				for(unsigned x = 0; x < width; x++) {
					// convert and skip alpha channel
					dst_bits[x].red   = src_bits[x].red;
					dst_bits[x].green = src_bits[x].green;
					dst_bits[x].blue  = src_bits[x].blue;
				}
			}
		}
		break;

		default:
			break;
	}

	if(src != dib) {
		FreeImage_Unload(src);
	}

	return dst;
}
Example #3
0
/**
@brief Composite a foreground image against a background color or a background image.

The equation for computing a composited sample value is:<br>
output = alpha * foreground + (1-alpha) * background<br>
where alpha and the input and output sample values are expressed as fractions in the range 0 to 1. 
For colour images, the computation is done separately for R, G, and B samples.

@param fg Foreground image
@param useFileBkg If TRUE and a file background is present, use it as the background color
@param appBkColor If not equal to NULL, and useFileBkg is FALSE, use this color as the background color
@param bg If not equal to NULL and useFileBkg is FALSE and appBkColor is NULL, use this as the background image
@return Returns the composite image if successful, returns NULL otherwise
@see FreeImage_IsTransparent, FreeImage_HasBackgroundColor
*/
FIBITMAP * DLL_CALLCONV
FreeImage_Composite(FIBITMAP *fg, BOOL useFileBkg, RGBQUAD *appBkColor, FIBITMAP *bg) {
	if(!FreeImage_HasPixels(fg)) return NULL;

	int width  = FreeImage_GetWidth(fg);
	int height = FreeImage_GetHeight(fg);
	int bpp    = FreeImage_GetBPP(fg);

	if((bpp != 8) && (bpp != 32))
		return NULL;

	if(bg) {
		int bg_width  = FreeImage_GetWidth(bg);
		int bg_height = FreeImage_GetHeight(bg);
		int bg_bpp    = FreeImage_GetBPP(bg);
		if((bg_width != width) || (bg_height != height) || (bg_bpp != 24))
			return NULL;
	}

	int bytespp = (bpp == 8) ? 1 : 4;

	
	int x, y, c;
	BYTE alpha = 0, not_alpha;
	BYTE index;
	RGBQUAD fgc;	// foreground color
	RGBQUAD bkc;	// background color

	memset(&fgc, 0, sizeof(RGBQUAD));
	memset(&bkc, 0, sizeof(RGBQUAD));

	// allocate the composite image
	FIBITMAP *composite = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
	if(!composite) return NULL;

	// get the palette
	RGBQUAD *pal = FreeImage_GetPalette(fg);

	// retrieve the alpha table from the foreground image
	BOOL bIsTransparent = FreeImage_IsTransparent(fg);
	BYTE *trns = FreeImage_GetTransparencyTable(fg);

	// retrieve the background color from the foreground image
	BOOL bHasBkColor = FALSE;

	if(useFileBkg && FreeImage_HasBackgroundColor(fg)) {
		FreeImage_GetBackgroundColor(fg, &bkc);
		bHasBkColor = TRUE;
	} else {
		// no file background color
		// use application background color ?
		if(appBkColor) {
			memcpy(&bkc, appBkColor, sizeof(RGBQUAD));
			bHasBkColor = TRUE;
		}
		// use background image ?
		else if(bg) {
			bHasBkColor = FALSE;
		}
	}

	for(y = 0; y < height; y++) {
		// foreground
		BYTE *fg_bits = FreeImage_GetScanLine(fg, y);
		// background
		BYTE *bg_bits = FreeImage_GetScanLine(bg, y);
		// composite image
		BYTE *cp_bits = FreeImage_GetScanLine(composite, y);

		for(x = 0; x < width; x++) {

			// foreground color + alpha

			if(bpp == 8) {
				// get the foreground color
				index = fg_bits[0];
				memcpy(&fgc, &pal[index], sizeof(RGBQUAD));
				// get the alpha
				if(bIsTransparent) {
					alpha = trns[index];
				} else {
					alpha = 255;
				}
			}
			else if(bpp == 32) {
				// get the foreground color
				fgc.rgbBlue  = fg_bits[FI_RGBA_BLUE];
				fgc.rgbGreen = fg_bits[FI_RGBA_GREEN];
				fgc.rgbRed   = fg_bits[FI_RGBA_RED];
				// get the alpha
				alpha = fg_bits[FI_RGBA_ALPHA];
			}

			// background color

			if(!bHasBkColor) {
				if(bg) {
					// get the background color from the background image
					bkc.rgbBlue  = bg_bits[FI_RGBA_BLUE];
					bkc.rgbGreen = bg_bits[FI_RGBA_GREEN];
					bkc.rgbRed   = bg_bits[FI_RGBA_RED];
				}
				else {
					// use a checkerboard pattern
					c = (((y & 0x8) == 0) ^ ((x & 0x8) == 0)) * 192;
					c = c ? c : 255;
					bkc.rgbBlue  = (BYTE)c;
					bkc.rgbGreen = (BYTE)c;
					bkc.rgbRed   = (BYTE)c;
				}
			}

			// composition

			if(alpha == 0) {
				// output = background
				cp_bits[FI_RGBA_BLUE] = bkc.rgbBlue;
				cp_bits[FI_RGBA_GREEN] = bkc.rgbGreen;
				cp_bits[FI_RGBA_RED] = bkc.rgbRed;
			}
			else if(alpha == 255) {
				// output = foreground
				cp_bits[FI_RGBA_BLUE] = fgc.rgbBlue;
				cp_bits[FI_RGBA_GREEN] = fgc.rgbGreen;
				cp_bits[FI_RGBA_RED] = fgc.rgbRed;
			}
			else {
				// output = alpha * foreground + (1-alpha) * background
				not_alpha = (BYTE)~alpha;
				cp_bits[FI_RGBA_BLUE] = (BYTE)((alpha * (WORD)fgc.rgbBlue  + not_alpha * (WORD)bkc.rgbBlue) >> 8);
				cp_bits[FI_RGBA_GREEN] = (BYTE)((alpha * (WORD)fgc.rgbGreen + not_alpha * (WORD)bkc.rgbGreen) >> 8);
				cp_bits[FI_RGBA_RED] = (BYTE)((alpha * (WORD)fgc.rgbRed   + not_alpha * (WORD)bkc.rgbRed) >> 8);
			}

			fg_bits += bytespp;
			bg_bits += 3;
			cp_bits += 3;
		}
	}

	// copy metadata from src to dst
	FreeImage_CloneMetadata(composite, fg);
	
	return composite;	
}