Ejemplo n.º 1
0
/** @brief Inverts each pixel data.

@param src Input image to be processed.
@return Returns TRUE if successful, FALSE otherwise.
*/
BOOL DLL_CALLCONV 
FreeImage_Invert(FIBITMAP *src) {
	unsigned i, x, y, k;
	BYTE *bits;

	if (!src) return FALSE;

	int bpp = FreeImage_GetBPP(src);
	
	switch(bpp) {
        case 1 :
		case 4 :
		case 8 :
		{
			// if the dib has a colormap, just invert it
			// else, keep the linear grayscale

			if (FreeImage_GetColorType(src) == FIC_PALETTE) {
				RGBQUAD *pal = FreeImage_GetPalette(src);

				for(i = 0; i < FreeImage_GetColorsUsed(src); i++) {
					pal[i].rgbRed	= 255 - pal[i].rgbRed;
					pal[i].rgbGreen = 255 - pal[i].rgbGreen;
					pal[i].rgbBlue	= 255 - pal[i].rgbBlue;
				}
			} else {
				for(y = 0; y < FreeImage_GetHeight(src); y++) {
					bits = FreeImage_GetScanLine(src, y);

					for (x = 0; x < FreeImage_GetLine(src); x++) {
						bits[x] = ~bits[x];
					}
				}
			}

			break;
		}		

		case 24 :
		case 32 :
		{
			unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);

			for(y = 0; y < FreeImage_GetHeight(src); y++) {
				bits =  FreeImage_GetScanLine(src, y);
				for(x = 0; x < FreeImage_GetWidth(src); x++) {
					for(k = 0; k < bytespp; k++) {
						bits[k] = ~bits[k];
					}
					bits += bytespp;
				}
			}

			break;
		}

	}
	return TRUE;
}
Ejemplo n.º 2
0
  void write_image(const string& file, const SampleBuffer& buffer)
  {
    const float samples = static_cast<float>(buffer.samples());
    FIBITMAP* dib = FreeImage_Allocate(buffer.width(), buffer.height(),
        32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);

    const unsigned int BYTESPP =
      FreeImage_GetLine(dib) / FreeImage_GetWidth(dib);
    for (unsigned int y = 0; y < FreeImage_GetHeight(dib); ++y) {
      BYTE* bits = FreeImage_GetScanLine(dib, y);

      for (unsigned int x = 0; x < FreeImage_GetWidth(dib); ++x) {
        vec3 c = gamma_correct(buffer.get(x, y) / samples) * 255.0f;
        bits[FI_RGBA_RED]   = static_cast<BYTE>(c.r);
        bits[FI_RGBA_GREEN] = static_cast<BYTE>(c.g);
        bits[FI_RGBA_BLUE]  = static_cast<BYTE>(c.b);
        bits[FI_RGBA_ALPHA] = 255;

        bits += BYTESPP;
      }
    }

    if (!FreeImage_Save(FIF_PNG, dib, file.c_str(), 0)) {
      string err = "Failed to save screenshot to file '";
      err += file;
      err += '\'';
      throw err;
    }

    FreeImage_Unload(dib);
  }
Ejemplo n.º 3
0
void ImageLoader::
compatible()
{
	// BITMAP数据是从下往上的, 需要翻转
	FreeImage_FlipVertical(mDIB);

	// FreeImage是BGR顺序, 与NVTT要求的一致, 而PVRT需要RGB顺序, 两者都需要32bits数据
	if (config.imageCompressionType != CT_DXTC)
	{
		// 将BGR改为RGB, 交换R channel和B channel
		const unsigned bytesperpixel = FreeImage_GetBPP(mDIB) / 8;
		const unsigned height = FreeImage_GetHeight(mDIB);
		const unsigned pitch = FreeImage_GetPitch(mDIB);
		const unsigned lineSize = FreeImage_GetLine(mDIB);

		BYTE* line = FreeImage_GetBits(mDIB);
		for (unsigned y = 0; y < height; ++y, line += pitch) {
			for (BYTE* pixel = line; pixel < line + lineSize; pixel += bytesperpixel) {
				INPLACESWAP(pixel[0], pixel[2]);
			}
		}
	}

	if (FreeImage_GetBPP(mDIB) != 32)
	{
		FIBITMAP* convertDIB = FreeImage_ConvertTo32Bits(mDIB);
		FreeImage_Unload(mDIB);
		mDIB = convertDIB;
	}
}
Ejemplo n.º 4
0
unsigned DLL_CALLCONV
FreeImage_GetPitch(FIBITMAP *dib) {
	if(dib) {
		FREEIMAGEHEADER *fih = (FREEIMAGEHEADER *)dib->data;
		return fih->external_bits ? fih->external_pitch : (FreeImage_GetLine(dib) + 3 & ~3);
	}
	return 0;
}
Ejemplo n.º 5
0
// Takes an image from the frame buffer and compresses it
int writeFrame(FIMEMORY *fiBuffer, FIBITMAP *fiImage, unsigned char imageType) {
	/*
	char msg[1024];
	sprintf_s(msg, 1024, "imageType: %i", imageType);
	MessageBox(NULL,msg,"ADES DEBUG", MB_OK);
	*/
	imageType = 2;
	int errStatus = 1;
	u_short imageWidth, imageHeight;

	unsigned width, height, pitch, line;
	BYTE *bits;

	// Package image using correct compression
	switch(imageType) {
	case 0: // Send a raw frame
		// Get image characteristics
		width = FreeImage_GetWidth(fiImage);
		height = FreeImage_GetHeight(fiImage);
		pitch = FreeImage_GetPitch(fiImage);
		line = FreeImage_GetLine(fiImage);

		// Write out width and height
		errStatus = FreeImage_SeekMemory(fiBuffer, 0, SEEK_SET);
		if (errStatus != 1) break;

		imageWidth = htons(width);
		errStatus = FreeImage_WriteMemory( &imageWidth, 2, 1, fiBuffer );
		if (errStatus != 1) break;
		
		imageHeight = htons(height);
		errStatus = FreeImage_WriteMemory( &imageHeight, 2, 1, fiBuffer );
		if (errStatus != 1) break;

		// Write out image (convert the bitmap to raw bits, top-left pixel first)
		bits = (BYTE*)malloc(height * pitch);
		FreeImage_ConvertToRawBits(bits, fiImage, pitch, 24, 
			FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, TRUE);
		errStatus = FreeImage_WriteMemory( bits, height*pitch*sizeof(BYTE), 1, fiBuffer );
		free(bits);
		if (errStatus != 1) break;
		
		break;
	default: // Send a jpg frame
		errStatus = FreeImage_SeekMemory(fiBuffer, 0, SEEK_SET);
		if (errStatus != 1) break;

		errStatus = FreeImage_SaveToMemory(FIF_JPEG, fiImage, fiBuffer, convertToJpegFlag(imageType));
		if (errStatus != 1) break;
		break;
	}
	
	// Clean up and exit
	return errStatus;
}
int main (int argc, char ** argv)
{
	if (argc != 2){
		printf("you need to give me the number of frames to captures\n");
		exit(-1);
	}
	int num_frames = atoi(argv[1]);
	initialize_pru();
	start_pru();
	FILE * image_data = fopen("/media/usb/image.data", "w");
	if (image_data == NULL){
		fprintf(stderr, "Failed to open image output file");
		exit(-1);
	}

	const char  *version = FreeImage_GetVersion();
	printf("Freeimage version %s\n", version);

	FIBITMAP* dib = FreeImage_Allocate(320, 203, 16, 0xF800, 0x07E0,0x001F); // allocate 320x203 RGB565 bitmap

	int bytespp = FreeImage_GetLine(dib)/FreeImage_GetWidth(dib);

	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);

	if (image_type == FIT_BITMAP){
		printf("1\n");
	}

	printf("%d %d\n", FreeImage_GetHeight(dib), FreeImage_GetWidth(dib));

	BYTE * bits = FreeImage_GetBits(dib);
	FILE * fp = fopen("image.data", "rb");
	char filename[] = "/root/1314-BeagleBone-Quadcopter/code/ControlTower/ramfs/latest_image.bmp";
	int i = 0;

	for (i = 0; i < num_frames; i++){
		while(i==pruDataMem_int[100]){usleep(100000);}
		int buffer = pruDataMem_int[1];
		printf("%d buffer=%d\n", pruDataMem_int[100], buffer);
		if (i%10==0){
			memcpy(bits, pru1_ddr+buffer*320*240*2, 320*203*2);
			FreeImage_Save(FIF_BMP, dib, filename,0);
		}
	}
	uninitialize_pru();
	fflush(image_data);
	printf("%d\n", ((volatile uint8_t *)pru1_ddr)[0]);
	fclose(image_data);

	prussdrv_pru_disable (PRU_NUM);
	prussdrv_exit ();

	return(0);
}
Ejemplo n.º 7
0
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
	if(!dib || !handle) return FALSE;

	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
	if((image_type != FIT_RGBF) && (image_type != FIT_FLOAT)) {
		return FALSE;
	}

	unsigned width  = FreeImage_GetWidth(dib);
	unsigned height = FreeImage_GetHeight(dib);
	unsigned lineWidth = FreeImage_GetLine(dib);
	
	// save image as Little Endian
	const float scalefactor = -1.0F;

	char buffer[PFM_MAXLINE];	// temporary buffer whose size should be enough for what we need

	// Find the appropriate magic number for this file type

	char magic = 0;

	switch(image_type) {
		case FIT_RGBF:
			magic = 'F';	// RGBF
			break;	
		case FIT_FLOAT:
			magic = 'f';	// float greyscale
			break;
		default:
			return FALSE;
	}

	// Write the header info

	sprintf(buffer, "P%c\n%d %d\n%f\n", magic, width, height, scalefactor);
	io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);

	// Write the image data
	for (unsigned y = 0; y < height; y++) {	
		BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
		io->write_proc(bits, 1, lineWidth, handle);
	}

	return TRUE;
}
Ejemplo n.º 8
0
/** @brief Fills an image with the specified color.

 This function sets all pixels of an image to the color provided through the color
 parameter. Since this should work for all image types supported by FreeImage, the
 pointer color must point to a memory location, which is at least as large as the
 image's color value, if this size is greater than 4 bytes. As the color is specified
 by an RGBQUAD structure for all images of type FIT_BITMAP (including all palletized
 images), the smallest possible size of this memory is the size of the RGBQUAD structure,
 which uses 4 bytes.

 So, color must point to a double, if the image to be filled is of type FIT_DOUBLE and
 point to a RGBF structure if the image is of type FIT_RGBF and so on.

 However, the fill color is always specified through a RGBQUAD structure for all images
 of type FIT_BITMAP. So, for 32- and 24-bit images, the red, green and blue members of
 the RGBQUAD structure are directly used for the image's red, green and blue channel
 respectively. Although alpha transparent RGBQUAD colors are supported, the alpha channel
 of a 32-bit image never gets modified by this function. A fill color with an alpha value
 smaller than 255 gets blended with the image's actual background color, which is determined
 from the image's bottom-left pixel. So, currently using alpha enabled colors, assumes the
 image to be unicolor before the fill operation. However, the RGBQUAD's rgbReserved member is
 only taken into account, if option FI_COLOR_IS_RGBA_COLOR has been specified.

 For 16-bit images, the red-, green- and blue components of the specified color are
 transparently translated into either the 16-bit 555 or 565 representation. This depends
 on the image's actual red- green- and blue masks.

 Special attention must be payed for palletized images. Generally, the RGB color specified
 is looked up in the image's palette. The found palette index is then used to fill the image.
 There are some option flags, that affect this lookup process:

 no option specified       (0x00)   Uses the color, that is nearest to the specified color.
                                    This is the default behavior and should always find a
                                    color in the palette. However, the visual result may
                                    far from what was expected and mainly depends on the
                                    image's palette.

 FI_COLOR_FIND_EQUAL_COLOR (0x02)	Searches the image's palette for the specified color
                                    but only uses the returned palette index, if the specified
                                    color exactly matches the palette entry. Of course,
                                    depending on the image's actual palette entries, this
                                    operation may fail. In this case, the function falls back
                                    to option FI_COLOR_ALPHA_IS_INDEX and uses the RGBQUAD's
                                    rgbReserved member (or its low nibble for 4-bit images
                                    or its least significant bit (LSB) for 1-bit images) as
                                    the palette index used for the fill operation.

 FI_COLOR_ALPHA_IS_INDEX   (0x04)   Does not perform any color lookup from the palette, but
                                    uses the RGBQUAD's alpha channel member rgbReserved as
                                    the palette index to be used for the fill operation.
                                    However, for 4-bit images, only the low nibble of the
                                    rgbReserved member are used and for 1-bit images, only
                                    the least significant bit (LSB) is used.

 This function fails if any of dib and color is NULL.

 @param dib The image to be filled.
 @param color A pointer to the color value to be used for filling the image. The
 memory pointed to by this pointer is always assumed to be at least as large as the
 image's color value, but never smaller than the size of an RGBQUAD structure.
 @param options Options that affect the color search process for palletized images.
 @return Returns TRUE on success, FALSE otherwise. This function fails if any of
 dib and color is NULL.
 */
BOOL DLL_CALLCONV
FreeImage_FillBackground(FIBITMAP *dib, const void *color, int options) {

	if (!FreeImage_HasPixels(dib)) {
		return FALSE;
	}
	
	if (!color) {
		return FALSE;
	}

	// handle FIT_BITMAP images with FreeImage_FillBackground()
	if (FreeImage_GetImageType(dib) == FIT_BITMAP) {
		return FillBackgroundBitmap(dib, (RGBQUAD *)color, options);
	}
	
	// first, construct the first scanline (bottom line)
	unsigned bytespp = (FreeImage_GetBPP(dib) / 8);
	BYTE *src_bits = FreeImage_GetScanLine(dib, 0);
	BYTE *dst_bits = src_bits;
	for (unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
		memcpy(dst_bits, color, bytespp);
		dst_bits += bytespp;
	}

	// then, copy the first scanline into all following scanlines
	unsigned height = FreeImage_GetHeight(dib);
	unsigned pitch = FreeImage_GetPitch(dib);
	unsigned bytes = FreeImage_GetLine(dib);
	dst_bits = src_bits + pitch;
	for (unsigned y = 1; y < height; y++) {
		memcpy(dst_bits, src_bits, bytes);
		dst_bits += pitch;
	}
	return TRUE;
}
FIBITMAP* DLL_CALLCONV 
FIA_ColourConvertBGRtoRGB (FIBITMAP * src)
{
    FIBITMAP *dst = NULL;
	int x, y, bytespp;

    if (!src)
        return NULL;
	
	if (FIA_IsGreyScale(src)==1)
		return NULL;

	dst = FreeImage_Clone(src);

	// Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
	bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
 
	for(y = 0; y < FreeImage_GetHeight(src); y++) {
		BYTE *src_bits = FreeImage_GetScanLine(src, y);
		BYTE *dst_bits = FreeImage_GetScanLine(dst, y);
		
		for(x = 0; x < FreeImage_GetWidth(src); x++) {
			// reverse colour bytes
			dst_bits[FI_RGBA_RED]   = src_bits[FI_RGBA_BLUE];
			dst_bits[FI_RGBA_GREEN] = src_bits[FI_RGBA_GREEN];
			dst_bits[FI_RGBA_BLUE]  = src_bits[FI_RGBA_RED];
			dst_bits[FI_RGBA_ALPHA] = 0;

			// jump to next pixel
			src_bits += bytespp;
			dst_bits += bytespp;
		 }
	}

    return dst;
}
Ejemplo n.º 10
0
/** @brief Inverts each pixel data.

@param src Input image to be processed.
@return Returns TRUE if successful, FALSE otherwise.
*/
BOOL DLL_CALLCONV 
FreeImage_Invert(FIBITMAP *src) {

	if (!FreeImage_HasPixels(src)) return FALSE;
	
	unsigned i, x, y, k;
	
	const unsigned width = FreeImage_GetWidth(src);
	const unsigned height = FreeImage_GetHeight(src);
	const unsigned bpp = FreeImage_GetBPP(src);

	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src);

	if(image_type == FIT_BITMAP) {
		switch(bpp) {
			case 1 :
			case 4 :
			case 8 :
			{
				// if the dib has a colormap, just invert it
				// else, keep the linear grayscale

				if (FreeImage_GetColorType(src) == FIC_PALETTE) {
					RGBQUAD *pal = FreeImage_GetPalette(src);

					for(i = 0; i < FreeImage_GetColorsUsed(src); i++) {
						pal[i].rgbRed	= 255 - pal[i].rgbRed;
						pal[i].rgbGreen = 255 - pal[i].rgbGreen;
						pal[i].rgbBlue	= 255 - pal[i].rgbBlue;
					}
				} else {
					for(y = 0; y < height; y++) {
						BYTE *bits = FreeImage_GetScanLine(src, y);

						for (x = 0; x < FreeImage_GetLine(src); x++) {
							bits[x] = ~bits[x];
						}
					}
				}

				break;
			}		

			case 24 :
			case 32 :
			{
				// Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
				const unsigned bytespp = FreeImage_GetLine(src) / width;

				for(y = 0; y < height; y++) {
					BYTE *bits = FreeImage_GetScanLine(src, y);
					for(x = 0; x < width; x++) {
						for(k = 0; k < bytespp; k++) {
							bits[k] = ~bits[k];
						}
						bits += bytespp;
					}
				}

				break;
			}
			default:
				return FALSE;
		}
	}
	else if((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) {
		// Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit)
		const unsigned wordspp = (FreeImage_GetLine(src) / width) / sizeof(WORD);

		for(y = 0; y < height; y++) {
			WORD *bits = (WORD*)FreeImage_GetScanLine(src, y);
			for(x = 0; x < width; x++) {
				for(k = 0; k < wordspp; k++) {
					bits[k] = ~bits[k];
				}
				bits += wordspp;
			}
		}
	}
	else {
		// anything else ... 
		return FALSE;
	}
		
	return TRUE;
}
Ejemplo n.º 11
0
FIBITMAP * DLL_CALLCONV
FreeImage_Clone(FIBITMAP *dib) {
	if(!dib) {
		return NULL;
	}

	FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib);
	unsigned width	= FreeImage_GetWidth(dib);
	unsigned height	= FreeImage_GetHeight(dib);
	unsigned bpp	= FreeImage_GetBPP(dib);

	const BYTE *ext_bits = ((FREEIMAGEHEADER *)dib->data)->external_bits;
	
	// check for pixel availability ...
	BOOL header_only = FreeImage_HasPixels(dib) ? FALSE : TRUE;

	// check whether this image has masks defined ...
	BOOL need_masks = (bpp == 16 && type == FIT_BITMAP) ? TRUE : FALSE;

	// allocate a new dib
	FIBITMAP *new_dib = FreeImage_AllocateHeaderT(header_only, type, width, height, bpp,
			FreeImage_GetRedMask(dib), FreeImage_GetGreenMask(dib), FreeImage_GetBlueMask(dib));

	if (new_dib) {
		// save ICC profile links
		FIICCPROFILE *src_iccProfile = FreeImage_GetICCProfile(dib);
		FIICCPROFILE *dst_iccProfile = FreeImage_GetICCProfile(new_dib);

		// save metadata links
		METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
		METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata;

		// calculate the size of the src image
		// align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary
		// palette is aligned on a 16 bytes boundary
		// pixels are aligned on a 16 bytes boundary
		
		// when using a user provided pixel buffer, force a 'header only' calculation		

		size_t dib_size = FreeImage_GetInternalImageSize(header_only || ext_bits, width, height, bpp, need_masks);

		// copy the bitmap + internal pointers (remember to restore new_dib internal pointers later)
		memcpy(new_dib->data, dib->data, dib_size);

		// reset ICC profile link for new_dib
		memset(dst_iccProfile, 0, sizeof(FIICCPROFILE));

		// restore metadata link for new_dib
		((FREEIMAGEHEADER *)new_dib->data)->metadata = dst_metadata;

		// reset thumbnail link for new_dib
		((FREEIMAGEHEADER *)new_dib->data)->thumbnail = NULL;

		// copy possible ICC profile
		FreeImage_CreateICCProfile(new_dib, src_iccProfile->data, src_iccProfile->size);
		dst_iccProfile->flags = src_iccProfile->flags;

		// copy metadata models
		for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) {
			int model = (*i).first;
			TAGMAP *src_tagmap = (*i).second;

			if(src_tagmap) {
				// create a metadata model
				TAGMAP *dst_tagmap = new(std::nothrow) TAGMAP();

				if(dst_tagmap) {
					// fill the model
					for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) {
						std::string dst_key = (*j).first;
						FITAG *dst_tag = FreeImage_CloneTag( (*j).second );

						// assign key and tag value
						(*dst_tagmap)[dst_key] = dst_tag;
					}

					// assign model and tagmap
					(*dst_metadata)[model] = dst_tagmap;
				}
			}
		}

		// copy the thumbnail
		FreeImage_SetThumbnail(new_dib, FreeImage_GetThumbnail(dib));

		// copy user provided pixel buffer (if any)
		if(ext_bits) {
			const unsigned pitch = FreeImage_GetPitch(dib);
			const unsigned linesize = FreeImage_GetLine(dib);
			for(unsigned y = 0; y < height; y++) {
				memcpy(FreeImage_GetScanLine(new_dib, y), ext_bits, linesize);
				ext_bits += pitch;
			}
		}

		return new_dib;
	}

	return NULL;
}
Ejemplo n.º 12
0
/** @brief Fills a FIT_BITMAP image with the specified color.

 This function does the dirty work for FreeImage_FillBackground for FIT_BITMAP
 images.
 @param dib The image to be filled.
 @param color The color, the specified image should be filled with.
 @param options Options that affect the color search process for palletized images.
 @return Returns TRUE on success, FALSE otherwise. This function fails if any of
 the dib and color is NULL or the provided image is not a FIT_BITMAP image.
 */
static BOOL
FillBackgroundBitmap(FIBITMAP *dib, const RGBQUAD *color, int options) {

	if ((!dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
		return FALSE;;
	}
	
	if (!color) {
		return FALSE;
	}
	
	const RGBQUAD *color_intl = color;
	unsigned bpp = FreeImage_GetBPP(dib);
	unsigned width = FreeImage_GetWidth(dib);
	unsigned height = FreeImage_GetHeight(dib);
	
	FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
	
	// get a pointer to the first scanline (bottom line)
	BYTE *src_bits = FreeImage_GetScanLine(dib, 0);
	BYTE *dst_bits = src_bits;	
	
	BOOL supports_alpha = ((bpp >= 24) || ((bpp == 8) && (color_type != FIC_PALETTE)));
	
	// Check for RGBA case if bitmap supports alpha 
	// blending (8-bit greyscale, 24- or 32-bit images)
	if (supports_alpha && (options & FI_COLOR_IS_RGBA_COLOR)) {
		
		if (color->rgbReserved == 0) {
			// the fill color is fully transparent; we are done
			return TRUE;
		}
		
		// Only if the fill color is NOT fully opaque, draw it with
		// the (much) slower FreeImage_DrawLine function and return.
		// Since we do not have the FreeImage_DrawLine function in this
		// release, just assume to have an unicolor background and fill
		// all with an 'alpha-blended' color.
		if (color->rgbReserved < 255) {
							
			// If we will draw on an unicolor background, it's
			// faster to draw opaque with an alpha blended color.
			// So, first get the color from the first pixel in the
			// image (bottom-left pixel).
			RGBQUAD bgcolor;
			if (bpp == 8) {
				bgcolor = FreeImage_GetPalette(dib)[*src_bits];
			} else {	
				bgcolor.rgbBlue = src_bits[FI_RGBA_BLUE];
				bgcolor.rgbGreen = src_bits[FI_RGBA_GREEN];
				bgcolor.rgbRed = src_bits[FI_RGBA_RED];
				bgcolor.rgbReserved = 0xFF;
			}
			RGBQUAD blend;
			GetAlphaBlendedColor(&bgcolor, color_intl, &blend);
			color_intl = &blend;
		}
	}
	
	int index = (bpp <= 8) ? GetPaletteIndex(dib, color_intl, options, &color_type) : 0;
	if (index == -1) {
		// No palette index found for a palletized
		// image. This should never happen...
		return FALSE;
	}
	
	// first, build the first scanline (line 0)
	switch (bpp) {
		case 1: {
			unsigned bytes = (width / 8);
			memset(dst_bits, ((index == 1) ? 0xFF : 0x00), bytes);
			//int n = width % 8;
			int n = width & 7;
			if (n) {
				if (index == 1) {
					// set n leftmost bits
					dst_bits[bytes] |= (0xFF << (8 - n));
				} else {
					// clear n leftmost bits
					dst_bits[bytes] &= (0xFF >> n);
				}
			}
			break;
		}
		case 4: {
			unsigned bytes = (width / 2);
			memset(dst_bits, (index | (index << 4)), bytes);
			//if (bytes % 2) {
			if (bytes & 1) {
				dst_bits[bytes] &= 0x0F;
				dst_bits[bytes] |= (index << 4);
			}
			break;
		}
		case 8: {
			memset(dst_bits, index, FreeImage_GetLine(dib));
			break;
		}
		case 16: {
			WORD wcolor = RGBQUAD_TO_WORD(dib, color_intl);
			for (unsigned x = 0; x < width; x++) {
				((WORD *)dst_bits)[x] = wcolor;
			}
			break;
		}
		case 24: {
			RGBTRIPLE rgbt = *((RGBTRIPLE *)color_intl);
			for (unsigned x = 0; x < width; x++) {
				((RGBTRIPLE *)dst_bits)[x] = rgbt;
			}
			break;
		}
		case 32: {
			RGBQUAD rgbq;
			rgbq.rgbBlue = ((RGBTRIPLE *)color_intl)->rgbtBlue;
			rgbq.rgbGreen = ((RGBTRIPLE *)color_intl)->rgbtGreen;
			rgbq.rgbRed = ((RGBTRIPLE *)color_intl)->rgbtRed;
			rgbq.rgbReserved = 0xFF;
			for (unsigned x = 0; x < width; x++) {
				((RGBQUAD *)dst_bits)[x] = rgbq;
			}
			break;
		}
		default:
			return FALSE;
	}

	// Then, copy the first scanline into all following scanlines.
	// 'src_bits' is a pointer to the first scanline and is already
	// set up correctly.
	if (src_bits) {
		unsigned pitch = FreeImage_GetPitch(dib);
		unsigned bytes = FreeImage_GetLine(dib);
		dst_bits = src_bits + pitch;
		for (unsigned y = 1; y < height; y++) {
			memcpy(dst_bits, src_bits, bytes);
			dst_bits += pitch;
		}
	}
	return TRUE;
}
Ejemplo n.º 13
0
/// Performs vertical image filtering
void CResizeEngine::verticalFilter(FIBITMAP *src, unsigned src_width, unsigned src_height, FIBITMAP *dst, unsigned dst_width, unsigned dst_height) { 
	if(src_height == dst_height) {
		// no scaling required, just copy
		BYTE *src_bits = FreeImage_GetBits(src);
		BYTE *dst_bits = FreeImage_GetBits(dst);
		memcpy(dst_bits, src_bits, dst_height * FreeImage_GetPitch(dst));	
	}
	else {
		unsigned index;	// pixel index

		// allocate and calculate the contributions
		CWeightsTable weightsTable(m_pFilter, dst_height, src_height); 


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

				unsigned src_pitch = FreeImage_GetPitch(src);
				unsigned dst_pitch = FreeImage_GetPitch(dst);

				for(unsigned x = 0; x < dst_width; x++) {
					index = x * bytespp;

					// work on column x in dst
					BYTE *dst_bits = FreeImage_GetBits(dst) + index;

					// scale each column
					for(unsigned y = 0; y < dst_height; y++) {
						// loop through column
						double value[4] = {0, 0, 0, 0};					// 4 = 32bpp max
						int iLeft = weightsTable.getLeftBoundary(y);    // retrieve left boundary
						int iRight = weightsTable.getRightBoundary(y);  // retrieve right boundary

						BYTE *src_bits = FreeImage_GetScanLine(src, iLeft) + index;

						for(int i = iLeft; i <= iRight; i++) {
							// scan between boundaries
							// accumulate weighted effect of each neighboring pixel
							double weight = weightsTable.getWeight(y, i-iLeft);							
							for (unsigned j = 0; j < bytespp; j++) {
								value[j] += (weight * (double)src_bits[j]);
							}

							src_bits += src_pitch;
						}

						// clamp and place result in destination pixel
						for (unsigned j = 0; j < bytespp; j++) {
							dst_bits[j] = (BYTE)MIN(MAX((int)0, (int)(value[j] + 0.5)), (int)255);
						}

						dst_bits += dst_pitch;
					}
				}
			}
			break;

			case 16:
			case 48:
			case 64:
			{
				// Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 96-bit)
				unsigned wordspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(WORD);

				unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(WORD);
				unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(WORD);

				for(unsigned x = 0; x < dst_width; x++) {
					index = x * wordspp;

					// work on column x in dst
					WORD *dst_bits = (WORD*)FreeImage_GetBits(dst) + index;

					// scale each column
					for(unsigned y = 0; y < dst_height; y++) {
						// loop through column
						double value[4] = {0, 0, 0, 0};					// 4 = 64bpp max
						int iLeft = weightsTable.getLeftBoundary(y);    // retrieve left boundary
						int iRight = weightsTable.getRightBoundary(y);  // retrieve right boundary

						WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, iLeft) + index;

						for(int i = iLeft; i <= iRight; i++) {
							// scan between boundaries
							// accumulate weighted effect of each neighboring pixel
							double weight = weightsTable.getWeight(y, i-iLeft);							
							for (unsigned j = 0; j < wordspp; j++) {
								value[j] += (weight * (double)src_bits[j]);
							}

							src_bits += src_pitch;
						}

						// clamp and place result in destination pixel
						for (unsigned j = 0; j < wordspp; j++) {
							dst_bits[j] = (BYTE)MIN(MAX((WORD)0, (WORD)(value[j] + 0.5)), (WORD)0xFFFF);
						}

						dst_bits += dst_pitch;
					}
				}
			}
			break;

		}
	}
} 
Ejemplo n.º 14
0
template < typename Tsrc > int LOGIC < Tsrc >::MaskImage (FIBITMAP * src, FIBITMAP * mask)
{
    if (mask == NULL || src == NULL)
    {
        return FIA_ERROR;
    }

    // Have to be the same size
    if (FIA_CheckDimensions (src, mask) == FIA_ERROR)
    {
        return FIA_ERROR;
    }

    // Mask has to be 8 bit 
    if (FreeImage_GetBPP (mask) != 8 || FreeImage_GetImageType (mask) != FIT_BITMAP)
    {
        return FIA_ERROR;
    }

    int width = FreeImage_GetWidth (src);
    int height = FreeImage_GetHeight (src);

    bool greyscale_image = true;

    if(FreeImage_GetImageType(src) == FIT_BITMAP && FreeImage_GetBPP(src) > 8) {
	    greyscale_image = false;
    }
    
    if(greyscale_image) {
        for(register int y = 0; y < height; y++)
        {
            Tsrc *src_ptr = (Tsrc *) FreeImage_GetScanLine (src, y);
            unsigned char *mask_ptr = (unsigned char *) FreeImage_GetScanLine (mask, y);

            for(register int x = 0; x < width; x++)
            {
                if (!mask_ptr[x])
                    src_ptr[x] = 0;
            }
        }
    }
    else {
        
        int bytespp = FreeImage_GetLine (src) / FreeImage_GetWidth (src);
    
        for(register int y = 0; y < height; y++)
        {
            BYTE *src_ptr = (BYTE *) FreeImage_GetScanLine (src, y);
            BYTE *mask_ptr = (BYTE *) FreeImage_GetScanLine (mask, y);

            for(register int x = 0; x < width; x++)
            {
                if (!mask_ptr[x]) {

                    src_ptr[FI_RGBA_RED] = 0;
		            src_ptr[FI_RGBA_GREEN] = 0;
		            src_ptr[FI_RGBA_BLUE] = 0;

		            if (bytespp == 4)
			          src_ptr[FI_RGBA_ALPHA] = 0;   
                }
                
                src_ptr += bytespp;
            }
        }
    }
    
    return FIA_SUCCESS;
}
Ejemplo n.º 15
0
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
	if ((dib != NULL) && (handle != NULL)) {
		// write the file header

		BITMAPFILEHEADER bitmapfileheader;
		bitmapfileheader.bfType = 0x4D42;
		bitmapfileheader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib);
		bitmapfileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD);
		bitmapfileheader.bfReserved1 = 0;
		bitmapfileheader.bfReserved2 = 0;

		// take care of the bit fields data of any

		bool bit_fields = (FreeImage_GetBPP(dib) == 16);

		if (bit_fields) {
			bitmapfileheader.bfSize += 3 * sizeof(DWORD);
			bitmapfileheader.bfOffBits += 3 * sizeof(DWORD);
		}

#ifdef FREEIMAGE_BIGENDIAN
		SwapFileHeader(&bitmapfileheader);
#endif
		if (io->write_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle) != 1)
			return FALSE;		

		// update the bitmap info header

		BITMAPINFOHEADER bih = *FreeImage_GetInfoHeader(dib);

		if (bit_fields)
			bih.biCompression = BI_BITFIELDS;
		else if ((bih.biBitCount == 8) && (flags & BMP_SAVE_RLE))
			bih.biCompression = BI_RLE8;
		else
			bih.biCompression = BI_RGB;

		// write the bitmap info header

#ifdef FREEIMAGE_BIGENDIAN
		SwapInfoHeader(&bih);
#endif
		if (io->write_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle) != 1)
			return FALSE;

		// write the bit fields when we are dealing with a 16 bit BMP

		if (bit_fields) {
			DWORD d;

			d = FreeImage_GetRedMask(dib);

			if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1)
				return FALSE;

			d = FreeImage_GetGreenMask(dib);

			if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1)
				return FALSE;

			d = FreeImage_GetBlueMask(dib);

			if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1)
				return FALSE;
		}

		// write the palette

		if (FreeImage_GetPalette(dib) != NULL) {
			RGBQUAD *pal = FreeImage_GetPalette(dib);
			FILE_BGRA bgra;
			for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++ ) {
				bgra.b = pal[i].rgbBlue;
				bgra.g = pal[i].rgbGreen;
				bgra.r = pal[i].rgbRed;
				bgra.a = pal[i].rgbReserved;
				if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1)
					return FALSE;
			}
		}

		// write the bitmap data... if RLE compression is enable, use it

		unsigned bpp = FreeImage_GetBPP(dib);
		if ((bpp == 8) && (flags & BMP_SAVE_RLE)) {
			BYTE *buffer = new BYTE[FreeImage_GetPitch(dib) * 2];

			for (DWORD i = 0; i < FreeImage_GetHeight(dib); ++i) {
				int size = RLEEncodeLine(buffer, FreeImage_GetScanLine(dib, i), FreeImage_GetLine(dib));

				if (io->write_proc(buffer, size, 1, handle) != 1) {
					delete [] buffer;
					return FALSE;
				}
			}

			buffer[0] = RLE_COMMAND;
			buffer[1] = RLE_ENDOFBITMAP;

			if (io->write_proc(buffer, 2, 1, handle) != 1) {
				delete [] buffer;
				return FALSE;
			}

			delete [] buffer;
#ifdef FREEIMAGE_BIGENDIAN
		} else if (bpp == 16) {
			WORD pixel;
			for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
				BYTE *line = FreeImage_GetScanLine(dib, y);
				for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
					pixel = ((WORD *)line)[x];
					SwapShort(&pixel);
					if (io->write_proc(&pixel, sizeof(WORD), 1, handle) != 1)
						return FALSE;
				}
			}
		} else if (bpp == 24) {
			FILE_BGR bgr;
			for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
				BYTE *line = FreeImage_GetScanLine(dib, y);
				for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
					RGBTRIPLE *triple = ((RGBTRIPLE *)line)+x;
					bgr.b = triple->rgbtBlue;
					bgr.g = triple->rgbtGreen;
					bgr.r = triple->rgbtRed;
					if (io->write_proc(&bgr, sizeof(FILE_BGR), 1, handle) != 1)
						return FALSE;
				}
			}
		} else if (bpp == 32) {
			FILE_BGRA bgra;
			for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
				BYTE *line = FreeImage_GetScanLine(dib, y);
				for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
					RGBQUAD *quad = ((RGBQUAD *)line)+x;
					bgra.b = quad->rgbBlue;
					bgra.g = quad->rgbGreen;
					bgra.r = quad->rgbRed;
					bgra.a = quad->rgbReserved;
					if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1)
						return FALSE;
				}
			}
