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 )