Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginTARGA.cpp view on Meta::CPAN
WORD is_xorigin; //! X-origin of image (absolute coordinate of lower-left corner for displays where origin is at the lower left)
WORD is_yorigin; //! Y-origin of image (as for X-origin)
WORD is_width; //! image width
WORD is_height; //! image height
BYTE is_pixel_depth; //! bits per pixel
BYTE is_image_descriptor; //! image descriptor, bits 3-0 give the alpha channel depth, bits 5-4 give direction
} TGAHEADER;
typedef struct tagTGAEXTENSIONAREA {
WORD extension_size; // Size in bytes of the extension area, always 495
char author_name[41]; // Name of the author. If not used, bytes should be set to NULL (\0) or spaces
char author_comments[324]; // A comment, organized as four lines, each consisting of 80 characters plus a NULL
WORD datetime_stamp[6]; // Date and time at which the image was created
char job_name[41]; // Job ID
WORD job_time[3]; // Hours, minutes and seconds spent creating the file (for billing, etc.)
char software_id[41]; // The application that created the file
BYTE software_version[3];
DWORD key_color;
WORD pixel_aspect_ratio[2];
WORD gamma_value[2];
DWORD color_correction_offset; // Number of bytes from the beginning of the file to the color correction table if present
DWORD postage_stamp_offset; // Number of bytes from the beginning of the file to the postage stamp image if present
DWORD scan_line_offset; // Number of bytes from the beginning of the file to the scan lines table if present
BYTE attributes_type; // Specifies the alpha channel
} TGAEXTENSIONAREA;
typedef struct tagTGAFOOTER {
DWORD extension_offset; // extension area offset : offset in bytes from the beginning of the file
DWORD developer_offset; // developer directory offset : offset in bytes from the beginning of the file
char signature[18]; // signature string : contains "TRUEVISION-XFILE.\0"
} TGAFOOTER;
#ifdef _WIN32
#pragma pack(pop)
#else
#pragma pack()
#endif
static const char *FI_MSG_ERROR_CORRUPTED = "Image data corrupted";
// ----------------------------------------------------------
// Image type
//
#define TGA_NULL 0 // no image data included
#define TGA_CMAP 1 // uncompressed, color-mapped image
#define TGA_RGB 2 // uncompressed, true-color image
#define TGA_MONO 3 // uncompressed, black-and-white image
#define TGA_RLECMAP 9 // run-length encoded, color-mapped image
#define TGA_RLERGB 10 // run-length encoded, true-color image
#define TGA_RLEMONO 11 // run-length encoded, black-and-white image
#define TGA_CMPCMAP 32 // compressed (Huffman/Delta/RLE) color-mapped image (e.g., VDA/D) - Obsolete
#define TGA_CMPCMAP4 33 // compressed (Huffman/Delta/RLE) color-mapped four pass image (e.g., VDA/D) - Obsolete
// ==========================================================
// Thumbnail functions
// ==========================================================
class TargaThumbnail
{
public:
TargaThumbnail() : _w(0), _h(0), _depth(0), _data(NULL) {
}
~TargaThumbnail() {
if(_data) {
free(_data);
}
}
BOOL isNull() const {
return (_data == NULL);
}
BOOL read(FreeImageIO *io, fi_handle handle, size_t size) {
io->read_proc(&_w, 1, 1, handle);
io->read_proc(&_h, 1, 1, handle);
const size_t sizeofData = size - 2;
_data = (BYTE*)malloc(sizeofData);
if(_data) {
return (io->read_proc(_data, 1, (unsigned)sizeofData, handle) == sizeofData);
}
return FALSE;
}
void setDepth(BYTE dp) {
_depth = dp;
}
FIBITMAP* toFIBITMAP();
private:
BYTE _w;
BYTE _h;
BYTE _depth;
BYTE* _data;
};
#ifdef FREEIMAGE_BIGENDIAN
static void
swapShortPixels(FIBITMAP* dib) {
if(FreeImage_GetImageType(dib) != FIT_BITMAP) {
return;
}
const unsigned Bpp = FreeImage_GetBPP(dib)/8;
if(Bpp != 2) {
return;
}
BYTE* bits = FreeImage_GetBits(dib);
const unsigned height = FreeImage_GetHeight(dib);
const unsigned pitch = FreeImage_GetPitch(dib);
BYTE* line = bits;
for(unsigned y = 0; y < height; y++, line += pitch) {
for(BYTE* pixel = line; pixel < line + pitch ; pixel += Bpp) {
SwapShort((WORD*)pixel);
}
}
}
#endif // FREEIMAGE_BIGENDIAN
FIBITMAP* TargaThumbnail::toFIBITMAP() {
if(isNull() || _depth == 0) {
return NULL;
}
const unsigned line_size = _depth * _w / 8;
FIBITMAP* dib = FreeImage_Allocate(_w, _h, _depth);
if(!dib) {
return NULL;
}
const BYTE* line = _data;
const BYTE height = _h;
for (BYTE h = 0; h < height; ++h, line += line_size) {
BYTE* dst_line = FreeImage_GetScanLine(dib, height - 1 - h);
memcpy(dst_line, line, line_size);
}
#ifdef FREEIMAGE_BIGENDIAN
swapShortPixels(dib);
#endif
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
SwapRedBlue32(dib);
#endif
return dib;
}
// ==========================================================
// Internal functions
// ==========================================================
/** This class is used when loading RLE compressed images, it implements io cache of fixed size.
In general RLE compressed images *should* be compressed line by line with line sizes stored in Scan Line Table section.
In reality, however there are images not obeying the specification, compressing image data continuously across lines,
making it impossible to load the file cached at every line.
*/
class IOCache
{
public:
IOCache(FreeImageIO *io, fi_handle handle, size_t size) :
_ptr(NULL), _begin(NULL), _end(NULL), _size(size), _io(io), _handle(handle) {
_begin = (BYTE*)malloc(size);
if (_begin) {
_end = _begin + _size;
_ptr = _end; // will force refill on first access
}
}
~IOCache() {
if (_begin != NULL) {
free(_begin);
}
}
BOOL isNull() { return _begin == NULL;}
inline
BYTE getByte() {
if (_ptr >= _end) {
// need refill
_ptr = _begin;
_io->read_proc(_ptr, sizeof(BYTE), (unsigned)_size, _handle); //### EOF - no problem?
}
BYTE result = *_ptr;
_ptr++;
return result;
}
inline
BYTE* getBytes(size_t count /*must be < _size!*/) {
if (_ptr + count >= _end) {
// need refill
// 'count' bytes might span two cache bounds,
// SEEK back to add the remains of the current cache again into the new one
long read = long(_ptr - _begin);
long remaining = long(_size - read);
_io->seek_proc(_handle, -remaining, SEEK_CUR);
_ptr = _begin;
_io->read_proc(_ptr, sizeof(BYTE), (unsigned)_size, _handle); //### EOF - no problem?
}
BYTE *result = _ptr;
_ptr += count;
return result;
}
private:
IOCache& operator=(const IOCache& src); // deleted
IOCache(const IOCache& other); // deleted
( run in 0.497 second using v1.01-cache-2.11-cpan-62a16548d74 )