#endif
		} else if (io->write_proc(FreeImage_GetBits(dib), FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib), 1, handle) != 1) {
			return FALSE;
		}

		return TRUE;
	} else {
		return FALSE;
	}
}
Ejemplo n.º 16
0
bool sr::Texture::LoadFromFile(const std::string& relativePath, const sr::FileSystem& fileSystem)
{
    Unload();
    Name(relativePath);
    
    const std::string fullPath   = fileSystem.GetFullPath(relativePath);
    const char* filename         = fullPath.c_str();
    const GLenum image_format    = GL_RGB;    // format the image is in
    const GLint  internal_format = GL_RGB;    // format to store the image in
    const GLint  level           = 0;	        // mipmapping level
    const GLint  border          = 0;	        // border size
        	
	//check the file signature and deduce its format
	FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(filename, 0);

    // Try to guess the file format from the file extension:
	if(fif == FIF_UNKNOWN) 
		fif = FreeImage_GetFIFFromFilename(filename);

	// if still unkown, return failure
	if(fif == FIF_UNKNOWN || !FreeImage_FIFSupportsReading(fif))
		return false;

	//check that the plugin has reading capabilities and load the file
    FIBITMAP* const dib = FreeImage_Load(fif, filename, PNG_DEFAULT);
	if(!dib) 
        return false;
    
	BYTE* const bits = FreeImage_GetBits(dib);
	const unsigned int width = FreeImage_GetWidth(dib);
	const unsigned int height = FreeImage_GetHeight(dib);
	
	// if this somehow one of these failed (they shouldn't), return failure
	if((bits == nullptr) || (width == 0) || (height == 0))
		return false;
	
	// Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
	const int bpp = FreeImage_GetLine(dib) / FreeImage_GetWidth(dib);

	// Exchange red and blue channel because FreeImage loads in BGRA format; while we need it as RGBA:
	for(unsigned y = 0; y < height; ++y)
	{
		BYTE* line = FreeImage_GetScanLine(dib, y);

		for( unsigned x = 0; x < width; ++x ) 
		{
			const BYTE r = line[FI_RGBA_BLUE];			
			const BYTE b = line[FI_RGBA_RED];
			line[FI_RGBA_RED]  = r;
			line[FI_RGBA_BLUE] = b;

			// jump to next pixel
			line += bpp;
		}
	}

    // Generate
	glGenTextures(1, &id);
	glBindTexture(GL_TEXTURE_2D, id);
	glTexImage2D(GL_TEXTURE_2D, level, internal_format, width, height, border, image_format, GL_UNSIGNED_BYTE, bits);

    // Configure
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    	
	GLfloat maxAniso(0.0f);
	glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso);

	// Free FreeImage's copy of the data
	FreeImage_Unload(dib);

    if(id != 0)
    {
        size = glm::uvec2(width, height);
        Loaded(true);
        return true;
    }
    else
    {
        return false;
    }
}
Ejemplo n.º 17
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	if (handle != NULL) {
		FIBITMAP *dib = NULL;

		DWORD type, size;

		io->read_proc(&type, 4, 1, handle);
#ifndef FREEIMAGE_BIGENDIAN
		SwapLong(&type);
#endif

		if(type != ID_FORM)
			return NULL;

		io->read_proc(&size, 4, 1, handle);
#ifndef FREEIMAGE_BIGENDIAN
		SwapLong(&size);
#endif

		io->read_proc(&type, 4, 1, handle);
#ifndef FREEIMAGE_BIGENDIAN
		SwapLong(&type);
#endif

		if((type != ID_ILBM) && (type != ID_PBM))
			return NULL;

		size -= 4;

		unsigned width = 0, height = 0, planes = 0, depth = 0, comp = 0;

		while (size) {
			DWORD ch_type,ch_size;

			io->read_proc(&ch_type, 4, 1, handle);
#ifndef FREEIMAGE_BIGENDIAN
			SwapLong(&ch_type);
#endif

			io->read_proc(&ch_size,4,1,handle );
#ifndef FREEIMAGE_BIGENDIAN
			SwapLong(&ch_size);
#endif

			unsigned ch_end = io->tell_proc(handle) + ch_size;

			if (ch_type == ID_BMHD) {			// Bitmap Header
				if (dib)
					FreeImage_Unload(dib);

				BMHD bmhd;

				io->read_proc(&bmhd, sizeof(bmhd), 1, handle);
#ifndef FREEIMAGE_BIGENDIAN
				SwapHeader(&bmhd);
#endif

				width = bmhd.w;
				height = bmhd.h;
				planes = bmhd.nPlanes;
				comp = bmhd.compression;

				if(bmhd.masking & 1)
					planes++;	// there is a mask ( 'stencil' )

				if (planes > 8 && planes != 24)
					return NULL;

				depth = planes > 8 ? 24 : 8;

				if( depth == 24 ) {
					dib = FreeImage_Allocate(width, height, depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
				} else {
					dib = FreeImage_Allocate(width, height, depth);
				}
			} else if (ch_type == ID_CMAP) {	// Palette (Color Map)
				if (!dib)
					return NULL;

				RGBQUAD *pal = FreeImage_GetPalette(dib);

				for (unsigned k = 0; k < ch_size / 3; k++) {					
					io->read_proc(&pal[k].rgbRed, 1, 1, handle );
					io->read_proc(&pal[k].rgbGreen, 1, 1, handle );
					io->read_proc(&pal[k].rgbBlue, 1, 1, handle );
				}
			} else if (ch_type == ID_BODY) {
				if (!dib)
					return NULL;

				if (type == ID_PBM) {
					// NON INTERLACED (LBM)

					unsigned line = FreeImage_GetLine(dib) + 1 & ~1;
					
					for (unsigned i = 0; i < FreeImage_GetHeight(dib); i++) {
						BYTE *bits = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - i - 1);

						if (comp == 1) {
							// use RLE compression

							DWORD number_of_bytes_written = 0;
							BYTE rle_count;
							BYTE byte;

							while (number_of_bytes_written < line) {
								io->read_proc(&rle_count, 1, 1, handle);

								if (rle_count < 128) {
									for (int k = 0; k < rle_count + 1; k++) {
										io->read_proc(&byte, 1, 1, handle);

										bits[number_of_bytes_written++] += byte;
									}
								} else if (rle_count > 128) {
									io->read_proc(&byte, 1, 1, handle);

									for (int k = 0; k < 257 - rle_count; k++) {
										bits[number_of_bytes_written++] += byte;
									}
								}
							}
						} else {
							// don't use compression

							io->read_proc(bits, line, 1, handle);
						}
					}

					return dib;
				} else {
					// INTERLACED (ILBM)

					unsigned pixel_size = depth/8;
					unsigned n_width=(width+15)&~15;
					unsigned plane_size = n_width/8;
					unsigned src_size = plane_size * planes;
					BYTE *src = (BYTE*)malloc(src_size);
					BYTE *dest = FreeImage_GetBits(dib);

					dest += FreeImage_GetPitch(dib) * height;

					for (unsigned y = 0; y < height; y++) {
						dest -= FreeImage_GetPitch(dib);

						// read all planes in one hit,
						// 'coz PSP compresses across planes...

						if (comp) {
							// unpacker algorithm

							for(unsigned x = 0; x < src_size;) {
								// read the next source byte into t
								signed char t = 0;
								io->read_proc(&t, 1, 1, handle);
								
								if (t >= 0) {
									// t = [0..127] => copy the next t+1 bytes literally
									unsigned size_to_read = t + 1;

									if((size_to_read + x) > src_size) {
										// sanity check for buffer overruns 
										size_to_read = src_size - x;
										io->read_proc(src + x, size_to_read, 1, handle);
										x += (t + 1);
									} else {
										io->read_proc(src + x, size_to_read, 1, handle);
										x += size_to_read;
									}
								} else if (t != -128) {
									// t = [-1..-127]  => replicate the next byte -t+1 times
									BYTE b = 0;
									io->read_proc(&b, 1, 1, handle);
									unsigned size_to_copy = (unsigned)(-(int)t + 1);

									if((size_to_copy + x) > src_size) {
										// sanity check for buffer overruns 
										size_to_copy = src_size - x;
										memset(src + x, b, size_to_copy);
										x += (unsigned)(-(int)t + 1);
									} else {
										memset(src + x, b, size_to_copy);
										x += size_to_copy;
									}
								}
								// t = -128 => noop
							}
						} else {
							io->read_proc(src, src_size, 1, handle);
						}

						// lazy planar->chunky...

						for (unsigned x = 0; x < width; x++) {
							for (unsigned n = 0; n < planes; n++) {
								BYTE bit = (BYTE)( src[n * plane_size + (x / 8)] >> ((x^7) & 7) );

								dest[x * pixel_size + (n / 8)] |= (bit & 1) << (n & 7);
							}
						}

#ifndef FREEIMAGE_BIGENDIAN
						if (depth == 24) {
							for (unsigned x = 0; x < width; ++x){
								INPLACESWAP(dest[x * 3], dest[x * 3 + 2]);
							}
						}
#endif
					}

					free(src);

					return dib;
				}
			}

			// Every odd-length chunk is followed by a 0 pad byte.  This pad
			//  byte is not counted in ch_size.
			if (ch_size & 1) {
				ch_size++;
				ch_end++;
			}

			io->seek_proc(handle, ch_end - io->tell_proc(handle), SEEK_CUR);

			size -= ch_size + 8;
		}

		if (dib)
			FreeImage_Unload(dib);
	}
