Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/BitmapAccess.cpp view on Meta::CPAN
void* mem_real = malloc(amount + 2 * alignment);
if(!mem_real) return NULL;
char* mem_align = (char*)((unsigned long)(2 * alignment - (unsigned long)mem_real % (unsigned long)alignment) + (unsigned long)mem_real);
*((long*)mem_align - 1) = (long)mem_real;
return mem_align;
}
void FreeImage_Aligned_Free(void* mem) {
free((void*)*((long*)mem - 1));
}
#endif // _WIN32 || _WIN64
// ----------------------------------------------------------
// FIBITMAP memory management
// ----------------------------------------------------------
/**
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;
}
/**
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;
}
/**
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;
( run in 0.778 second using v1.01-cache-2.11-cpan-796a6f069b2 )