Alien-FreeImage

 view release on metacpan or  search on metacpan

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

typedef struct tagSGIHeader {
	/** IRIS image file magic number. This should be decimal 474. */
	WORD magic;
	/** Storage format: 0 for uncompressed, 1 for RLE compression. */
	BYTE storage;
	/** Number of bytes per pixel channel. Legally 1 or 2. */
	BYTE bpc;
	/**
	Number of dimensions. Legally 1, 2, or 3. 
	1 means a single row, XSIZE long
	2 means a single 2D image
	3 means multiple 2D images
	*/
	WORD dimension;	
	/** X size in pixels */
	WORD xsize;
	/** Y size in pixels */
	WORD ysize;
	/**
	Number of channels. 
	1 indicates greyscale
	3 indicates RGB
	4 indicates RGB and Alpha
	*/
	WORD zsize;
	/** Minimum pixel value. This is the lowest pixel value in the image.*/
	LONG pixmin;
	/** Maximum pixel value. This is the highest pixel value in the image.*/
	LONG pixmax;
	/** Ignored. Normally set to 0. */
	char dummy[4];
	/** Image name. Must be null terminated, therefore at most 79 bytes. */
	char imagename[80];
	/** 
	Colormap ID. 
	0 - normal mode
	1 - dithered, 3 mits for red and green, 2 for blue, obsolete
	2 - index colour, obsolete
	3 - not an image but a colourmap
	*/
	LONG colormap;
	/** Ignored. Should be set to 0, makes the header 512 bytes. */
	char reserved[404];
} SGIHeader;

typedef struct tagRLEStatus {
  int cnt;
  int val;
} RLEStatus;

#ifdef _WIN32
#pragma pack(pop)
#else
#pragma pack()
#endif

static const char *SGI_LESS_THAN_HEADER_LENGTH = "Incorrect header size";
static const char *SGI_16_BIT_COMPONENTS_NOT_SUPPORTED = "No 16 bit support";
static const char *SGI_COLORMAPS_NOT_SUPPORTED = "No colormap support";
static const char *SGI_EOF_IN_RLE_INDEX = "EOF in run length encoding";
static const char *SGI_EOF_IN_IMAGE_DATA = "EOF in image data";
static const char *SGI_INVALID_CHANNEL_COUNT = "Invalid channel count";

// ==========================================================
// Plugin Interface
// ==========================================================

static int s_format_id;

// ==========================================================
// Plugin Implementation
// ==========================================================

#ifndef FREEIMAGE_BIGENDIAN
static void 
SwapHeader(SGIHeader *header) {
	SwapShort(&header->magic);
	SwapShort(&header->dimension);
	SwapShort(&header->xsize);
	SwapShort(&header->ysize);
	SwapShort(&header->zsize);
	SwapLong((DWORD*)&header->pixmin);
	SwapLong((DWORD*)&header->pixmax);
	SwapLong((DWORD*)&header->colormap);
}
#endif

static int 
get_rlechar(FreeImageIO *io, fi_handle handle, RLEStatus *pstatus) {
	if (!pstatus->cnt) {
		int cnt = 0;
		while (0 == cnt) {
			BYTE packed = 0;
			if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) {
				return EOF;
			}
			cnt = packed;
		}
		if (cnt == EOF) {
			return EOF;
		}
		pstatus->cnt = cnt & 0x7F;
		if (cnt & 0x80) {
			pstatus->val = -1;
		} else {
			BYTE packed = 0;
			if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) {
				return EOF;
			}
			pstatus->val = packed;
		}
	}
	pstatus->cnt--;
	if (pstatus->val == -1) {
		BYTE packed = 0;
		if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) {
			return EOF;
		}
		return packed;
	}
	else {

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

		}
		
		dib = FreeImage_Allocate(width, height, bitcount);
		if(!dib) {
			throw FI_MSG_ERROR_DIB_MEMORY;
		}
		
		if (bitcount == 8) {
			// 8-bit SGI files are grayscale images, so we'll generate
			// a grayscale palette.
			RGBQUAD *pclrs = FreeImage_GetPalette(dib);
			for (i = 0; i < 256; i++) {
				pclrs[i].rgbRed = (BYTE)i;
				pclrs[i].rgbGreen = (BYTE)i;
				pclrs[i].rgbBlue = (BYTE)i;
				pclrs[i].rgbReserved = 0;
			}
		}

		// decode the image

		memset(&my_rle_status, 0, sizeof(RLEStatus));
		
		int ns = FreeImage_GetPitch(dib);                                                    
		BYTE *pStartRow = FreeImage_GetScanLine(dib, 0);
		int offset_table[] = { 2, 1, 0, 3 };
		int numChannels = zsize;
		if (zsize < 3) {
			offset_table[0] = 0;
		}
		if (zsize == 2)
		{
			//This is how faked grayscale+alpha works.
			//First channel goes into first 
			//second channel goes into alpha (4th channel)
			//Two channels are left empty and will be copied later
			offset_table[1] = 3;
			numChannels = 4;
		}
		
		LONG *pri = pRowIndex;
		for (i = 0; i < zsize; i++) {
			BYTE *pRow = pStartRow + offset_table[i];
			for (int j = 0; j < height; j++, pRow += ns, pri++) {
				BYTE *p = pRow;
				if (bIsRLE) {
					my_rle_status.cnt = 0;
					io->seek_proc(handle, *pri, SEEK_SET);
				}
				for (int k = 0; k < width; k++, p += numChannels) {
					int ch;
					BYTE packed = 0;
					if (bIsRLE) {
						ch = get_rlechar(io, handle, &my_rle_status);
						packed = (BYTE)ch;
					}
					else {
						ch = io->read_proc(&packed, sizeof(BYTE), 1, handle);
					}
					if (ch == EOF) {
						throw SGI_EOF_IN_IMAGE_DATA;
					}
					*p = packed;
				}
			}
		}
		
		if (zsize == 2)
		{
			BYTE *pRow = pStartRow;
			//If faking RGBA from grayscale + alpha, copy first channel to second and third
			for (int i=0; i<height; i++, pRow += ns)
			{
				BYTE *pPixel = pRow;
				for (int j=0; j<width; j++)
				{
					pPixel[2] = pPixel[1] = pPixel[0];
					pPixel += 4;
				}
			}
		}
		if(pRowIndex)
			free(pRowIndex);

		return dib;

	} catch(const char *text) {
		if(pRowIndex) free(pRowIndex);
		if(dib) FreeImage_Unload(dib);
		FreeImage_OutputMessageProc(s_format_id, text);
		return NULL;
	}
}

// ==========================================================
//   Init
// ==========================================================

void DLL_CALLCONV 
InitSGI(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 = RegExpr;
	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 = NULL;
}



( run in 0.603 second using v1.01-cache-2.11-cpan-13bb782fe5a )