Пример #1
0
/**
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;
}
Пример #2
0
unsigned DLL_CALLCONV
FreeImage_GetMemorySize(FIBITMAP *dib) {
	if (!dib) {
		return 0;
	}
	FREEIMAGEHEADER *header = (FREEIMAGEHEADER *)dib->data;
	BITMAPINFOHEADER *bih = FreeImage_GetInfoHeader(dib);

	BOOL header_only = !header->has_pixels || header->external_bits != NULL;
	BOOL need_masks = bih->biCompression == BI_BITFIELDS;
	unsigned width = bih->biWidth;
	unsigned height = bih->biHeight;
	unsigned bpp = bih->biBitCount;
	
	// start off with the size of the FIBITMAP structure
	size_t size = sizeof(FIBITMAP);
	
	// add sizes of FREEIMAGEHEADER, BITMAPINFOHEADER, palette and DIB data
	size += FreeImage_GetInternalImageSize(header_only, width, height, bpp, need_masks);

	// add ICC profile size
	size += header->iccProfile.size;

	// add thumbnail image size
	if (header->thumbnail) {
		// we assume a thumbnail not having a thumbnail as well, 
		// so this recursive call should not create an infinite loop
		size += FreeImage_GetMemorySize(header->thumbnail);
	}

	// add metadata size
	METADATAMAP *md = header->metadata;
	if (!md) {
		return (unsigned)size;
	}

	// add size of METADATAMAP
	size += sizeof(METADATAMAP);

	const size_t models = md->size();
	if (models == 0) {
		return (unsigned)size;
	}

	unsigned tags = 0;

	for (METADATAMAP::iterator i = md->begin(); i != md->end(); i++) {
		TAGMAP *tm = i->second;
		if (tm) {
			for (TAGMAP::iterator j = tm->begin(); j != tm->end(); j++) {
				++tags;
				const std::string & key = j->first;
				size += key.capacity();
				size += FreeImage_GetTagMemorySize(j->second);
			}
		}
	}

	// add size of all TAGMAP instances
	size += models * sizeof(TAGMAP);
	// add size of tree nodes in METADATAMAP
	size += MapIntrospector<METADATAMAP>::GetNodesMemorySize(models);
	// add size of tree nodes in TAGMAP
	size += MapIntrospector<TAGMAP>::GetNodesMemorySize(tags);

	return (unsigned)size;
}
Пример #3
0
/**
Helper for 16-bit FIT_BITMAP
Returns a pointer to the bitmap's red-, green- and blue masks.
@param dib The bitmap to obtain masks from.
@return Returns a pointer to the bitmap's red-, green- and blue masks
or NULL, if no masks are present (e.g. for 24 bit images).
*/
static FREEIMAGERGBMASKS *
FreeImage_GetRGBMasks(FIBITMAP *dib) {
	return FreeImage_HasRGBMasks(dib) ? (FREEIMAGERGBMASKS *)(((BYTE *)FreeImage_GetInfoHeader(dib)) + sizeof(BITMAPINFOHEADER)) : NULL;
}
Пример #4
0
void DLL_CALLCONV
FreeImage_SetDotsPerMeterY(FIBITMAP *dib, unsigned res) {
	if(dib) {
		FreeImage_GetInfoHeader(dib)->biYPelsPerMeter = res;
	}
}
Пример #5
0
BITMAPINFO * DLL_CALLCONV
FreeImage_GetInfo(FIBITMAP *dib) {
	return (BITMAPINFO *)FreeImage_GetInfoHeader(dib);
}
Пример #6
0
RGBQUAD * DLL_CALLCONV
FreeImage_GetPalette(FIBITMAP *dib) {
	return (dib && FreeImage_GetBPP(dib) < 16) ? (RGBQUAD *)(((BYTE *)FreeImage_GetInfoHeader(dib)) + sizeof(BITMAPINFOHEADER)) : NULL;
}
Пример #7
0
unsigned DLL_CALLCONV
FreeImage_GetDotsPerMeterY(FIBITMAP *dib) {
	return (dib) ? FreeImage_GetInfoHeader(dib)->biYPelsPerMeter : 0;
}
Пример #8
0
unsigned DLL_CALLCONV
FreeImage_GetBPP(FIBITMAP *dib) {
	return dib ? FreeImage_GetInfoHeader(dib)->biBitCount : 0;
}
Пример #9
0
unsigned DLL_CALLCONV
FreeImage_GetColorsUsed(FIBITMAP *dib) {
	return dib ? FreeImage_GetInfoHeader(dib)->biClrUsed : 0;
}
Пример #10
0
unsigned DLL_CALLCONV
FreeImage_GetHeight(FIBITMAP *dib) {
	return (dib) ? FreeImage_GetInfoHeader(dib)->biHeight : 0;
}
Пример #11
0
unsigned DLL_CALLCONV
FreeImage_GetWidth(FIBITMAP *dib) {
	return dib ? FreeImage_GetInfoHeader(dib)->biWidth : 0;
}
Пример #12
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         = (WORD)bpp;
			bih->biClrUsed          = CalculateUsedPaletteEntries(bpp);
			bih->biClrImportant     = bih->biClrUsed;
			bih->biXPelsPerMeter	= 2835;	// 72 dpi
			bih->biYPelsPerMeter	= 2835;	// 72 dpi

			return bitmap;
		}

		free(bitmap);
	}

	return NULL;
}
Пример #13
0
	int getPlanes() const {
		AlloTy type = getDataType();
		BITMAPINFOHEADER * hdr = FreeImage_GetInfoHeader(mImage);
		return (hdr->biBitCount)/(8*allo_type_size(type));
	}
