Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginPICT.cpp view on Meta::CPAN
WORD y;
};
struct MacPattern // Klaube
{
BYTE pix[64];
};
// ----------------------------------------------------------
static void
ReadRect( FreeImageIO *io, fi_handle handle, MacRect* rect ) {
rect->top = Read16( io, handle );
rect->left = Read16( io, handle );
rect->bottom = Read16( io, handle );
rect->right = Read16( io, handle );
}
static void
ReadPixmap( FreeImageIO *io, fi_handle handle, MacpixMap* pPixMap ) {
pPixMap->version = Read16( io, handle );
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.";
}
}
/**
Expands Width units to 8-bit pixel data.
Max. 8 bpp source format.
*/
static void
expandBuf8( FreeImageIO *io, fi_handle handle, int width, int bpp, BYTE* dst )
{
switch (bpp) {
case 8:
io->read_proc( dst, width, 1, handle );
break;
case 4:
for (int i = 0; i < width; i++) {
WORD src = Read8( io, handle );
*dst = (src >> 4) & 15;
*(dst+1) = (src & 15);
dst += 2;
}
if (width & 1) { // Odd Width?
WORD src = Read8( io, handle );
*dst = (src >> 4) & 15;
dst++;
}
break;
case 2:
for (int i = 0; i < width; i++) {
WORD src = Read8( io, handle );
*dst = (src >> 6) & 3;
*(dst+1) = (src >> 4) & 3;
*(dst+2) = (src >> 2) & 3;
*(dst+3) = (src & 3);
dst += 4;
}
if (width & 3) { // Check for leftover pixels
for (int i = 6; i > 8 - (width & 3) * 2; i -= 2) {
WORD src = Read8( io, handle );
*dst = (src >> i) & 3;
dst++;
}
}
break;
case 1:
for (int i = 0; i < width; i++) {
WORD src = Read8( io, handle );
*dst = (src >> 7) & 1;
*(dst+1) = (src >> 6) & 1;
*(dst+2) = (src >> 5) & 1;
*(dst+3) = (src >> 4) & 1;
*(dst+4) = (src >> 3) & 1;
*(dst+5) = (src >> 2) & 1;
*(dst+6) = (src >> 1) & 1;
*(dst+7) = (src & 1);
dst += 8;
}
if (width & 7) { // Check for leftover pixels
for (int i = 7; i > (8-width & 7); i--) {
WORD src = Read8( io, handle );
*dst = (src >> i) & 1;
dst++;
}
}
break;
default:
throw "Bad bits per pixel in expandBuf8.";
}
}
static BYTE*
UnpackPictRow( FreeImageIO *io, fi_handle handle, BYTE* pLineBuf, int width, int rowBytes, int srcBytes ) {
if (rowBytes < 8) { // Ah-ha! The bits aren't actually packed. This will be easy.
io->read_proc( pLineBuf, rowBytes, 1, handle );
}
else {
BYTE* pCurPixel = pLineBuf;
// Unpack RLE. The data is packed bytewise.
for (int j = 0; j < srcBytes; ) {
BYTE FlagCounter = Read8( io, handle );
if (FlagCounter & 0x80) {
if (FlagCounter == 0x80) {
// Special case: repeat value of 0.
// Apple says ignore.
j++;
} else {
// Packed data.
int len = ((FlagCounter ^ 255) & 255) + 2;
BYTE p = Read8( io, handle );
memset( pCurPixel, p, len);
pCurPixel += len;
j += 2;
}
}
else {
// Unpacked data
int len = (FlagCounter & 255) + 1;
io->read_proc( pCurPixel, len, 1, handle );
pCurPixel += len;
j += len + 1;
}
}
}
return pLineBuf;
}
/**
This routine decompresses BitsRects with a packType of 4 (and 32 bits per pixel).
In this format, each line is separated into 8-bit-bitplanes and then compressed via RLE.
To decode, the routine decompresses each line & then juggles the bytes around to get pixel-oriented data.
NumBitPlanes == 3 if RGB, 4 if RGBA
*/
static void
Unpack32Bits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes, int numPlanes ) {
int height = bounds->bottom - bounds->top;
int width = bounds->right - bounds->left;
if (rowBytes == 0) {
rowBytes = (WORD)( width * 4 );
}
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 );
}
BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);
BYTE FlagCounter;
// Unpack RLE. The data is packed bytewise - except for
// 16 bpp data, which is packed per pixel :-(.
for ( int j = 0; j < linelen; ) {
FlagCounter = Read8( io, handle );
if (FlagCounter & 0x80) {
if (FlagCounter == 0x80) {
// Special case: repeat value of 0.
// Apple says ignore.
j++;
}
else {
// Packed data.
int len = ((FlagCounter ^ 255) & 255) + 2;
// This is slow for some formats...
if (pixelSize == 16) {
expandBuf( io, handle, 1, pixelSize, dst );
for ( int k = 1; k < len; k++ ) {
// Repeat the pixel len times.
memcpy( dst+(k*4*PixelPerRLEUnit), dst, 4*PixelPerRLEUnit);
}
dst += len*4*PixelPerRLEUnit;
}
else {
expandBuf8( io, handle, 1, pixelSize, dst );
for ( int k = 1; k < len; k++ ) {
// Repeat the expanded byte len times.
memcpy( dst+(k*PixelPerRLEUnit), dst, PixelPerRLEUnit);
}
dst += len*PixelPerRLEUnit;
}
j += pkpixsize + 1;
}
}
else {
// Unpacked data
int len = (FlagCounter & 255) + 1;
if (pixelSize == 16) {
expandBuf( io, handle, len, pixelSize, dst );
dst += len*4*PixelPerRLEUnit;
}
else {
expandBuf8( io, handle, len, pixelSize, dst );
dst += len*PixelPerRLEUnit;
}
j += ( len * pkpixsize ) + 1;
}
}
}
}
}
}
static void
DecodeOp9a( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacpixMap* pixMap ) {
// Do the actual unpacking.
switch ( pixMap->pixelSize ) {
case 32:
Unpack32Bits( io, handle, dib, &pixMap->Bounds, 0, pixMap->cmpCount );
break;
case 8:
Unpack8Bits( io, handle, dib, &pixMap->Bounds, 0 );
break;
default:
UnpackBits( io, handle, dib, &pixMap->Bounds, 0, pixMap->pixelSize );
}
}
static void
DecodeBitmap( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, BOOL isRegion, MacRect* bounds, WORD rowBytes ) {
WORD mode = Read16( io, handle );
if ( isRegion ) {
SkipPolyOrRegion( io, handle );
}
RGBQUAD* pal = FreeImage_GetPalette( dib );
if ( !pal ) {
throw "No palette for bitmap!";
}
for (int i = 0; i < 2; i++) {
unsigned char val = i ? 0xFF : 0x0;
pal[i].rgbRed = val;
pal[i].rgbGreen = val;
pal[i].rgbBlue = val;
}
UnpackBits( io, handle, dib, bounds, rowBytes, 1 );
}
static void
DecodePixmap( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, BOOL isRegion, MacpixMap* pixMap, WORD rowBytes ) {
// Read mac colour table into windows palette.
WORD numColors; // Palette size.
RGBQUAD ct[256];
ReadColorTable( io, handle, &numColors, ct );
if ( FreeImage_GetBPP( dib ) == 8 ) {
RGBQUAD* pal = FreeImage_GetPalette( dib );
if ( !pal ) {
throw "No palette for bitmap!";
}
for (int i = 0; i < numColors; i++) {
pal[i].rgbRed = ct[ i ].rgbRed;
pal[i].rgbGreen = ct[ i ].rgbGreen;
pal[i].rgbBlue = ct[ i ].rgbBlue;
}
}
// Ignore source & destination rectangle as well as transfer mode.
MacRect tempRect;
ReadRect( io, handle, &tempRect );
ReadRect( io, handle, &tempRect );
WORD mode = Read16( io, handle );
if ( isRegion) {
SkipPolyOrRegion( io, handle );
}
switch ( pixMap->pixelSize ) {
case 32:
Unpack32Bits( io, handle, dib, &pixMap->Bounds, rowBytes, pixMap->cmpCount );
break;
case 8:
Unpack8Bits( io, handle, dib, &pixMap->Bounds, rowBytes );
break;
default:
UnpackBits( io, handle, dib, &pixMap->Bounds, rowBytes, pixMap->pixelSize );
}
}
// ==========================================================
// Plugin Implementation
// ==========================================================
static const char * DLL_CALLCONV
Format() {
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;
WORD len = Read16( io, handle );
if (len == 0x000a) {
/* null rgn */
ReadRect( io, handle, &clipRect );
} else {
io->seek_proc(handle, len - 2, SEEK_CUR);
}
break;
}
case 0x12:
case 0x13:
case 0x14:
{
// skip pattern definition
WORD patType;
WORD rowBytes;
MacpixMap p;
WORD numColors;
patType = Read16( io, handle );
switch( patType ) {
case 2:
io->seek_proc(handle, 8, SEEK_CUR);
io->seek_proc(handle, 5, SEEK_CUR);
break;
case 1:
{
io->seek_proc(handle, 8, SEEK_CUR);
rowBytes = Read16( io, handle );
ReadRect( io, handle, &p.Bounds );
ReadPixmap( io, handle, &p);
RGBQUAD ct[256];
ReadColorTable(io, handle, &numColors, ct );
SkipBits( io, handle, &p.Bounds, rowBytes, p.pixelSize );
break;
}
default:
throw "Unknown pattern type.";
}
break;
}
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77:
{
SkipPolyOrRegion( io, handle );
break;
}
case 0x90:
case 0x98:
{
// Bitmap/pixmap data clipped by a rectangle.
rowBytes = Read16( io, handle ); // Bytes per row in source when uncompressed.
isRegion = FALSE;
if ( rowBytes & 0x8000) {
pictType = pixmap;
} else {
pictType = bitmap;
}
done = TRUE;
break;
}
case 0x91:
case 0x99:
{
// Bitmap/pixmap data clipped by a region.
rowBytes = Read16( io, handle ); // Bytes per row in source when uncompressed.
isRegion = TRUE;
if ( rowBytes & 0x8000) {
pictType = pixmap;
} else {
pictType = bitmap;
}
done = TRUE;
break;
}
case 0x9a:
{
// DirectBitsRect.
Read32( io, handle ); // Skip fake len and fake EOF.
Read16( io, handle ); // bogus row bytes.
// Read in the PixMap fields.
ReadRect( io, handle, &pixMap.Bounds );
ReadPixmap( io, handle, &pixMap );
// Ignore source & destination rectangle as well as transfer mode.
MacRect dummy;
ReadRect( io, handle, &dummy );
ReadRect( io, handle, &dummy );
src/Source/FreeImage/PluginPICT.cpp view on Meta::CPAN
WORD len;
type = Read16( io, handle );
len = Read16( io, handle);
if (len > 0) {
io->seek_proc(handle, len, SEEK_CUR);
}
break;
}
default:
// No function => skip to next opcode
if (optable[opcode].len == WORD_LEN) {
WORD len = Read16( io, handle );
io->seek_proc(handle, len, SEEK_CUR);
} else {
io->seek_proc(handle, optable[opcode].len, SEEK_CUR);
}
break;
}
}
else if (opcode == 0xc00) {
// version 2 header (26 bytes)
WORD minorVersion = Read16( io, handle ); // always FFFE (-2) for extended version 2
Read16( io, handle ); // reserved
hRes = Read32( io, handle ); // original horizontal resolution in pixels/inch
vRes = Read32( io, handle ); // original horizontal resolution in pixels/inch
MacRect dummy;
ReadRect( io, handle, &dummy ); // frame bounds at original resolution
Read32( io, handle ); // reserved
}
else if (opcode == 0x8200) {
// jpeg
long opLen = Read32( io, handle );
BOOL found = FALSE;
int i = 0;
// skip to JPEG header.
while ( !found && i < opLen ) {
// io->seek_proc( handle, 24, SEEK_CUR );
// MacRect dummy;
// ReadRect( io, handle, &dummy );
// io->seek_proc( handle, 122, SEEK_CUR );
// found = TRUE;
BYTE data[ 2 ];
if( io->read_proc( data, 2, 1, handle ) ) {
io->seek_proc( handle, -2, SEEK_CUR );
if ( data[0] == 0xFF && data[1] == 0xD8 ) {
found = TRUE;
} else {
Read8( io, handle );
i++;
}
}
}
if ( found ) {
// Pass the data to the JPEG decoder.
pictType = jpeg;
} else {
throw "PICT file contains unrecognized quicktime data.";
}
done = TRUE;
}
else if (opcode >= 0xa2 && opcode <= 0xaf) {
// reserved
WORD len = Read16( io, handle );
io->seek_proc(handle, len, SEEK_CUR);
}
else if ((opcode >= 0xb0 && opcode <= 0xcf) || (opcode >= 0x8000 && opcode <= 0x80ff)) {
// just a reserved opcode, no data
}
else if ((opcode >= 0xd0 && opcode <= 0xfe) || opcode >= 8100) {
// reserved
LONG len = Read32( io, handle );
io->seek_proc(handle, len, SEEK_CUR);
}
else if (opcode >= 0x100 && opcode <= 0x7fff) {
// reserved
io->seek_proc(handle, ((opcode >> 7) & 255), SEEK_CUR);
}
else {
sprintf( outputMessage, "Can't handle opcode %x.\n", opcode );
throw outputMessage;
}
if(currentPos == io->tell_proc(handle)) {
// we probaly reached the end of file as we can no longer move forward ...
throw "Invalid PICT file";
}
}
switch ( pictType ) {
case op9a:
{
bounds = pixMap.Bounds;
int width = bounds.right - bounds.left;
int height = bounds.bottom - bounds.top;
if ( pixMap.pixelSize > 8 ) {
dib = FreeImage_Allocate( width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
} else {
dib = FreeImage_Allocate( width, height, 8);
}
hRes = pixMap.hRes << 16;
vRes = pixMap.vRes << 16;
break;
}
case jpeg:
{
dib = FreeImage_LoadFromHandle( FIF_JPEG, io, handle );
break;
}
case pixmap:
{
// Decode version 2 pixmap
ReadRect( io, handle, &pixMap.Bounds );
ReadPixmap( io, handle, &pixMap );
bounds = pixMap.Bounds;
int width = bounds.right - bounds.left;
int height = bounds.bottom - bounds.top;
if ( pixMap.pixelSize > 8 ) {
dib = FreeImage_Allocate( width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
} else {
dib = FreeImage_Allocate( width, height, 8);
}
hRes = pixMap.hRes << 16;
vRes = pixMap.vRes << 16;
break;
}
case bitmap:
{
// Decode version 1 bitmap: 1 bpp.
MacRect srcRect;
MacRect dstRect;
WORD width; // Width in pixels
WORD height; // Height in pixels
ReadRect( io, handle, &bounds );
ReadRect( io, handle, &srcRect );
ReadRect( io, handle, &dstRect );
width = bounds.right - bounds.left;
height = bounds.bottom - bounds.top;
dib = FreeImage_Allocate(width, height, 8);
break;
}
}
if ( dib ) {
// need to convert resolution figures from fixed point, pixels/inch
// to floating point, pixels/meter.
float hres_ppm = hRes * ((float)39.4 / (float)65536.0);
float vres_ppm = vRes * ((float)39.4 / (float)65536.0);
FreeImage_SetDotsPerMeterX( dib, (LONG)hres_ppm );
FreeImage_SetDotsPerMeterY( dib, (LONG)vres_ppm );
switch( pictType ) {
case op9a:
DecodeOp9a( io, handle, dib, &pixMap );
break;
case jpeg:
// Already decoded if the embedded format was valid.
break;
case pixmap:
DecodePixmap( io, handle, dib, isRegion, &pixMap, rowBytes );
break;
case bitmap:
DecodeBitmap( io, handle, dib, isRegion, &bounds, rowBytes );
break;
default:
throw "invalid pict type";
}
}
return dib;
}
catch(const char *message) {
FreeImage_Unload( dib );
FreeImage_OutputMessageProc(s_format_id, message);
}
return NULL;
}
// ==========================================================
// Init
// ==========================================================
void DLL_CALLCONV
InitPICT(Plugin *plugin, int format_id) {
s_format_id = format_id;
plugin->format_proc = Format;
plugin->description_proc = Description;
plugin->extension_proc = Extension;
plugin->regexpr_proc = NULL;
plugin->open_proc = NULL;
plugin->close_proc = NULL;
plugin->pagecount_proc = NULL;
plugin->pagecapability_proc = NULL;
plugin->load_proc = Load;
plugin->save_proc = NULL;
plugin->validate_proc = Validate;
plugin->mime_proc = MimeType;
plugin->supports_export_bpp_proc = SupportsExportDepth;
plugin->supports_export_type_proc = SupportsExportType;
plugin->supports_icc_profiles_proc = SupportsICCProfiles;
}
( run in 0.612 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )