コード例 #1
0
/**
Calculate the size of a FreeImage image. 
Align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary.
*/
static unsigned 
FreeImage_GetImageSize(int width, int height, int bpp) {
	unsigned dib_size = sizeof(FREEIMAGEHEADER); 
	dib_size += (dib_size % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - dib_size % FIBITMAP_ALIGNMENT : 0);  
	dib_size += FIBITMAP_ALIGNMENT - sizeof(BITMAPINFOHEADER) % FIBITMAP_ALIGNMENT; 
	dib_size += sizeof(BITMAPINFOHEADER);  
	// palette is aligned on a 16 bytes boundary
	dib_size += sizeof(RGBQUAD) * CalculateUsedPaletteEntries(bpp);  
	dib_size += (dib_size % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - dib_size % FIBITMAP_ALIGNMENT : 0);  
	// pixels are aligned on a 16 bytes boundary
	dib_size += CalculatePitch(CalculateLine(width, bpp)) * height; 

	return dib_size;
}
コード例 #2
0
ファイル: BitmapAccess.cpp プロジェクト: FlyApple/_3rdParty
/**
Calculate the size of a FreeImage image. 
Align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary.
This function includes a protection against malicious images, based on a KISS integer overflow detection mechanism. 

@param header_only If TRUE, calculate a 'header only' FIBITMAP size, otherwise calculate a full FIBITMAP size
@param width Image width
@param height Image height
@param bpp Number of bits-per-pixel
@param need_masks We only store the masks (and allocate memory for them) for 16-bit images of type FIT_BITMAP
@return Returns a size in BYTE units
@see FreeImage_AllocateBitmap
*/
static size_t 
FreeImage_GetInternalImageSize(BOOL header_only, unsigned width, unsigned height, unsigned bpp, BOOL need_masks) {
	size_t dib_size = sizeof(FREEIMAGEHEADER);
	dib_size += (dib_size % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - dib_size % FIBITMAP_ALIGNMENT : 0);
	dib_size += FIBITMAP_ALIGNMENT - sizeof(BITMAPINFOHEADER) % FIBITMAP_ALIGNMENT;
	dib_size += sizeof(BITMAPINFOHEADER);
	// palette is aligned on a 16 bytes boundary
	dib_size += sizeof(RGBQUAD) * CalculateUsedPaletteEntries(bpp);
	// we both add palette size and masks size if need_masks is true, since CalculateUsedPaletteEntries
	// always returns 0 if need_masks is true (which is only true for 16 bit images).
	dib_size += need_masks ? sizeof(DWORD) * 3 : 0;
	dib_size += (dib_size % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - dib_size % FIBITMAP_ALIGNMENT : 0);

	if(!header_only) {
		const size_t header_size = dib_size;

		// pixels are aligned on a 16 bytes boundary
		dib_size += (size_t)CalculatePitch(CalculateLine(width, bpp)) * (size_t)height;

		// check for possible malloc overflow using a KISS integer overflow detection mechanism
		{
			const double dPitch = floor( ((double)bpp * width + 31.0) / 32.0 ) * 4.0;
			const double dImageSize = (double)header_size + dPitch * height;
			if(dImageSize != (double)dib_size) {
				// here, we are sure to encounter a malloc overflow: try to avoid it ...
				return 0;
			}

			/*
			The following constant take into account the additionnal memory used by 
			aligned malloc functions as well as debug malloc functions. 
			It is supposed here that using a (8 * FIBITMAP_ALIGNMENT) risk margin will be enough
			for the target compiler. 
			*/
			const double FIBITMAP_MAX_MEMORY = (double)((size_t)-1) - 8 * FIBITMAP_ALIGNMENT;

			if(dImageSize > FIBITMAP_MAX_MEMORY) {
				// avoid possible overflow inside C allocation functions
				return 0;
			}
		}
	}

	return dib_size;
}
コード例 #3
0
ファイル: PluginBMP.cpp プロジェクト: MichaelH13/sdkpub
static FIBITMAP *
LoadOS21XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset) {
	FIBITMAP *dib = NULL;

	try {
		BITMAPINFOOS2_1X_HEADER bios2_1x;

		io->read_proc(&bios2_1x, sizeof(BITMAPINFOOS2_1X_HEADER), 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
		SwapOS21XHeader(&bios2_1x);
#endif
		// keep some general information about the bitmap

		int used_colors = 0;
		int width       = bios2_1x.biWidth;
		int height      = bios2_1x.biHeight;
		int bit_count   = bios2_1x.biBitCount;
		int pitch       = CalculatePitch(CalculateLine(width, bit_count));
		
		switch (bit_count) {
			case 1 :
			case 4 :
			case 8 :
			{
				used_colors = CalculateUsedPaletteEntries(bit_count);
				
				// allocate enough memory to hold the bitmap (header, palette, pixels) and read the palette

				dib = FreeImage_Allocate(width, height, bit_count);

				if (dib == NULL)
					throw "DIB allocation failed";						

				BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib);
				pInfoHeader->biXPelsPerMeter = 0;
				pInfoHeader->biYPelsPerMeter = 0;
				
				// load the palette

				RGBQUAD *pal = FreeImage_GetPalette(dib);

				for (int count = 0; count < used_colors; count++) {
					FILE_BGR bgr;

					io->read_proc(&bgr, sizeof(FILE_BGR), 1, handle);
					
					pal[count].rgbRed = bgr.r;
					pal[count].rgbGreen = bgr.g;
					pal[count].rgbBlue = bgr.b;
				}

				// Skip over the optional palette 
				// A 24 or 32 bit DIB may contain a palette for faster color reduction

				io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
				
				// read the pixel data

				if (height > 0) {
					io->read_proc((void *)FreeImage_GetBits(dib), height * pitch, 1, handle);
				} else {
					for (int c = 0; c < abs(height); ++c) {
						io->read_proc((void *)FreeImage_GetScanLine(dib, height - c - 1), pitch, 1, handle);								
					}
				}
						
				return dib;
			}

			case 16 :
			{
				dib = FreeImage_Allocate(width, height, bit_count, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK);

				if (dib == NULL)
					throw "DIB allocation failed";						

				BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib);
				pInfoHeader->biXPelsPerMeter = 0;
				pInfoHeader->biYPelsPerMeter = 0;

				io->read_proc(FreeImage_GetBits(dib), height * pitch, 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
				for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
					WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y);
					for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
						SwapShort(pixel);
						pixel++;
					}
				}
#endif

				return dib;
			}

			case 24 :
			case 32 :
			{
				if( bit_count == 32 ) {
					dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
				} else {
					dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
				}

				if (dib == NULL)
					throw "DIB allocation failed";						

				BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib);
				pInfoHeader->biXPelsPerMeter = 0;
				pInfoHeader->biYPelsPerMeter = 0;

				// Skip over the optional palette 
				// A 24 or 32 bit DIB may contain a palette for faster color reduction

				io->read_proc(FreeImage_GetBits(dib), height * pitch, 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
				for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
					BYTE *pixel = FreeImage_GetScanLine(dib, y);
					for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
						INPLACESWAP(pixel[0], pixel[2]);
						pixel += (bit_count>>3);
					}
				}
