Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginTARGA.cpp view on Meta::CPAN
if(header.is_width == 0 || header.is_height == 0) {
return FALSE;
}
// let's now verify all the types that are supported by FreeImage (this is our final verification)
switch(header.image_type) {
case TGA_CMAP:
case TGA_RGB:
case TGA_MONO:
case TGA_RLECMAP:
case TGA_RLERGB:
case TGA_RLEMONO:
switch(header.is_pixel_depth) {
case 8 :
case 16:
case 24:
case 32:
return TRUE;
default:
return FALSE;
}
break;
default:
return FALSE;
}
}
}
static BOOL DLL_CALLCONV
SupportsExportDepth(int depth) {
return (
(depth == 8) ||
(depth == 16) ||
(depth == 24) ||
(depth == 32)
);
}
static BOOL DLL_CALLCONV
SupportsExportType(FREE_IMAGE_TYPE type) {
return (type == FIT_BITMAP) ? TRUE : FALSE;
}
static BOOL DLL_CALLCONV
SupportsNoPixels() {
return TRUE;
}
// ----------------------------------------------------------
/**
Used for all 32 and 24 bit loading of uncompressed images
*/
static void
loadTrueColor(FIBITMAP* dib, int width, int height, int file_pixel_size, FreeImageIO* io, fi_handle handle, BOOL as24bit) {
const int pixel_size = as24bit ? 3 : file_pixel_size;
// input line cache
BYTE* file_line = (BYTE*)malloc( width * file_pixel_size);
if (!file_line) {
throw FI_MSG_ERROR_MEMORY;
}
for (int y = 0; y < height; y++) {
BYTE *bits = FreeImage_GetScanLine(dib, y);
io->read_proc(file_line, file_pixel_size, width, handle);
BYTE *bgra = file_line;
for (int x = 0; x < width; x++) {
bits[FI_RGBA_BLUE] = bgra[0];
bits[FI_RGBA_GREEN] = bgra[1];
bits[FI_RGBA_RED] = bgra[2];
if (!as24bit) {
bits[FI_RGBA_ALPHA] = bgra[3];
}
bgra += file_pixel_size;
bits += pixel_size;
}
}
free(file_line);
}
/**
For the generic RLE loader we need to abstract away the pixel format.
We use a specific overload based on bits-per-pixel for each type of pixel
*/
template <int nBITS>
inline static void
_assignPixel(BYTE* bits, BYTE* val, BOOL as24bit = FALSE) {
// static assert should go here
assert(FALSE);
}
template <>
inline void
_assignPixel<8>(BYTE* bits, BYTE* val, BOOL as24bit) {
*bits = *val;
}
template <>
inline void
_assignPixel<16>(BYTE* bits, BYTE* val, BOOL as24bit) {
WORD value(*reinterpret_cast<WORD*>(val));
#ifdef FREEIMAGE_BIGENDIAN
SwapShort(&value);
#endif
if (as24bit) {
bits[FI_RGBA_BLUE] = (BYTE)((((value & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
bits[FI_RGBA_GREEN] = (BYTE)((((value & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F);
bits[FI_RGBA_RED] = (BYTE)((((value & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
} else {
*reinterpret_cast<WORD *>(bits) = 0x7FFF & value;
src/Source/FreeImage/PluginTARGA.cpp view on Meta::CPAN
// read and process the bitmap's footer
TargaThumbnail thumbnail;
if(isTARGA20(io, handle)) {
TGAFOOTER footer;
const long footer_offset = start_offset + eof - sizeof(footer);
io->seek_proc(handle, footer_offset, SEEK_SET);
io->read_proc(&footer, sizeof(tagTGAFOOTER), 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
SwapFooter(&footer);
#endif
BOOL hasExtensionArea = footer.extension_offset > 0;
if(hasExtensionArea) {
TGAEXTENSIONAREA extensionarea;
io->seek_proc(handle, footer.extension_offset, SEEK_SET);
io->read_proc(&extensionarea, sizeof(extensionarea), 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
SwapExtensionArea(&extensionarea);
#endif
DWORD postage_stamp_offset = extensionarea.postage_stamp_offset;
BOOL hasThumbnail = (postage_stamp_offset > 0) && (postage_stamp_offset < (DWORD)footer_offset);
if(hasThumbnail) {
io->seek_proc(handle, postage_stamp_offset, SEEK_SET);
thumbnail.read(io, handle, footer_offset - postage_stamp_offset);
}
}
}
// read and process the bitmap's header
TGAHEADER header;
io->seek_proc(handle, start_offset, SEEK_SET);
io->read_proc(&header, sizeof(tagTGAHEADER), 1, handle);
#ifdef FREEIMAGE_BIGENDIAN
SwapHeader(&header);
#endif
thumbnail.setDepth(header.is_pixel_depth);
const int line = CalculateLine(header.is_width, header.is_pixel_depth);
const int pixel_bits = header.is_pixel_depth;
const int pixel_size = pixel_bits/8;
int fliphoriz = (header.is_image_descriptor & 0x10) ? 1 : 0;
int flipvert = (header.is_image_descriptor & 0x20) ? 1 : 0;
// skip comment
io->seek_proc(handle, header.id_length, SEEK_CUR);
switch (header.is_pixel_depth) {
case 8 : {
dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, 8);
if (dib == NULL) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
// read the palette (even if header only)
RGBQUAD *palette = FreeImage_GetPalette(dib);
if (header.color_map_type > 0) {
unsigned count, csize;
// calculate the color map size
csize = header.cm_length * header.cm_size / 8;
// read the color map
BYTE *cmap = (BYTE*)malloc(csize * sizeof(BYTE));
if (cmap == NULL) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
io->read_proc(cmap, sizeof(BYTE), csize, handle);
// build the palette
switch (header.cm_size) {
case 16: {
WORD *rgb555 = (WORD*)&cmap[0];
unsigned start = (unsigned)header.cm_first_entry;
unsigned stop = MIN((unsigned)256, (unsigned)header.cm_length);
for (count = start; count < stop; count++) {
palette[count].rgbRed = (BYTE)((((*rgb555 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
palette[count].rgbGreen = (BYTE)((((*rgb555 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F);
palette[count].rgbBlue = (BYTE)((((*rgb555 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
rgb555++;
}
}
break;
case 24: {
FILE_BGR *bgr = (FILE_BGR*)&cmap[0];
unsigned start = (unsigned)header.cm_first_entry;
unsigned stop = MIN((unsigned)256, (unsigned)header.cm_length);
for (count = start; count < stop; count++) {
palette[count].rgbBlue = bgr->b;
palette[count].rgbGreen = bgr->g;
palette[count].rgbRed = bgr->r;
bgr++;
}
}
break;
case 32: {
BYTE trns[256];
// clear the transparency table
memset(trns, 0xFF, 256);
FILE_BGRA *bgra = (FILE_BGRA*)&cmap[0];
unsigned start = (unsigned)header.cm_first_entry;
unsigned stop = MIN((unsigned)256, (unsigned)header.cm_length);
for (count = start; count < stop; count++) {
palette[count].rgbBlue = bgra->b;
palette[count].rgbGreen = bgra->g;
palette[count].rgbRed = bgra->r;
// alpha
trns[count] = bgra->a;
bgra++;
}
// set the tranparency table
FreeImage_SetTransparencyTable(dib, trns, 256);
}
break;
} // switch(header.cm_size)
src/Source/FreeImage/PluginTARGA.cpp view on Meta::CPAN
RGBQUAD* dst_pal = FreeImage_GetPalette(th);
if(dst_pal && pal) {
for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++) {
dst_pal[i] = pal[i];
}
}
FreeImage_SetTransparencyTable(th, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib));
FreeImage_SetThumbnail(dib, th);
FreeImage_Unload(th);
}
if(header_only) {
return dib;
}
// read in the bitmap bits
switch (header.image_type) {
case TGA_CMAP:
case TGA_MONO: {
BYTE *bits = NULL;
for (unsigned count = 0; count < header.is_height; count++) {
bits = FreeImage_GetScanLine(dib, count);
io->read_proc(bits, sizeof(BYTE), line, handle);
}
}
break;
case TGA_RLECMAP:
case TGA_RLEMONO: { //(8 bit)
loadRLE<8>(dib, header.is_width, header.is_height, io, handle, eof, FALSE);
}
break;
default :
FreeImage_Unload(dib);
return NULL;
}
}
break; // header.is_pixel_depth == 8
case 15 :
case 16 : {
int pixel_bits = 16;
// allocate the dib
if (TARGA_LOAD_RGB888 & flags) {
pixel_bits = 24;
dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, pixel_bits, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
} else {
dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, pixel_bits, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK);
}
if (dib == NULL) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
// handle thumbnail
FIBITMAP* th = thumbnail.toFIBITMAP();
if(th) {
if(TARGA_LOAD_RGB888 & flags) {
FIBITMAP* t = FreeImage_ConvertTo24Bits(th);
FreeImage_Unload(th);
th = t;
}
FreeImage_SetThumbnail(dib, th);
FreeImage_Unload(th);
}
if(header_only) {
return dib;
}
int line = CalculateLine(header.is_width, pixel_bits);
const unsigned pixel_size = unsigned(pixel_bits) / 8;
const unsigned src_pixel_size = sizeof(WORD);
// note header.cm_size is a misleading name, it should be seen as header.cm_bits
// ignore current position in file and set filepointer explicitly from the beginning of the file
int garblen = 0;
if (header.color_map_type != 0) {
garblen = (int)((header.cm_size + 7) / 8) * header.cm_length; /* should byte align */
} else {
garblen = 0;
}
io->seek_proc(handle, start_offset, SEEK_SET);
io->seek_proc(handle, sizeof(tagTGAHEADER) + header.id_length + garblen, SEEK_SET);
// read in the bitmap bits
switch (header.image_type) {
case TGA_RGB: { //(16 bit)
// input line cache
BYTE *in_line = (BYTE*)malloc(header.is_width * sizeof(WORD));
if (!in_line)
throw FI_MSG_ERROR_MEMORY;
const int h = header.is_height;
for (int y = 0; y < h; y++) {
BYTE *bits = FreeImage_GetScanLine(dib, y);
io->read_proc(in_line, src_pixel_size, header.is_width, handle);
BYTE *val = in_line;
for (int x = 0; x < line; x += pixel_size) {
_assignPixel<16>(bits+x, val, TARGA_LOAD_RGB888 & flags);
val += src_pixel_size;
}
}
free(in_line);
}
break;
case TGA_RLERGB: { //(16 bit)
loadRLE<16>(dib, header.is_width, header.is_height, io, handle, eof, TARGA_LOAD_RGB888 & flags);
}
break;
default :
FreeImage_Unload(dib);
return NULL;
}
}
break; // header.is_pixel_depth == 15 or 16
case 24 : {
dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, pixel_bits, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
if (dib == NULL) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
FIBITMAP* th = thumbnail.toFIBITMAP();
if(th) {
FreeImage_SetThumbnail(dib, th);
FreeImage_Unload(th);
}
if(header_only) {
return dib;
}
// read in the bitmap bits
switch (header.image_type) {
case TGA_RGB: { //(24 bit)
//uncompressed
loadTrueColor(dib, header.is_width, header.is_height, pixel_size,io, handle, TRUE);
}
break;
case TGA_RLERGB: { //(24 bit)
loadRLE<24>(dib, header.is_width, header.is_height, io, handle, eof, TRUE);
}
break;
default :
FreeImage_Unload(dib);
return NULL;
}
}
break; // header.is_pixel_depth == 24
case 32 : {
int pixel_bits = 32;
if (TARGA_LOAD_RGB888 & flags) {
pixel_bits = 24;
}
dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, pixel_bits, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
if (dib == NULL) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
// handle thumbnail
FIBITMAP* th = thumbnail.toFIBITMAP();
if(th) {
if(TARGA_LOAD_RGB888 & flags) {
FIBITMAP* t = FreeImage_ConvertTo24Bits(th);
FreeImage_Unload(th);
th = t;
}
FreeImage_SetThumbnail(dib, th);
FreeImage_Unload(th);
}
if(header_only) {
return dib;
}
// read in the bitmap bits
switch (header.image_type) {
case TGA_RGB: { //(32 bit)
// uncompressed
loadTrueColor(dib, header.is_width, header.is_height, 4 /*file_pixel_size*/, io, handle, TARGA_LOAD_RGB888 & flags);
}
break;
case TGA_RLERGB: { //(32 bit)
loadRLE<32>(dib, header.is_width, header.is_height, io, handle, eof, TARGA_LOAD_RGB888 & flags);
}
break;
default :
FreeImage_Unload(dib);
return NULL;
}
}
break; // header.is_pixel_depth == 32
} // switch(header.is_pixel_depth)
if (flipvert) {
FreeImage_FlipVertical(dib);
}
if (fliphoriz) {
FreeImage_FlipHorizontal(dib);
}
return dib;
} catch (const char *message) {
if (dib) {
FreeImage_Unload(dib);
}
FreeImage_OutputMessageProc(s_format_id, message);
return NULL;
( run in 0.735 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )