Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginPICT.cpp view on Meta::CPAN
return (WORD)(lo + (hi << 8));
}
static unsigned
Read32(FreeImageIO *io, fi_handle handle) {
// reads a four-byte big-endian integer from the given file and returns its value.
// assumes unsigned.
unsigned b3 = Read8(io, handle);
unsigned b2 = Read8(io, handle);
unsigned b1 = Read8(io, handle);
unsigned b0 = Read8(io, handle);
return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
}
// ----------------------------------------------------------
struct OpDef
{
const char * name;
int len;
const char * description;
};
// for reserved opcodes
#define res(length) { "reserved", (length), "reserved for Apple use" }
#define RGB_LEN 6
#define WORD_LEN -1
#define NA 0
static OpDef optable[] =
{
/* 0x00 */ { "NOP", 0, "nop" },
/* 0x01 */ { "Clip", NA, "clip" },
/* 0x02 */ { "BkPat", 8, "background pattern" },
/* 0x03 */ { "TxFont", 2, "text font (word)" },
/* 0x04 */ { "TxFace", 1, "text face (byte)" },
/* 0x05 */ { "TxMode", 2, "text mode (word)" },
/* 0x06 */ { "SpExtra", 4, "space extra (fixed point)" },
/* 0x07 */ { "PnSize", 4, "pen size (point)" },
/* 0x08 */ { "PnMode", 2, "pen mode (word)" },
/* 0x09 */ { "PnPat", 8, "pen pattern" },
/* 0x0a */ { "FillPat", 8, "fill pattern" },
/* 0x0b */ { "OvSize", 4, "oval size (point)" },
/* 0x0c */ { "Origin", 4, "dh, dv (word)" },
/* 0x0d */ { "TxSize", 2, "text size (word)" },
/* 0x0e */ { "FgColor", 4, "foreground color (longword)" },
/* 0x0f */ { "BkColor", 4, "background color (longword)" },
/* 0x10 */ { "TxRatio", 8, "numerator (point), denominator (point)" },
/* 0x11 */ { "Version", 1, "version (byte)" },
/* 0x12 */ { "BkPixPat", NA, "color background pattern" },
/* 0x13 */ { "PnPixPat", NA, "color pen pattern" },
/* 0x14 */ { "FillPixPat", NA, "color fill pattern" },
/* 0x15 */ { "PnLocHFrac", 2, "fractional pen position" },
/* 0x16 */ { "ChExtra", 2, "extra for each character" },
/* 0x17 */ res(0),
/* 0x18 */ res(0),
/* 0x19 */ res(0),
/* 0x1a */ { "RGBFgCol", RGB_LEN, "RGB foreColor" },
/* 0x1b */ { "RGBBkCol", RGB_LEN, "RGB backColor" },
/* 0x1c */ { "HiliteMode", 0, "hilite mode flag" },
/* 0x1d */ { "HiliteColor", RGB_LEN, "RGB hilite color" },
/* 0x1e */ { "DefHilite", 0, "Use default hilite color" },
/* 0x1f */ { "OpColor", 6, "RGB OpColor for arithmetic modes" },
/* 0x20 */ { "Line", 8, "pnLoc (point), newPt (point)" },
/* 0x21 */ { "LineFrom", 4, "newPt (point)" },
/* 0x22 */ { "ShortLine", 6, "pnLoc (point, dh, dv (-128 .. 127))" },
/* 0x23 */ { "ShortLineFrom", 2, "dh, dv (-128 .. 127)" },
/* 0x24 */ res(WORD_LEN),
/* 0x25 */ res(WORD_LEN),
/* 0x26 */ res(WORD_LEN),
/* 0x27 */ res(WORD_LEN),
/* 0x28 */ { "LongText", NA, "txLoc (point), count (0..255), text" },
/* 0x29 */ { "DHText", NA, "dh (0..255), count (0..255), text" },
/* 0x2a */ { "DVText", NA, "dv (0..255), count (0..255), text" },
/* 0x2b */ { "DHDVText", NA, "dh, dv (0..255), count (0..255), text" },
/* 0x2c */ res(WORD_LEN),
/* 0x2d */ res(WORD_LEN),
/* 0x2e */ res(WORD_LEN),
/* 0x2f */ res(WORD_LEN),
/* 0x30 */ { "frameRect", 8, "rect" },
/* 0x31 */ { "paintRect", 8, "rect" },
/* 0x32 */ { "eraseRect", 8, "rect" },
/* 0x33 */ { "invertRect", 8, "rect" },
/* 0x34 */ { "fillRect", 8, "rect" },
/* 0x35 */ res(8),
/* 0x36 */ res(8),
/* 0x37 */ res(8),
/* 0x38 */ { "frameSameRect", 0, "rect" },
/* 0x39 */ { "paintSameRect", 0, "rect" },
/* 0x3a */ { "eraseSameRect", 0, "rect" },
/* 0x3b */ { "invertSameRect", 0, "rect" },
/* 0x3c */ { "fillSameRect", 0, "rect" },
/* 0x3d */ res(0),
/* 0x3e */ res(0),
/* 0x3f */ res(0),
/* 0x40 */ { "frameRRect", 8, "rect" },
/* 0x41 */ { "paintRRect", 8, "rect" },
/* 0x42 */ { "eraseRRect", 8, "rect" },
/* 0x43 */ { "invertRRect", 8, "rect" },
/* 0x44 */ { "fillRRrect", 8, "rect" },
/* 0x45 */ res(8),
/* 0x46 */ res(8),
/* 0x47 */ res(8),
/* 0x48 */ { "frameSameRRect", 0, "rect" },
/* 0x49 */ { "paintSameRRect", 0, "rect" },
/* 0x4a */ { "eraseSameRRect", 0, "rect" },
/* 0x4b */ { "invertSameRRect", 0, "rect" },
/* 0x4c */ { "fillSameRRect", 0, "rect" },
/* 0x4d */ res(0),
/* 0x4e */ res(0),
/* 0x4f */ res(0),
/* 0x50 */ { "frameOval", 8, "rect" },
/* 0x51 */ { "paintOval", 8, "rect" },
/* 0x52 */ { "eraseOval", 8, "rect" },
/* 0x53 */ { "invertOval", 8, "rect" },
/* 0x54 */ { "fillOval", 8, "rect" },
/* 0x55 */ res(8),
/* 0x56 */ res(8),
/* 0x57 */ res(8),
/* 0x58 */ { "frameSameOval", 0, "rect" },
src/Source/FreeImage/PluginPICT.cpp view on Meta::CPAN
pPixMap->packType = Read16( io, handle );
pPixMap->packSize = Read32( io, handle );
pPixMap->hRes = Read16( io, handle );
Read16( io, handle );
pPixMap->vRes = Read16( io, handle );
Read16( io, handle );
pPixMap->pixelType = Read16( io, handle );
pPixMap->pixelSize = Read16( io, handle );
pPixMap->cmpCount = Read16( io, handle );
pPixMap->cmpSize = Read16( io, handle );
pPixMap->planeBytes = Read32( io, handle );
pPixMap->pmTable = Read32( io, handle );
pPixMap->pmReserved = Read32( io, handle );
}
/**
Reads a mac color table into a bitmap palette.
*/
static void
ReadColorTable( FreeImageIO *io, fi_handle handle, WORD* pNumColors, RGBQUAD* pPal ) {
LONG ctSeed;
WORD ctFlags;
WORD val;
int i;
ctSeed = Read32( io, handle );
ctFlags = Read16( io, handle );
WORD numColors = Read16( io, handle )+1;
*pNumColors = numColors;
for (i = 0; i < numColors; i++) {
val = Read16( io, handle );
if (ctFlags & 0x8000) {
// The indicies in a device colour table are bogus and
// usually == 0, so I assume we allocate up the list of
// colours in order.
val = (WORD)i;
}
if (val >= numColors) {
throw "pixel value greater than color table size.";
}
// Mac colour tables contain 16-bit values for R, G, and B...
pPal[val].rgbRed = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF));
pPal[val].rgbGreen = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF));
pPal[val].rgbBlue = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF));
}
}
/**
skips unneeded packbits.
pixelSize == Source bits per pixel.
*/
static void
SkipBits( FreeImageIO *io, fi_handle handle, MacRect* bounds, WORD rowBytes, int pixelSize ) {
int i;
WORD pixwidth; // bytes per row when uncompressed.
int height = bounds->bottom - bounds->top;
int width = bounds->right - bounds->left;
// High bit of rowBytes is flag.
if (pixelSize <= 8) {
rowBytes &= 0x7fff;
}
pixwidth = (WORD)width;
if (pixelSize == 16) {
pixwidth *= 2;
}
if (rowBytes == 0) {
rowBytes = pixwidth;
}
if (rowBytes < 8) {
io->seek_proc( handle, rowBytes*height, SEEK_CUR );
}
else {
for (i = 0; i < height; i++) {
int lineLen; // length of source line in bytes.
if (rowBytes > 250) {
lineLen = Read16( io, handle );
} else {
lineLen = Read8( io, handle );
}
io->seek_proc( handle, lineLen, SEEK_CUR );
}
}
}
/**
Skip polygon or region
*/
static void
SkipPolyOrRegion( FreeImageIO *io, fi_handle handle ) {
WORD len = Read16( io, handle ) - 2;
io->seek_proc(handle, len, SEEK_CUR);
}
/**
Width in bytes for 8 bpp or less.
Width in pixels for 16 bpp.
Expands Width units to 32-bit pixel data.
*/
static void
expandBuf( FreeImageIO *io, fi_handle handle, int width, int bpp, BYTE* dst ) {
switch (bpp) {
case 16:
for ( int i=0; i<width; i++) {
WORD src = Read16( io, handle );
dst[ FI_RGBA_BLUE ] = (src & 31)*8; // Blue
dst[ FI_RGBA_GREEN ] = ((src >> 5) & 31)*8; // Green
dst[ FI_RGBA_RED ] = ((src >> 10) & 31)*8; // Red
dst[ FI_RGBA_ALPHA ] = 0xFF; // Alpha
dst += 4;
}
break;
default:
throw "Bad bits per pixel in expandBuf.";
}
}
/**
src/Source/FreeImage/PluginPICT.cpp view on Meta::CPAN
BYTE* pLineBuf = (BYTE*)malloc( rowBytes ); // Let's allocate enough for 4 bit planes
if ( pLineBuf ) {
try {
for ( int i = 0; i < height; i++ ) {
// for each line do...
int linelen; // length of source line in bytes.
if (rowBytes > 250) {
linelen = Read16( io, handle );
} else {
linelen = Read8( io, handle);
}
BYTE* pBuf = UnpackPictRow( io, handle, pLineBuf, width, rowBytes, linelen );
// Convert plane-oriented data into pixel-oriented data &
// copy into destination bitmap.
BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);
if ( numPlanes == 3 ) {
for ( int j = 0; j < width; j++ ) {
// For each pixel in line...
dst[ FI_RGBA_BLUE ] = (*(pBuf+width*2)); // Blue
dst[ FI_RGBA_GREEN ] = (*(pBuf+width)); // Green
dst[ FI_RGBA_RED ] = (*pBuf); // Red
dst[ FI_RGBA_ALPHA ] = (0xFF);
dst += 4;
pBuf++;
}
} else {
for ( int j = 0; j < width; j++ ) {
// For each pixel in line...
dst[ FI_RGBA_BLUE ] = (*(pBuf+width*3)); // Blue
dst[ FI_RGBA_GREEN ] = (*(pBuf+width*2)); // Green
dst[ FI_RGBA_RED ] = (*(pBuf+width)); // Red
dst[ FI_RGBA_ALPHA ] = (*pBuf);
dst += 4;
pBuf++;
}
}
}
}
catch( ... ) {
free( pLineBuf );
throw;
}
}
free( pLineBuf );
}
/**
Decompression routine for 8 bpp.
rowBytes is the number of bytes each source row would take if it were uncompressed.
This _isn't_ equal to the number of pixels in the row - it seems apple pads the data to a word boundary and then compresses it.
Of course, we have to decompress the excess data and then throw it away.
*/
static void
Unpack8Bits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes ) {
int height = bounds->bottom - bounds->top;
int width = bounds->right - bounds->left;
// High bit of rowBytes is flag.
rowBytes &= 0x7fff;
if (rowBytes == 0) {
rowBytes = (WORD)width;
}
for ( int i = 0; i < height; i++ ) {
int linelen; // length of source line in bytes.
if (rowBytes > 250) {
linelen = Read16( io, handle );
} else {
linelen = Read8( io, handle );
}
BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);
dst = UnpackPictRow( io, handle, dst, width, rowBytes, linelen );
}
}
/**
Decompression routine for everything but 8 & 32 bpp.
This routine is slower than the two routines above since it has to deal with a lot of special cases :-(.
It's also a bit chaotic because of these special cases...
unpack8bits is basically a dumber version of unpackbits.
pixelSize == Source bits per pixel.
*/
static void
UnpackBits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes, int pixelSize ) {
WORD pixwidth; // bytes per row when uncompressed.
int pkpixsize;
int PixelPerRLEUnit;
char outputMessage[ outputMessageSize ] = "";
int height = bounds->bottom - bounds->top;
int width = bounds->right - bounds->left;
// High bit of rowBytes is flag.
if (pixelSize <= 8) {
rowBytes &= 0x7fff;
}
pixwidth = (WORD)width;
pkpixsize = 1; // RLE unit: one byte for everything...
if (pixelSize == 16) { // ...except 16 bpp.
pkpixsize = 2;
pixwidth *= 2;
}
if (rowBytes == 0) {
rowBytes = pixwidth;
}
{
// I allocate the temporary line buffer here. I allocate too
// much memory to compensate for sloppy (& hence fast) decompression.
switch (pixelSize) {
case 1:
PixelPerRLEUnit = 8;
break;
case 2:
PixelPerRLEUnit = 4;
break;
case 4:
PixelPerRLEUnit = 2;
break;
case 8:
PixelPerRLEUnit = 1;
break;
case 16:
PixelPerRLEUnit = 1;
break;
default:
sprintf( outputMessage, "Illegal bpp value in unpackbits: %d\n", pixelSize );
throw outputMessage;
}
if (rowBytes < 8) {
// ah-ha! The bits aren't actually packed. This will be easy.
for ( int i = 0; i < height; i++ ) {
BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);
if (pixelSize == 16) {
expandBuf( io, handle, width, pixelSize, dst );
} else {
expandBuf8( io, handle, width, pixelSize, dst );
}
}
}
else {
for ( int i = 0; i < height; i++ ) {
// For each line do...
int linelen; // length of source line in bytes.
if (rowBytes > 250) {
linelen = Read16( io, handle );
} else {
linelen = Read8( io, handle );
}
src/Source/FreeImage/PluginPICT.cpp view on Meta::CPAN
return "PICT";
}
static const char * DLL_CALLCONV
Description() {
return "Macintosh PICT";
}
static const char * DLL_CALLCONV
Extension() {
return "pct,pict,pic";
}
static const char * DLL_CALLCONV
MimeType() {
return "image/x-pict";
}
static BOOL DLL_CALLCONV
Validate(FreeImageIO *io, fi_handle handle) {
if(io->seek_proc(handle, 522, SEEK_SET) == 0) {
BYTE pict_signature[] = { 0x00, 0x11, 0x02, 0xFF, 0x0C, 0X00 };
BYTE signature[6];
if(io->read_proc(signature, 1, sizeof(pict_signature), handle)) {
// v1.0 files have 0x11 (version operator) followed by 0x01 (version number)
// v2.0 files have 0x0011 (version operator) followed by 0x02ff (version number)
// and additionally 0x0c00 as a header opcode
// Currently, we are only supporting v2.0
return (memcmp(pict_signature, signature, sizeof(pict_signature)) == 0);
} else {
return FALSE;
}
}
return FALSE;
}
static BOOL DLL_CALLCONV
SupportsExportDepth(int depth) {
return FALSE;
}
static BOOL DLL_CALLCONV
SupportsExportType(FREE_IMAGE_TYPE type) {
return FALSE;
}
static BOOL DLL_CALLCONV
SupportsICCProfiles() {
return FALSE;
}
/**
This plugin decodes macintosh PICT files with 1,2,4,8,16 and 32 bits per pixel as well as PICT/JPEG.
If an alpha channel is present in a 32-bit-PICT, it is decoded as well.
The PICT format is a general picture file format and can contain a lot of other elements besides bitmaps.
These elements are ignored.
*/
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
char outputMessage[ outputMessageSize ] = "";
FIBITMAP* dib = NULL;
try {
// Skip empty 512 byte header.
if ( !io->seek_proc(handle, 512, SEEK_CUR) == 0 )
return NULL;
// Read PICT header
Read16( io, handle ); // Skip version 1 picture size
MacRect frame;
ReadRect( io, handle, &frame );
BYTE b = 0;
while ((b = Read8(io, handle)) == 0);
if ( b != 0x11 ) {
throw "invalid header: version number missing.";
}
int version = Read8( io, handle );
if ( version == 2 && Read8( io, handle ) != 0xff ) {
throw "invalid header: illegal version number.";
}
enum PICTType {none, op9a, jpeg, pixmap, bitmap};
PICTType pictType = none;
MacRect bounds;
MacpixMap pixMap;
int hRes = 0x480000; // in pixels/inch (72 by default == 0x480000 in fixed point)
int vRes = 0x480000; // in pixels/inch (72 by default == 0x480000 in fixed point)
WORD rowBytes = 0;
BOOL isRegion = FALSE;
BOOL done = FALSE;
long currentPos = 0;
while ( !done ) {
WORD opcode = 0;
// get the current stream position (used to avoid infinite loops)
currentPos = io->tell_proc(handle);
if ((version == 1) || ((io->tell_proc( handle ) % 2) != 0)) {
// align to word for version 2
opcode = Read8( io, handle );
}
if (version == 2) {
opcode = Read16( io, handle );
}
if (opcode == 0xFF || opcode == 0xFFFF) {
done = TRUE;
throw "PICT contained only vector data!";
}
else if (opcode < 0xa2) {
switch (opcode) {
case 0x01:
{
// skip clipping rectangle
MacRect clipRect;
( run in 0.578 second using v1.01-cache-2.11-cpan-63c85eba8c4 )