#endif

				// check if the bitmap contains transparency, if so enable it in the header

				FreeImage_SetTransparent(dib, (FreeImage_GetColorType(dib) == FIC_RGBALPHA));

				return dib;
			}
		}
	} catch(const char *message) {	
		if(dib)
			FreeImage_Unload(dib);

		FreeImage_OutputMessageProc(s_format_id, message);
	}

	return NULL;
}
コード例 #4
0
ファイル: PluginBMP.cpp プロジェクト: MichaelH13/sdkpub
static FIBITMAP *
LoadOS22XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset) {
	FIBITMAP *dib = NULL;

	try {
		// load the info header

		BITMAPINFOHEADER bih;

		io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
		SwapInfoHeader(&bih);
#endif

		// keep some general information about the bitmap

		int used_colors = bih.biClrUsed;
		int width       = bih.biWidth;
		int height      = bih.biHeight;
		int bit_count   = bih.biBitCount;
		int compression = bih.biCompression;
		int pitch       = CalculatePitch(CalculateLine(width, bit_count));
		
		switch (bit_count) {
			case 1 :
			case 4 :
			case 8 :
			{
				if ((used_colors <= 0) || (used_colors > CalculateUsedPaletteEntries(bit_count)))
					used_colors = CalculateUsedPaletteEntries(bit_count);
					
				// allocate enough memory to hold the bitmap (header, palette, pixels) and read the palette

				dib = FreeImage_Allocate(width, height, bit_count);

				if (dib == NULL)
					throw "DIB allocation failed";

				BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib);
				pInfoHeader->biXPelsPerMeter = bih.biXPelsPerMeter;
				pInfoHeader->biYPelsPerMeter = bih.biYPelsPerMeter;
				
				// load the palette

				io->seek_proc(handle, sizeof(BITMAPFILEHEADER) + bih.biSize, SEEK_SET);

				RGBQUAD *pal = FreeImage_GetPalette(dib);

				for (int count = 0; count < used_colors; count++) {
					FILE_BGR bgr;

					io->read_proc(&bgr, sizeof(FILE_BGR), 1, handle);
					
					pal[count].rgbRed = bgr.r;
					pal[count].rgbGreen = bgr.g;
					pal[count].rgbBlue = bgr.b;
				}

				// seek to the actual pixel data.
				// this is needed because sometimes the palette is larger than the entries it contains predicts

				if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3)))
					io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);

				// read the pixel data

				switch (compression) {
					case BI_RGB :
						if (height > 0) {
							io->read_proc((void *)FreeImage_GetBits(dib), height * pitch, 1, handle);
						} else {
							for (int c = 0; c < abs(height); ++c) {
								io->read_proc((void *)FreeImage_GetScanLine(dib, height - c - 1), pitch, 1, handle);								
							}
						}
						
						return dib;

					case BI_RLE4 :
					{
						BYTE status_byte = 0;
						BYTE second_byte = 0;
						int scanline = 0;
						int bits = 0;
						BOOL low_nibble = FALSE;

						for (;;) {
							io->read_proc(&status_byte, sizeof(BYTE), 1, handle);

							switch (status_byte) {
								case RLE_COMMAND :
									io->read_proc(&status_byte, sizeof(BYTE), 1, handle);

									switch (status_byte) {
										case RLE_ENDOFLINE :
											bits = 0;
											scanline++;
											low_nibble = FALSE;
											break;

										case RLE_ENDOFBITMAP :
											return (FIBITMAP *)dib;

										case RLE_DELTA :
										{
											// read the delta values

											BYTE delta_x;
											BYTE delta_y;

											io->read_proc(&delta_x, sizeof(BYTE), 1, handle);
											io->read_proc(&delta_y, sizeof(BYTE), 1, handle);

											// apply them

											bits       += delta_x / 2;
											scanline   += delta_y;
											break;
										}

										default :
											io->read_proc(&second_byte, sizeof(BYTE), 1, handle);

											BYTE *sline = FreeImage_GetScanLine(dib, scanline);

											for (int i = 0; i < status_byte; i++) {
												if (low_nibble) {
													*(sline + bits) |= LOWNIBBLE(second_byte);

													if (i != status_byte - 1)
														io->read_proc(&second_byte, sizeof(BYTE), 1, handle);

													bits++;
												} else {
													*(sline + bits) |= HINIBBLE(second_byte);
												}
												
												low_nibble = !low_nibble;
											}

											if (((status_byte / 2) & 1 ) == 1)
												io->read_proc(&second_byte, sizeof(BYTE), 1, handle);												

											break;
									};

									break;

								default :
								{
									BYTE *sline = FreeImage_GetScanLine(dib, scanline);

									io->read_proc(&second_byte, sizeof(BYTE), 1, handle);

									for (unsigned i = 0; i < status_byte; i++) {
										if (low_nibble) {
											*(sline + bits) |= LOWNIBBLE(second_byte);

											bits++;
										} else {
											*(sline + bits) |= HINIBBLE(second_byte);
										}				
										
										low_nibble = !low_nibble;
									}
								}

								break;
							};
						}

						break;
					}

					case BI_RLE8 :
					{
						BYTE status_byte = 0;
						BYTE second_byte = 0;
						int scanline = 0;
						int bits = 0;

						for (;;) {
							io->read_proc(&status_byte, sizeof(BYTE), 1, handle);

							switch (status_byte) {
								case RLE_COMMAND :
									io->read_proc(&status_byte, sizeof(BYTE), 1, handle);

									switch (status_byte) {
										case RLE_ENDOFLINE :
											bits = 0;
											scanline++;
											break;

										case RLE_ENDOFBITMAP :
											return (FIBITMAP *)dib;

										case RLE_DELTA :
										{
											// read the delta values

											BYTE delta_x;
											BYTE delta_y;

											io->read_proc(&delta_x, sizeof(BYTE), 1, handle);
											io->read_proc(&delta_y, sizeof(BYTE), 1, handle);

											// apply them

											bits     += delta_x;
											scanline += delta_y;
											break;
										}

										default :
											io->read_proc((void *)(FreeImage_GetScanLine(dib, scanline) + bits), sizeof(BYTE) * status_byte, 1, handle);
											
											// align run length to even number of bytes 

											if ((status_byte & 1) == 1)
												io->read_proc(&second_byte, sizeof(BYTE), 1, handle);												

											bits += status_byte;

											break;								
									};

									break;

								default :
									BYTE *sline = FreeImage_GetScanLine(dib, scanline);

									io->read_proc(&second_byte, sizeof(BYTE), 1, handle);

									for (unsigned i = 0; i < status_byte; i++) {
										*(sline + bits) = second_byte;

										bits++;
									}

									break;
							};
						}

						break;
					}

					default :		
						throw "compression type not supported";
				}						

				break;
			}

			case 16 :
			{
				if (bih.biCompression == 3) {
					DWORD bitfields[3];

					io->read_proc(bitfields, 3 * sizeof(DWORD), 1, handle);

					dib = FreeImage_Allocate(width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]);
				} else {
					dib = FreeImage_Allocate(width, height, bit_count, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK);
				}

				if (dib == NULL)
					throw "DIB allocation failed";						

				BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib);
				pInfoHeader->biXPelsPerMeter = bih.biXPelsPerMeter;
				pInfoHeader->biYPelsPerMeter = bih.biYPelsPerMeter;

				if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3)))
					io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);

				io->read_proc(FreeImage_GetBits(dib), height * pitch, 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
				for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
					WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y);
					for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
						SwapShort(pixel);
						pixel++;
					}
				}
