Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginPCX.cpp view on Meta::CPAN
the page parameter is always -1.
The fourth parameter (int flags) manipulates the load function to load a bitmap
in a certain way. Every plugin has a different flag parameter with different meanings.
The last parameter (void *data) can contain a special data block used when
the file is read multi-paged. Because not every plugin supports multi-paging
not every plugin will use the data parameter and it will be set to NULL.However,
when the plugin does support multi-paging the parameter contains a pointer to a
block of data allocated by the Open function.
*/
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
FIBITMAP *dib = NULL;
BYTE *bits; // Pointer to dib data
RGBQUAD *pal; // Pointer to dib palette
BYTE *line = NULL; // PCX raster line
BYTE *ReadBuf = NULL; // buffer;
BOOL bIsRLE; // True if the file is run-length encoded
if(!handle) {
return NULL;
}
BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
try {
// check PCX identifier
long start_pos = io->tell_proc(handle);
BOOL validated = pcx_validate(io, handle);
io->seek_proc(handle, start_pos, SEEK_SET);
if(!validated) {
throw FI_MSG_ERROR_MAGIC_NUMBER;
}
// process the header
PCXHEADER header;
if(io->read_proc(&header, sizeof(PCXHEADER), 1, handle) != 1) {
throw FI_MSG_ERROR_PARSING;
}
#ifdef FREEIMAGE_BIGENDIAN
SwapHeader(&header);
#endif
// allocate a new DIB
unsigned width = header.window[2] - header.window[0] + 1;
unsigned height = header.window[3] - header.window[1] + 1;
unsigned bitcount = header.bpp * header.planes;
if (bitcount == 24) {
dib = FreeImage_AllocateHeader(header_only, width, height, bitcount, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
} else {
dib = FreeImage_AllocateHeader(header_only, width, height, bitcount);
}
// if the dib couldn't be allocated, throw an error
if (!dib) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
// metrics handling code
FreeImage_SetDotsPerMeterX(dib, (unsigned) (((float)header.hdpi) / 0.0254000 + 0.5));
FreeImage_SetDotsPerMeterY(dib, (unsigned) (((float)header.vdpi) / 0.0254000 + 0.5));
// Set up the palette if needed
// ----------------------------
switch(bitcount) {
case 1:
{
pal = FreeImage_GetPalette(dib);
pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
break;
}
case 4:
{
pal = FreeImage_GetPalette(dib);
BYTE *pColormap = &header.color_map[0];
for (int i = 0; i < 16; i++) {
pal[i].rgbRed = pColormap[0];
pal[i].rgbGreen = pColormap[1];
pal[i].rgbBlue = pColormap[2];
pColormap += 3;
}
break;
}
case 8:
{
BYTE palette_id;
io->seek_proc(handle, -769L, SEEK_END);
io->read_proc(&palette_id, 1, 1, handle);
if (palette_id == 0x0C) {
BYTE *cmap = (BYTE*)malloc(768 * sizeof(BYTE));
io->read_proc(cmap, 768, 1, handle);
pal = FreeImage_GetPalette(dib);
BYTE *pColormap = &cmap[0];
for(int i = 0; i < 256; i++) {
pal[i].rgbRed = pColormap[0];
pal[i].rgbGreen = pColormap[1];
pal[i].rgbBlue = pColormap[2];
pColormap += 3;
}
free(cmap);
( run in 0.475 second using v1.01-cache-2.11-cpan-5735350b133 )