Ejemplo n.º 18
0
/** open the given bitmap file and guarantee
 that the pixels can be accessed by RGB
 ( i.e. convert if indexed )
 @return true -> opened and converted correct
*/
bool Vt2IsoImageFreeImage_c::openBitmap( const char* filename )
{
 reset();
 i_curScanLineY = -1;

 if (isOstream())
   getOstream() << std::endl << "Opening " << filename << std::endl;
 FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;

 // check the file signature and deduce its format
 // (the second argument is currently not used by FreeImage)
 fif = FreeImage_GetFileType(filename, 0);
 if(fif == FIF_UNKNOWN) {
  // no signature ?
  // try to guess the file format from the file extension
  fif = FreeImage_GetFIFFromFilename(filename);
  if (isOstream()) getOstream() << "File type not recognized" << std::endl;
 }
 // check that the plugin has reading capabilities ...
 if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
  // ok, let's load the file
  bitmap = FreeImage_Load(fif, filename, 0);
 }
 else
 { // hardcore - try with BMP
  if (isOstream()) getOstream() << "Try with BMP" << std::endl;
  bitmap = FreeImage_Load(FIF_BMP, filename, 0);
  if ( bitmap == NULL )
  { // next hardcoretry with png
    if (isOstream()) getOstream() << "Try with PNG" << std::endl;
    bitmap = FreeImage_Load(FIF_PNG, filename, 0);
  }
  if ( bitmap == NULL )
  { // next hardcoretry with jpg
    if (isOstream()) getOstream() << "Try with JPEG" << std::endl;
    bitmap = FreeImage_Load(FIF_JPEG, filename, 0);
  }
 }
 if ( bitmap == NULL )
 {
    if (isOstream()) getOstream() << "Error loading bitmap file" << std::endl;
    return false;
 }
 else if (isOstream()) getOstream() << "Bitmap successfully loaded" << std::endl;

 if (FreeImage_GetBPP(bitmap) > 8)
 { // convert to 32-Bit standard bitmap ONLY if NOT palettized!
   FIBITMAP *tmp = FreeImage_ConvertTo32Bits(bitmap);
   FreeImage_Unload(bitmap);
   bitmap = tmp;
 }

 ui_width  = FreeImage_GetWidth(bitmap);
 ui_height = FreeImage_GetHeight(bitmap);
 // Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
 bytespp = FreeImage_GetLine(bitmap) / FreeImage_GetWidth(bitmap);

 mb_palettized = false;

 if (FreeImage_GetBPP(bitmap) <= 8)
 {
   mi_colourMismatch = -1; // default: no colour mismatches...

   for (int i=0; i<(16+216); i++)
   { // check all colours if the bitmap uses the ISO-palette
     if ( (vtColourTable[i].bgrRed != FreeImage_GetPalette (bitmap)[i].rgbRed)
       || (vtColourTable[i].bgrGreen != FreeImage_GetPalette (bitmap)[i].rgbGreen)
       || (vtColourTable[i].bgrBlue != FreeImage_GetPalette (bitmap)[i].rgbBlue) )
     {
       mi_colourMismatch = i;
       break;
     }
   }
   mb_palettized = true;
   if (isOstream()) getOstream() << " palettized (depth="<<FreeImage_GetBPP(bitmap)<<"). ";
   return true;
 }
 else
 {
   if (isOstream()) getOstream() << " as RGB (depth="<<FreeImage_GetBPP(bitmap)<<"). ";
   return true;
 }
}
Ejemplo n.º 19
0
unsigned fipImage::getLine() const {
	return FreeImage_GetLine(_dib);
}
Ejemplo n.º 20
0
// MAIN
int main(int argc, char ** argv) {
	int scene_id = 0;
	bool use_octree = false;
	char basename[256] = "";
	if (argc > 1)
		scene_id = atoi(argv[1]);
	if (argc > 2)
		strcpy(basename, argv[2]);

	// scene_id 0, 1, 2, 3 is for tp 1 tests;
	switch (scene_id) {
	case 0:
		fill_red(output_image);
		break;
	case 1:
		fill(output_image, vector_init(0.7, 0.3, 0.1));
		fill_rect(output_image, vector_init(0.2, 0.6, 0.7), vector_init(WIDTH / 4, HEIGHT / 5, 0), vector_init(WIDTH / 3, HEIGHT / 4, 0));
		break;
	case 2:
		horizontal_gradient(output_image, vector_init(0, 0, 1), vector_init(1, 1, 1));
		break;
	case 3:
		horizontal_gradient(output_image, vector_init(0, 0, 1), vector_init(1, 1, 1));
		fill_circle(output_image, WIDTH / 20, vector_init(4 * WIDTH / 5, 4 * HEIGHT / 5, 0), vector_init(1, 1, 0));
		fill_rect(output_image, vector_init(0.1, 0.8, 0.4), vector_init(0, 0, 0), vector_init(WIDTH, HEIGHT / 4, 0));
		break;
	case 4:
		horizontal_gradient(output_image, vector_init(0.5, 0.8, 1), vector_init(1, 1, 1));
		fill_circle(output_image, WIDTH / 20, vector_init(4 * WIDTH / 5, 4 * HEIGHT / 5, 0), vector_init(1, 1, 0));
		fill_circle(output_image, WIDTH / 21, vector_init(3 * WIDTH / 5, 3 * HEIGHT / 5, 0), vector_init(1, 0.3, 0.1));
		fill_rect(output_image, vector_init(0.85, 0.85, 0.3), vector_init(0, 0, 0), vector_init(WIDTH, HEIGHT / 4, 0));
		break;
	default:
		setup_scene(scene_id - 5);
		raytrace();
		break;
	}

#ifdef USE_FREEIMAGE
	FreeImage_Initialise();
	FIBITMAP *bitmap = FreeImage_Allocate(WIDTH, HEIGHT, 32, FI_RGBA_RED_MASK,
			FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
	if (bitmap) {
		// bitmap successfully created!

		// Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
		color *ptr = output_image;
		int bytespp = FreeImage_GetLine(bitmap) / FreeImage_GetWidth(bitmap);
		for(unsigned y = 0; y < FreeImage_GetHeight(bitmap); y++) {
			BYTE *bits = FreeImage_GetScanLine(bitmap, y);
			for(unsigned x = 0; x < FreeImage_GetWidth(bitmap); x++) {
				// Set pixel color to green with a transparency of 128
				*ptr = vector_clamp(*ptr, 0.f, 1.f);
				bits[FI_RGBA_RED] = ptr->x*255;
				bits[FI_RGBA_GREEN] = ptr->y*255;
				bits[FI_RGBA_BLUE] = ptr->z*255;
				bits[FI_RGBA_ALPHA] = 255;
				// jump to next pixel
				bits += bytespp;
				ptr++;
			}
		}

		// FreeImage_Save(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const char *filename, int flags FI_DEFAULT(0));
		char filename[256];
		strcpy(filename, basename);
		strcat(filename, ".png");
		if (FreeImage_Save(FIF_PNG, bitmap, filename, 0)) {
			// bitmap successfully saved!
		}
		FreeImage_Unload(bitmap);
	}

	FreeImage_DeInitialise();
#endif
	// le code ci dessous crée et sauvegarde une image sous le nom output.png dans le repertoire d'execution
	{
		FILE *fp = NULL;
		char filename[256];
		strcpy(filename, basename);
		strcat(filename, ".ppm");

		fp = fopen(filename, "w");

		if (fp) {
			// création réussi

			fprintf(fp, "P3\n");
			fprintf(fp, "%d %d\n255\n", WIDTH, HEIGHT);
			// La c'est pour faire la boucle

			for (unsigned y = 0; y < HEIGHT; y++) {
				color *ptr = &(output_image[(HEIGHT - y - 1) * WIDTH]);
				for (unsigned x = 0; x < WIDTH; x++) {
					*ptr = vector_clamp(*ptr, 0.f, 1.f);
					unsigned char r = ptr->x * 255;
					unsigned char g = ptr->y * 255;
					unsigned char b = ptr->z * 255;
					ptr++;
					fprintf(fp, "%d %d %d  ", r, g, b);
				}
				fprintf(fp, "\n");
			}
			fclose(fp);
		}
	}

	return 0;
}
Ejemplo n.º 21
0
static HBITMAP 
GetDibSection(FIBITMAP *src, HDC hdc, int left, int top, int right, int bottom)
{
	if(!src) 
		return NULL;

	unsigned bpp = FreeImage_GetBPP(src);

	if(bpp <=4)
		return NULL;

	// normalize the rectangle
	if(right < left)
		INPLACESWAP(left, right);

	if(bottom < top)
		INPLACESWAP(top, bottom);

	// check the size of the sub image
	int src_width  = FreeImage_GetWidth(src);
	int src_height = FreeImage_GetHeight(src);
	int src_pitch = FreeImage_GetPitch(src);

	if((left < 0) || (right > src_width) || (top < 0) || (bottom > src_height))
		return NULL;

	// allocate the sub image
	int dst_width = (right - left);
	int dst_height = (bottom - top);

	BITMAPINFO *info = (BITMAPINFO *) malloc(sizeof(BITMAPINFO) + (FreeImage_GetColorsUsed(src) * sizeof(RGBQUAD)));
	BITMAPINFOHEADER *bih = (BITMAPINFOHEADER *)info;

	bih->biSize = sizeof(BITMAPINFOHEADER);
	bih->biWidth = dst_width;
	bih->biHeight = dst_height;
	bih->biPlanes = 1;
	bih->biBitCount = bpp;
	bih->biCompression = BI_RGB;
	bih->biSizeImage = 0;
    bih->biXPelsPerMeter = 0;
    bih->biYPelsPerMeter = 0;
   	bih->biClrUsed = 0;           // Always use the whole palette.
    bih->biClrImportant = 0;

	// copy the palette
	if(bpp < 16)
		memcpy(info->bmiColors, FreeImage_GetPalette(src), FreeImage_GetColorsUsed(src) * sizeof(RGBQUAD));

	BYTE *dst_bits;

	HBITMAP hbitmap = CreateDIBSection(hdc, info, DIB_RGB_COLORS, (void **) &dst_bits, NULL, 0);

	free(info);

	if(hbitmap == NULL || dst_bits == NULL)
		return NULL;

	// get the pointers to the bits and such
	BYTE *src_bits = FreeImage_GetScanLine(src, src_height - top - dst_height);

	// calculate the number of bytes per pixel
	unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
	
	// point to x = left
	src_bits += (left * bytespp);	

	int dst_line = (dst_width * bpp + 7) / 8;
	int dst_pitch = (dst_line + 3) & ~3;

	for(int y = 0; y < dst_height; y++)
		memcpy(dst_bits + (y * dst_pitch), src_bits + (y * src_pitch), dst_line);

	return hbitmap;
}
Ejemplo n.º 22
0
/** @brief Perfoms an histogram transformation on a 8, 24 or 32-bit image 
according to the values of a lookup table (LUT).

The transformation is done as follows.<br>
Image 8-bit : if the image has a color palette, the LUT is applied to this palette, 
otherwise, it is applied to the grey values.<br>
Image 24-bit & 32-bit : if channel == FICC_RGB, the same LUT is applied to each color
plane (R,G, and B). Otherwise, the LUT is applied to the specified channel only.
@param src Input image to be processed.
@param LUT Lookup table. <b>The size of 'LUT' is assumed to be 256.</b>
@param channel The color channel to be processed (only used with 24 & 32-bit DIB).
@return Returns TRUE if successful, FALSE otherwise.
@see FREE_IMAGE_COLOR_CHANNEL
*/
BOOL DLL_CALLCONV 
FreeImage_AdjustCurve(FIBITMAP *src, BYTE *LUT, FREE_IMAGE_COLOR_CHANNEL channel) {
	unsigned x, y;
	BYTE *bits = NULL;

	if(!src || !LUT || (FreeImage_GetImageType(src) != FIT_BITMAP))
		return FALSE;

	int bpp = FreeImage_GetBPP(src);
	if((bpp != 8) && (bpp != 24) && (bpp != 32))
		return FALSE;

	// apply the LUT
	switch(bpp) {

		case 8 :
		{
			// if the dib has a colormap, apply the LUT to it
			// else, apply the LUT to pixel values

			if(FreeImage_GetColorType(src) == FIC_PALETTE) {
				RGBQUAD *rgb = FreeImage_GetPalette(src);
				for (unsigned pal = 0; pal < FreeImage_GetColorsUsed(src); pal++) {
					rgb->rgbRed   = LUT[rgb->rgbRed];
					rgb->rgbGreen = LUT[rgb->rgbGreen];
					rgb->rgbBlue  = LUT[rgb->rgbBlue];
					rgb++;
				}
			}
			else {
				for(y = 0; y < FreeImage_GetHeight(src); y++) {
					bits =  FreeImage_GetScanLine(src, y);
					for(x = 0; x < FreeImage_GetWidth(src); x++) {
						bits[x] = LUT[ bits[x] ];
					}
				}
			}

			break;
		}

		case 24 :
		case 32 :
		{
			int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);

			switch(channel) {
				case FICC_RGB :
					for(y = 0; y < FreeImage_GetHeight(src); y++) {
						bits =  FreeImage_GetScanLine(src, y);
						for(x = 0; x < FreeImage_GetWidth(src); x++) {
							bits[FI_RGBA_BLUE]	= LUT[ bits[FI_RGBA_BLUE] ];	// B
							bits[FI_RGBA_GREEN] = LUT[ bits[FI_RGBA_GREEN] ];	// G
							bits[FI_RGBA_RED]	= LUT[ bits[FI_RGBA_RED] ];		// R
							
							bits += bytespp;
						}
					}
					break;

				case FICC_BLUE :
					for(y = 0; y < FreeImage_GetHeight(src); y++) {
						bits =  FreeImage_GetScanLine(src, y);
						for(x = 0; x < FreeImage_GetWidth(src); x++) {
							bits[FI_RGBA_BLUE] = LUT[ bits[FI_RGBA_BLUE] ];		// B
							
							bits += bytespp;
						}
					}
					break;

				case FICC_GREEN :
					for(y = 0; y < FreeImage_GetHeight(src); y++) {
						bits =  FreeImage_GetScanLine(src, y);
						for(x = 0; x < FreeImage_GetWidth(src); x++) {
							bits[FI_RGBA_GREEN] = LUT[ bits[FI_RGBA_GREEN] ];	// G
							
							bits += bytespp;
						}
					}
					break;

				case FICC_RED :
					for(y = 0; y < FreeImage_GetHeight(src); y++) {
						bits =  FreeImage_GetScanLine(src, y);
						for(x = 0; x < FreeImage_GetWidth(src); x++) {
							bits[FI_RGBA_RED] = LUT[ bits[FI_RGBA_RED] ];		// R
							
							bits += bytespp;
						}
					}
					break;
					
				case FICC_ALPHA :
					if(32 == bpp) {
						for(y = 0; y < FreeImage_GetHeight(src); y++) {
							bits =  FreeImage_GetScanLine(src, y);
							for(x = 0; x < FreeImage_GetWidth(src); x++) {
								bits[FI_RGBA_ALPHA] = LUT[ bits[FI_RGBA_ALPHA] ];	// A
								
								bits += bytespp;
							}
						}
					}
					break;

				default:
					break;
			}
			break;
		}
	}

	return TRUE;
}
Ejemplo n.º 23
0
unsigned DLL_CALLCONV
FreeImage_GetPitch(FIBITMAP *dib) {
	return dib ? FreeImage_GetLine(dib) + 3 & ~3 : 0;
}
Ejemplo n.º 24
0
/** @brief Applies palette index mapping for one or several indices on a 1-, 4- 
 or 8-bit palletized image.

 This function maps up to <i>count</i> palette indices specified in
 <i>srcindices</i> to these specified in <i>dstindices</i>. Thereby, index 
 <i>srcindices[N]</i>, if present in the image, will be replaced by index
 <i>dstindices[N]</i>. If parameter <i>swap</i> is TRUE, additionally all indices
 specified in <i>dstindices</i> are also mapped to these specified in 
 <i>srcindices</i>.<br>

 The function returns the number of pixels changed or zero, if no pixels were
 changed. 

 Both arrays <i>srcindices</i> and <i>dstindices</i> are assumed not to hold less
 than <i>count</i> indices.<br>

 <b>Note, that this behaviour is different from what FreeImage_ApplyColorMapping()
 does, which modifies the actual image data on palletized images.</b>

 @param dib Input/output image to be processed.
 @param srcindices Array of palette indices to be used as the mapping source.
 @param dstindices Array of palette indices to be used as the mapping destination.
 @param count The number of palette indices to be mapped. This is the size of both
 <i>srcindices</i> and <i>dstindices</i>.  
 @param swap If TRUE, source and destination palette indices are swapped, that is,
 each destination index is also mapped to the corresponding source index.  
 @return Returns the total number of pixels changed. 
 */
