Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginPICT.cpp view on Meta::CPAN
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 {
src/Source/FreeImage/PluginPICT.cpp view on Meta::CPAN
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!";
}
( run in 1.277 second using v1.01-cache-2.11-cpan-5b529ec07f3 )