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 )