Alien-FreeImage

 view release on metacpan or  search on metacpan

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

	the page parameter is always -1.
	
	The fourth parameter (int flags) manipulates the load function to load a bitmap
	in a certain way. Every plugin has a different flag parameter with different meanings.

	The last parameter (void *data) can contain a special data block used when
	the file is read multi-paged. Because not every plugin supports multi-paging
	not every plugin will use the data parameter and it will be set to NULL.However,
	when the plugin does support multi-paging the parameter contains a pointer to a
	block of data allocated by the Open function.
*/

static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	FIBITMAP *dib = NULL;
	BYTE *bits;			  // Pointer to dib data
	RGBQUAD *pal;		  // Pointer to dib palette
	BYTE *line = NULL;	  // PCX raster line
	BYTE *ReadBuf = NULL; // buffer;
	BOOL bIsRLE;		  // True if the file is run-length encoded

	if(!handle) {
		return NULL;
	}

	BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;

	try {
		// check PCX identifier

		long start_pos = io->tell_proc(handle);
		BOOL validated = pcx_validate(io, handle);		
		io->seek_proc(handle, start_pos, SEEK_SET);
		if(!validated) {
			throw FI_MSG_ERROR_MAGIC_NUMBER;
		}

		// process the header

		PCXHEADER header;

		if(io->read_proc(&header, sizeof(PCXHEADER), 1, handle) != 1) {
			throw FI_MSG_ERROR_PARSING;
		}
#ifdef FREEIMAGE_BIGENDIAN
		SwapHeader(&header);
#endif

		// allocate a new DIB

		unsigned width = header.window[2] - header.window[0] + 1;
		unsigned height = header.window[3] - header.window[1] + 1;
		unsigned bitcount = header.bpp * header.planes;

		if (bitcount == 24) {
			dib = FreeImage_AllocateHeader(header_only, width, height, bitcount, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
		} else {
			dib = FreeImage_AllocateHeader(header_only, width, height, bitcount);			
		}

		// if the dib couldn't be allocated, throw an error

		if (!dib) {
			throw FI_MSG_ERROR_DIB_MEMORY;
		}

		// metrics handling code

		FreeImage_SetDotsPerMeterX(dib, (unsigned) (((float)header.hdpi) / 0.0254000 + 0.5));
		FreeImage_SetDotsPerMeterY(dib, (unsigned) (((float)header.vdpi) / 0.0254000 + 0.5));

		// Set up the palette if needed
		// ----------------------------

		switch(bitcount) {
			case 1:
			{
				pal = FreeImage_GetPalette(dib);
				pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
				pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
				break;
			}

			case 4:
			{
				pal = FreeImage_GetPalette(dib);

				BYTE *pColormap = &header.color_map[0];

				for (int i = 0; i < 16; i++) {
					pal[i].rgbRed   = pColormap[0];
					pal[i].rgbGreen = pColormap[1];
					pal[i].rgbBlue  = pColormap[2];
					pColormap += 3;
				}

				break;
			}

			case 8:
			{
				BYTE palette_id;

				io->seek_proc(handle, -769L, SEEK_END);
				io->read_proc(&palette_id, 1, 1, handle);

				if (palette_id == 0x0C) {
					BYTE *cmap = (BYTE*)malloc(768 * sizeof(BYTE));
					io->read_proc(cmap, 768, 1, handle);

					pal = FreeImage_GetPalette(dib);
					BYTE *pColormap = &cmap[0];

					for(int i = 0; i < 256; i++) {
						pal[i].rgbRed   = pColormap[0];
						pal[i].rgbGreen = pColormap[1];
						pal[i].rgbBlue  = pColormap[2];
						pColormap += 3;
					}

					free(cmap);



( run in 0.475 second using v1.01-cache-2.11-cpan-5735350b133 )