Пример #14
0
BOOL fipWinImage::copyFromHandle(HANDLE hMem) {
	BYTE *lpVoid = NULL;
	BITMAPINFOHEADER *pHead = NULL;
	RGBQUAD *pPalette = NULL;
	BYTE *bits = NULL;
	DWORD bitfields[3] = {0, 0, 0};

	// Get a pointer to the bitmap
	lpVoid = (BYTE *)GlobalLock(hMem);

	// Get a pointer to the bitmap header
	pHead = (BITMAPINFOHEADER *)lpVoid;

	// Get a pointer to the palette
	if(pHead->biBitCount < 16)
		pPalette = (RGBQUAD *)(((BYTE *)pHead) + sizeof(BITMAPINFOHEADER));

	// Get a pointer to the pixels
	bits = ((BYTE*)pHead + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pHead->biClrUsed);

	if(pHead->biCompression == BI_BITFIELDS) {
		// Take into account the color masks that specify the red, green, and blue components (16- and 32-bit)
		unsigned mask_size = 3 * sizeof(DWORD);
		memcpy(&bitfields[0], bits, mask_size);
		bits += mask_size;
	} 

	if(lpVoid) {

		// Allocate a new FIBITMAP

		FREE_IMAGE_TYPE image_type = FIT_BITMAP;
		// Use a hack to decide if the clipboard contains non standard bitmaps ...
		switch(GET_FREEIMAGE_MARKER(pHead)) {
			case FIT_UINT16:
			case FIT_INT16:
			case FIT_UINT32:
			case FIT_INT32:
			case FIT_FLOAT:
			case FIT_DOUBLE:
			case FIT_COMPLEX:
			case FIT_RGB16:
			case FIT_RGBA16:
			case FIT_RGBF:
			case FIT_RGBAF:
				image_type = GET_FREEIMAGE_MARKER(pHead);
				break;
		}
		if(!setSize(image_type, (WORD)pHead->biWidth, (WORD)pHead->biHeight, pHead->biBitCount, bitfields[2], bitfields[1], bitfields[0])) {
			GlobalUnlock(lpVoid);
			return FALSE;
		}

		// Copy the bitmap header
		memcpy(FreeImage_GetInfoHeader(_dib), pHead, sizeof(BITMAPINFOHEADER));


		// Copy the palette
		memcpy(FreeImage_GetPalette(_dib), pPalette, pHead->biClrUsed * sizeof(RGBQUAD));

		// Copy the bitmap
		memcpy(FreeImage_GetBits(_dib), bits, FreeImage_GetPitch(_dib) * FreeImage_GetHeight(_dib));

		GlobalUnlock(lpVoid);

		return TRUE;
	}

	return FALSE;
}