#endif
				return dib;
			}

			case 24 :
			case 32 :
			{
				if( bit_count == 32 ) {
					dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
				} else {
					dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
				}

				if (dib == NULL)
					throw "DIB allocation failed";
				
				BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib);
				pInfoHeader->biXPelsPerMeter = bih.biXPelsPerMeter;
				pInfoHeader->biYPelsPerMeter = bih.biYPelsPerMeter;

				// Skip over the optional palette 
				// A 24 or 32 bit DIB may contain a palette for faster color reduction

				if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3)))
					io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
				
				// read in the bitmap bits

				io->read_proc(FreeImage_GetBits(dib), height * pitch, 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
				for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
					BYTE *pixel = FreeImage_GetScanLine(dib, y);
					for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
						INPLACESWAP(pixel[0], pixel[2]);
						pixel += (bit_count>>3);
					}
				}
#endif

				// check if the bitmap contains transparency, if so enable it in the header

				FreeImage_SetTransparent(dib, (FreeImage_GetColorType(dib) == FIC_RGBALPHA));

				return dib;
			}
		}
	} catch(const char *message) {
		if(dib)
			FreeImage_Unload(dib);

		FreeImage_OutputMessageProc(s_format_id, message);
	}

	return NULL;
}
コード例 #5
0
FIBITMAP * DLL_CALLCONV
FreeImage_AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
	FIBITMAP *bitmap = (FIBITMAP *)malloc(sizeof(FIBITMAP));

	if (bitmap != NULL) {
		height = abs(height);

		// check pixel bit depth
		switch(type) {
			case FIT_BITMAP:
				switch(bpp) {
					case 1:
					case 4:
					case 8:
					case 16:
					case 24:
					case 32:
						break;
					default:
						bpp = 8;
						break;
				}
				break;
			case FIT_UINT16:
				bpp = 8 * sizeof(unsigned short);
				break;
			case FIT_INT16:
				bpp = 8 * sizeof(short);
				break;
			case FIT_UINT32:
				bpp = 8 * sizeof(unsigned long);
				break;
			case FIT_INT32:
				bpp = 8 * sizeof(long);
				break;
			case FIT_FLOAT:
				bpp = 8 * sizeof(float);
				break;
			case FIT_DOUBLE:
				bpp = 8 * sizeof(double);
				break;
			case FIT_COMPLEX:
				bpp = 8 * sizeof(FICOMPLEX);
				break;
			case FIT_RGB16:
				bpp = 8 * sizeof(FIRGB16);
				break;
			case FIT_RGBA16:
				bpp = 8 * sizeof(FIRGBA16);
				break;
			case FIT_RGBF:
				bpp = 8 * sizeof(FIRGBF);
				break;
			case FIT_RGBAF:
				bpp = 8 * sizeof(FIRGBAF);
				break;
			default:
				free(bitmap);
				return NULL;
		}

		// calculate the size of a FreeImage 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

		unsigned dib_size = FreeImage_GetImageSize(width, height, bpp); 

		bitmap->data = (BYTE *)FreeImage_Aligned_Malloc(dib_size * sizeof(BYTE), FIBITMAP_ALIGNMENT);

		if (bitmap->data != NULL) {
			memset(bitmap->data, 0, dib_size);

			// write out the FREEIMAGEHEADER

			FREEIMAGEHEADER *fih    = (FREEIMAGEHEADER *)bitmap->data;
			fih->type				= type;

			fih->red_mask           = red_mask;
			fih->green_mask         = green_mask;
			fih->blue_mask          = blue_mask;

			memset(&fih->bkgnd_color, 0, sizeof(RGBQUAD));

			fih->transparent        = FALSE;
			fih->transparency_count = 0;
			memset(fih->transparent_table, 0xff, 256);

			// initialize FIICCPROFILE link

			FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(bitmap);
			iccProfile->size		= 0;
			iccProfile->data		= 0;
			iccProfile->flags		= 0;

			// initialize metadata models list

			fih->metadata = new METADATAMAP;

			// write out the BITMAPINFOHEADER

			BITMAPINFOHEADER *bih   = FreeImage_GetInfoHeader(bitmap);
			bih->biSize             = sizeof(BITMAPINFOHEADER);
			bih->biWidth            = width;
			bih->biHeight           = height;
			bih->biPlanes           = 1;
			bih->biCompression      = 0;
			bih->biBitCount         = bpp;
			bih->biClrUsed          = CalculateUsedPaletteEntries(bpp);
			bih->biClrImportant     = bih->biClrUsed;

			return bitmap;
		}

		free(bitmap);
	}

	return NULL;
}
コード例 #6
0
ファイル: BitmapAccess.cpp プロジェクト: 2php/ogre-android
FIBITMAP * DLL_CALLCONV
FreeImage_AllocateHeaderT(BOOL header_only, FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
	FIBITMAP *bitmap = (FIBITMAP *)malloc(sizeof(FIBITMAP));

	if (bitmap != NULL) {
		width = abs(width);
		height = abs(height);

		// check pixel bit depth
		switch(type) {
			case FIT_BITMAP:
				switch(bpp) {
					case 1:
					case 4:
					case 8:
					case 16:
					case 24:
					case 32:
						break;
					default:
						bpp = 8;
						break;
				}
				break;
			case FIT_UINT16:
				bpp = 8 * sizeof(unsigned short);
				break;
			case FIT_INT16:
				bpp = 8 * sizeof(short);
				break;
			case FIT_UINT32:
				bpp = 8 * sizeof(DWORD);
				break;
			case FIT_INT32:
				bpp = 8 * sizeof(LONG);
				break;
			case FIT_FLOAT:
				bpp = 8 * sizeof(float);
				break;
			case FIT_DOUBLE:
				bpp = 8 * sizeof(double);
				break;
			case FIT_COMPLEX:
				bpp = 8 * sizeof(FICOMPLEX);
				break;
			case FIT_RGB16:
				bpp = 8 * sizeof(FIRGB16);
				break;
			case FIT_RGBA16:
				bpp = 8 * sizeof(FIRGBA16);
				break;
			case FIT_RGBF:
				bpp = 8 * sizeof(FIRGBF);
				break;
			case FIT_RGBAF:
				bpp = 8 * sizeof(FIRGBAF);
				break;
			default:
				free(bitmap);
				return NULL;
		}

		// calculate the size of a FreeImage 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

		size_t dib_size = FreeImage_GetImageSizeHeader(header_only, width, height, bpp); 

		if(dib_size == 0) {
			// memory allocation will fail (probably a malloc overflow)
			free(bitmap);
			return NULL;
		}

		bitmap->data = (BYTE *)FreeImage_Aligned_Malloc(dib_size * sizeof(BYTE), FIBITMAP_ALIGNMENT);

		if (bitmap->data != NULL) {
			memset(bitmap->data, 0, dib_size);

			// write out the FREEIMAGEHEADER

			FREEIMAGEHEADER *fih    = (FREEIMAGEHEADER *)bitmap->data;
			fih->type				= type;

			fih->red_mask           = red_mask;
			fih->green_mask         = green_mask;
			fih->blue_mask          = blue_mask;

			memset(&fih->bkgnd_color, 0, sizeof(RGBQUAD));

			fih->transparent        = FALSE;
			fih->transparency_count = 0;
			memset(fih->transparent_table, 0xff, 256);

			fih->has_pixels = header_only ? FALSE : TRUE;

			// initialize FIICCPROFILE link

			FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(bitmap);
			iccProfile->size		= 0;
			iccProfile->data		= 0;
			iccProfile->flags		= 0;

			// initialize metadata models list

			fih->metadata = new(std::nothrow) METADATAMAP;

			// initialize attached thumbnail

			fih->thumbnail = NULL;

			// write out the BITMAPINFOHEADER

			BITMAPINFOHEADER *bih   = FreeImage_GetInfoHeader(bitmap);
			bih->biSize             = sizeof(BITMAPINFOHEADER);
			bih->biWidth            = width;
			bih->biHeight           = height;
			bih->biPlanes           = 1;
			bih->biCompression      = 0;
			bih->biBitCount         = (WORD)bpp;
			bih->biClrUsed          = CalculateUsedPaletteEntries(bpp);
			bih->biClrImportant     = bih->biClrUsed;
			bih->biXPelsPerMeter	= 2835;	// 72 dpi
			bih->biYPelsPerMeter	= 2835;	// 72 dpi

			if(bpp == 8) {
				// build a default greyscale palette (very useful for image processing)
				RGBQUAD *pal = FreeImage_GetPalette(bitmap);
				for(int i = 0; i < 256; i++) {
					pal[i].rgbRed	= (BYTE)i;
					pal[i].rgbGreen = (BYTE)i;
					pal[i].rgbBlue	= (BYTE)i;
				}
			}

			return bitmap;
		}

		free(bitmap);
	}

	return NULL;
}
コード例 #7
0
ファイル: BitmapAccess.cpp プロジェクト: FlyApple/_3rdParty
/**
Internal FIBITMAP allocation.

This function accepts (ext_bits, ext_pitch) arguments. If these are provided the FIBITMAP 
will be allocated as "header only", but bits and pitch will be stored within the FREEIMAGEHEADER 
and the resulting FIBITMAP will have pixels, i.e. HasPixels() will return TRUE.
- GetBits() and GetPitch return the correct values - either offsets or the stored values (user-provided bits and pitch).
- Clone() creates a new FIBITMAP with copy of the user pixel data.
- Unload's implementation does not need to change - it just release a "header only" dib.
Note that when using external data, the data does not need to have the same alignment as the default 4-byte alignment. 
This enables the possibility to access buffers with, for instance, stricter alignment,
like the ones used in low-level APIs like OpenCL or intrinsics.

@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP
@param ext_bits Pointer to external user's pixel buffer if using wrapped buffer, NULL otherwise
@param ext_pitch Pointer to external user's pixel buffer pitch if using wrapped buffer, 0 otherwise
@param type Image type
@param width Image width
@param height Image height
@param bpp Number of bits per pixel
@param red_mask Image red mask 
@param green_mask Image green mask
@param blue_mask Image blue mask
@return Returns the allocated FIBITMAP if successful, returns NULL otherwise
*/
static FIBITMAP * 
FreeImage_AllocateBitmap(BOOL header_only, BYTE *ext_bits, unsigned ext_pitch, FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {

	// check input variables
	width = abs(width);
	height = abs(height);
	if(!((width > 0) && (height > 0))) {
		return NULL;
	}
	if(ext_bits) {
		if(ext_pitch == 0) {
			return NULL;
		}
		assert(header_only == FALSE);
	}

	// we only store the masks (and allocate memory for them) for 16-bit images of type FIT_BITMAP
	BOOL need_masks = FALSE;

	// check pixel bit depth
	switch(type) {
		case FIT_BITMAP:
			switch(bpp) {
				case 1:
				case 4:
				case 8:
					break;
				case 16:
					need_masks = TRUE;
					break;
				case 24:
				case 32:
					break;
				default:
					bpp = 8;
					break;
			}
			break;
		case FIT_UINT16:
			bpp = 8 * sizeof(unsigned short);
			break;
		case FIT_INT16:
			bpp = 8 * sizeof(short);
			break;
		case FIT_UINT32:
			bpp = 8 * sizeof(DWORD);
			break;
		case FIT_INT32:
			bpp = 8 * sizeof(LONG);
			break;
		case FIT_FLOAT:
			bpp = 8 * sizeof(float);
			break;
		case FIT_DOUBLE:
			bpp = 8 * sizeof(double);
			break;
		case FIT_COMPLEX:
			bpp = 8 * sizeof(FICOMPLEX);
			break;
		case FIT_RGB16:
			bpp = 8 * sizeof(FIRGB16);
			break;
		case FIT_RGBA16:
			bpp = 8 * sizeof(FIRGBA16);
			break;
		case FIT_RGBF:
			bpp = 8 * sizeof(FIRGBF);
			break;
		case FIT_RGBAF:
			bpp = 8 * sizeof(FIRGBAF);
			break;
		default:
			return NULL;
	}

	FIBITMAP *bitmap = (FIBITMAP *)malloc(sizeof(FIBITMAP));

	if (bitmap != NULL) {

		// calculate the size of a FreeImage 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' allocation

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

		if(dib_size == 0) {
			// memory allocation will fail (probably a malloc overflow)
			free(bitmap);
			return NULL;
		}

		bitmap->data = (BYTE *)FreeImage_Aligned_Malloc(dib_size * sizeof(BYTE), FIBITMAP_ALIGNMENT);

		if (bitmap->data != NULL) {
			memset(bitmap->data, 0, dib_size);

			// write out the FREEIMAGEHEADER

			FREEIMAGEHEADER *fih = (FREEIMAGEHEADER *)bitmap->data;

			fih->type = type;

			memset(&fih->bkgnd_color, 0, sizeof(RGBQUAD));

			fih->transparent = FALSE;
			fih->transparency_count = 0;
			memset(fih->transparent_table, 0xff, 256);

			fih->has_pixels = header_only ? FALSE : TRUE;

			// initialize FIICCPROFILE link

			FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(bitmap);
			iccProfile->size = 0;
			iccProfile->data = 0;
			iccProfile->flags = 0;

			// initialize metadata models list

			fih->metadata = new(std::nothrow) METADATAMAP;

			// initialize attached thumbnail

			fih->thumbnail = NULL;

			// store a pointer to user provided pixel buffer (if any)

			fih->external_bits = ext_bits;
			fih->external_pitch = ext_pitch;

			// write out the BITMAPINFOHEADER

			BITMAPINFOHEADER *bih   = FreeImage_GetInfoHeader(bitmap);
			bih->biSize             = sizeof(BITMAPINFOHEADER);
			bih->biWidth            = width;
			bih->biHeight           = height;
			bih->biPlanes           = 1;
			bih->biCompression      = need_masks ? BI_BITFIELDS : BI_RGB;
			bih->biBitCount         = (WORD)bpp;
			bih->biClrUsed          = CalculateUsedPaletteEntries(bpp);
			bih->biClrImportant     = bih->biClrUsed;
			bih->biXPelsPerMeter	= 2835;	// 72 dpi
			bih->biYPelsPerMeter	= 2835;	// 72 dpi

			if(bpp == 8) {
				// build a default greyscale palette (very useful for image processing)
				RGBQUAD *pal = FreeImage_GetPalette(bitmap);
				for(int i = 0; i < 256; i++) {
					pal[i].rgbRed	= (BYTE)i;
					pal[i].rgbGreen = (BYTE)i;
					pal[i].rgbBlue	= (BYTE)i;
				}
			}

			// just setting the masks (only if needed) just like the palette.
			if (need_masks) {
				FREEIMAGERGBMASKS *masks = FreeImage_GetRGBMasks(bitmap);
				masks->red_mask = red_mask;
				masks->green_mask = green_mask;
				masks->blue_mask = blue_mask;
			}

			return bitmap;
		}

		free(bitmap);
	}

	return NULL;
}