Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/FreeImage/PluginPICT.cpp  view on Meta::CPAN

// 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)	{				

src/Source/FreeImage/PluginPICT.cpp  view on Meta::CPAN

			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.912 second using v1.01-cache-2.11-cpan-8450f2e95f3 )