unsigned DLL_CALLCONV
FreeImage_ApplyPaletteIndexMapping(FIBITMAP *dib, BYTE *srcindices,	BYTE *dstindices, unsigned count, BOOL swap) {
	unsigned result = 0;

	if ((!dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
		return 0;
	}

	// validate parameters
	if ((!srcindices) || (!dstindices)|| (count < 1)) {
		return 0;
	}

	unsigned height = FreeImage_GetHeight(dib);
	unsigned width = FreeImage_GetLine(dib);
	BYTE *a, *b;

	int bpp = FreeImage_GetBPP(dib);
	switch (bpp) {
		case 1: {

			return result;
		}
		case 4: {
			int skip_last = (FreeImage_GetWidth(dib) & 0x01);
			unsigned max_x = width - 1;
			for (unsigned y = 0; y < height; y++) {
				BYTE *bits = FreeImage_GetScanLine(dib, y);
				for (unsigned x = 0; x < width; x++) {
					int start = ((skip_last) && (x == max_x)) ? 1 : 0;
					for (int cn = start; cn < 2; cn++) {
						for (unsigned j = 0; j < count; j++) {
							a = srcindices;
							b = dstindices;
							for (int i = ((swap) ? 0 : 1); i < 2; i++) {
								if (GET_NIBBLE(cn, bits[x]) == (a[j] & 0x0F)) {
									SET_NIBBLE(cn, bits[x], b[j]);
									result++;
									j = count;
									break;
								}
								a = dstindices;
								b = srcindices;
							}
						}
					}
				}
			}
			return result;
		}
		case 8: {
			for (unsigned y = 0; y < height; y++) {
				BYTE *bits = FreeImage_GetScanLine(dib, y);
				for (unsigned x = 0; x < width; x++) {
					for (unsigned j = 0; j < count; j++) {
						a = srcindices;
						b = dstindices;
						for (int i = ((swap) ? 0 : 1); i < 2; i++) {
							if (bits[x] == a[j]) {
								bits[x] = b[j];
								result++;
								j = count;
								break;
							}
							a = dstindices;
							b = srcindices;
						}
					}
				}
			}
			return result;
		}
		default: {
			return 0;
		}
	}
}
Ejemplo n.º 25
0
WORD fipImage::getLine() const {
	return FreeImage_GetLine(_dib);
}
Ejemplo n.º 26
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;
}
Ejemplo n.º 27
0
FIBITMAP * DLL_CALLCONV
FreeImage_ConvertToRGBF(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:
            {
                // allow conversion from 24- and 32-bit
                const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
                if((color_type != FIC_RGB) && (color_type != FIC_RGBALPHA)) {
                    src = FreeImage_ConvertTo24Bits(dib);
                    if(!src) return NULL;
                } else {
                    src = dib;
                }
                break;
            }
        case FIT_UINT16:
            // allow conversion from 16-bit
            src = dib;
            break;
        case FIT_RGB16:
            // allow conversion from 48-bit RGB
            src = dib;
            break;
        case FIT_RGBA16:
            // allow conversion from 64-bit RGBA (ignore the alpha channel)
            src = dib;
            break;
        case FIT_FLOAT:
            // allow conversion from 32-bit float
            src = dib;
            break;
        case FIT_RGBAF:
            // allow conversion from 128-bit RGBAF
            src = dib;
            break;
        case FIT_RGBF:
            // RGBF type : clone the src
            return FreeImage_Clone(dib);
            break;
        default:
            return NULL;
    }

    // allocate dst image

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

    dst = FreeImage_AllocateT(FIT_RGBF, 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 RGBF

    const unsigned src_pitch = FreeImage_GetPitch(src);
    const unsigned dst_pitch = FreeImage_GetPitch(dst);

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

                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const BYTE   *src_pixel = (BYTE*)src_bits;
                    FIRGBF *dst_pixel = (FIRGBF*)dst_bits;
                    for(unsigned x = 0; x < width; x++) {
                        // convert and scale to the range [0..1]
                        dst_pixel->red   = (float)(src_pixel[FI_RGBA_RED])   / 255.0F;
                        dst_pixel->green = (float)(src_pixel[FI_RGBA_GREEN]) / 255.0F;
                        dst_pixel->blue  = (float)(src_pixel[FI_RGBA_BLUE])  / 255.0F;

                        src_pixel += bytespp;
                        dst_pixel ++;
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;

        case FIT_UINT16:
            {
                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const WORD *src_pixel = (WORD*)src_bits;
                    FIRGBF *dst_pixel = (FIRGBF*)dst_bits;

                    for(unsigned x = 0; x < width; x++) {
                        // convert and scale to the range [0..1]
                        const float dst_value = (float)src_pixel[x] / 65535.0F;
                        dst_pixel[x].red   = dst_value;
                        dst_pixel[x].green = dst_value;
                        dst_pixel[x].blue  = dst_value;
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;

        case FIT_RGB16:
            {
                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const FIRGB16 *src_pixel = (FIRGB16*) src_bits;
                    FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;

                    for(unsigned x = 0; x < width; x++) {
                        // convert and scale to the range [0..1]
                        dst_pixel[x].red   = (float)(src_pixel[x].red)   / 65535.0F;
                        dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F;
                        dst_pixel[x].blue  = (float)(src_pixel[x].blue)  / 65535.0F;
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;

        case FIT_RGBA16:
            {
                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const FIRGBA16 *src_pixel = (FIRGBA16*) src_bits;
                    FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;

                    for(unsigned x = 0; x < width; x++) {
                        // convert and scale to the range [0..1]
                        dst_pixel[x].red   = (float)(src_pixel[x].red)   / 65535.0F;
                        dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F;
                        dst_pixel[x].blue  = (float)(src_pixel[x].blue)  / 65535.0F;
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;

        case FIT_FLOAT:
            {
                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const float *src_pixel = (float*) src_bits;
                    FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;

                    for(unsigned x = 0; x < width; x++) {
                        // convert by copying greyscale channel to each R, G, B channels
                        // assume float values are in [0..1]
                        const float value = CLAMP(src_pixel[x], 0.0F, 1.0F);
                        dst_pixel[x].red   = value;
                        dst_pixel[x].green = value;
                        dst_pixel[x].blue  = value;
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;

        case FIT_RGBAF:
            {
                const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
                BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);

                for(unsigned y = 0; y < height; y++) {
                    const FIRGBAF *src_pixel = (FIRGBAF*) src_bits;
                    FIRGBF  *dst_pixel = (FIRGBF*)  dst_bits;

                    for(unsigned x = 0; x < width; x++) {
                        // convert and skip alpha channel
                        dst_pixel[x].red   = CLAMP(src_pixel[x].red, 0.0F, 1.0F);
                        dst_pixel[x].green = CLAMP(src_pixel[x].green, 0.0F, 1.0F);
                        dst_pixel[x].blue  = CLAMP(src_pixel[x].blue, 0.0F, 1.0F);
                    }
                    src_bits += src_pitch;
                    dst_bits += dst_pitch;
                }
            }
            break;
    }

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

    return dst;
}
Ejemplo n.º 28
0
/**
Copy or convert & copy decoded pixels into the dib
@param pDecoder Decoder handle
@param out_guid_format Target guid format
@param dib Output dib
@param width Image width
@param height Image height
@return Returns 0 if successful, returns ERR otherwise
*/
static ERR
CopyPixels(PKImageDecode *pDecoder, PKPixelFormatGUID out_guid_format, FIBITMAP *dib, int width, int height) {
	PKFormatConverter *pConverter = NULL;	// pixel format converter
	ERR error_code = 0;	// error code as returned by the interface
	BYTE *pb = NULL;	// local buffer used for pixel format conversion
	
	// image dimensions
	const PKRect rect = {0, 0, width, height};

	try {
		// get input file pixel format ...
		PKPixelFormatGUID in_guid_format;
		error_code = pDecoder->GetPixelFormat(pDecoder, &in_guid_format);
		JXR_CHECK(error_code);
		
		// is a format conversion needed ?

		if(IsEqualGUID(out_guid_format, in_guid_format)) {
			// no conversion, load bytes "as is" ...

			// get a pointer to dst pixel data
			BYTE *dib_bits = FreeImage_GetBits(dib);

			// get dst pitch (count of BYTE for stride)
			const unsigned cbStride = FreeImage_GetPitch(dib);			

			// decode and copy bits to dst array
			error_code = pDecoder->Copy(pDecoder, &rect, dib_bits, cbStride);
			JXR_CHECK(error_code);		
		}
		else {
			// we need to use the conversion API ...
			
			// allocate the pixel format converter
			error_code = PKCodecFactory_CreateFormatConverter(&pConverter);
			JXR_CHECK(error_code);
			
			// set the conversion function
			error_code = pConverter->Initialize(pConverter, pDecoder, NULL, out_guid_format);
			JXR_CHECK(error_code);
			
			// get the maximum stride
			unsigned cbStride = 0;
			{
				PKPixelInfo pPIFrom;
				PKPixelInfo pPITo;
				
				pPIFrom.pGUIDPixFmt = &in_guid_format;
				error_code = PixelFormatLookup(&pPIFrom, LOOKUP_FORWARD);
				JXR_CHECK(error_code);

				pPITo.pGUIDPixFmt = &out_guid_format;
				error_code = PixelFormatLookup(&pPITo, LOOKUP_FORWARD);
				JXR_CHECK(error_code);

				unsigned cbStrideFrom = ((pPIFrom.cbitUnit + 7) >> 3) * width;
				unsigned cbStrideTo = ((pPITo.cbitUnit + 7) >> 3) * width;
				cbStride = MAX(cbStrideFrom, cbStrideTo);
			}

			// allocate a local decoder / encoder buffer
			error_code = PKAllocAligned((void **) &pb, cbStride * height, 128);
			JXR_CHECK(error_code);

			// copy / convert pixels
			error_code = pConverter->Copy(pConverter, &rect, pb, cbStride);
			JXR_CHECK(error_code);

			// now copy pixels into the dib
			const size_t line_size = FreeImage_GetLine(dib);
			for(int y = 0; y < height; y++) {
				BYTE *src_bits = (BYTE*)(pb + y * cbStride);
				BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, y);
				memcpy(dst_bits, src_bits, line_size);
			}
			
			// free the local buffer
			PKFreeAligned((void **) &pb);

			// free the pixel format converter
			PKFormatConverter_Release(&pConverter);
		}

		// FreeImage DIB are upside-down relative to usual graphic conventions
		FreeImage_FlipVertical(dib);

		// post-processing ...
		// -------------------

		// swap RGB as needed

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
		if(IsEqualGUID(out_guid_format, GUID_PKPixelFormat24bppRGB) || IsEqualGUID(out_guid_format, GUID_PKPixelFormat32bppRGB)) {
			SwapRedBlue32(dib);
		}
#elif FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
		if(IsEqualGUID(out_guid_format, GUID_PKPixelFormat24bppBGR) || IsEqualGUID(out_guid_format, GUID_PKPixelFormat32bppBGR)) {
			SwapRedBlue32(dib);
		}
#endif
		
		return WMP_errSuccess;

	} catch(...) {
		// free the local buffer
		PKFreeAligned((void **) &pb);
		// free the pixel format converter
		PKFormatConverter_Release(&pConverter);

		return error_code;
	}
}