diff options
Diffstat (limited to 'plugins/FreeImage/Source/FreeImage/PluginSGI.cpp')
| -rw-r--r-- | plugins/FreeImage/Source/FreeImage/PluginSGI.cpp | 850 | 
1 files changed, 425 insertions, 425 deletions
diff --git a/plugins/FreeImage/Source/FreeImage/PluginSGI.cpp b/plugins/FreeImage/Source/FreeImage/PluginSGI.cpp index 38ac293b78..0fd162b1d4 100644 --- a/plugins/FreeImage/Source/FreeImage/PluginSGI.cpp +++ b/plugins/FreeImage/Source/FreeImage/PluginSGI.cpp @@ -1,425 +1,425 @@ -// ==========================================================
 -// SGI Loader
 -//
 -// Design and implementation by
 -// - Sherman Wilcox
 -// - Noam Gat
 -//
 -// References : 
 -// ------------
 -// - The SGI Image File Format, Version 1.0
 -// http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html
 -// - SGI RGB Image Format
 -// http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/
 -//
 -//
 -// This file is part of FreeImage 3
 -//
 -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
 -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
 -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
 -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
 -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
 -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
 -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
 -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
 -// THIS DISCLAIMER.
 -//
 -// Use at your own risk!
 -// ==========================================================
 -
 -#include "FreeImage.h"
 -#include "Utilities.h"
 -
 -// ----------------------------------------------------------
 -//   Constants + headers
 -// ----------------------------------------------------------
 -
 -#ifdef _WIN32
 -#pragma pack(push, 1)
 -#else
 -#pragma pack(1)
 -#endif
 -
 -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 {
 -		return pstatus->val;
 -	}
 -}
 -
 -static const char * DLL_CALLCONV
 -Format() {
 -  return "SGI";
 -}
 -
 -static const char * DLL_CALLCONV
 -Description() {
 -  return "SGI Image Format";
 -}
 -
 -static const char * DLL_CALLCONV
 -Extension() {
 -  return "sgi";
 -}
 -
 -static const char * DLL_CALLCONV
 -RegExpr() {
 -  return NULL;
 -}
 -
 -static const char * DLL_CALLCONV
 -MimeType() {
 -  return "image/sgi";
 -}
 -
 -static BOOL DLL_CALLCONV
 -Validate(FreeImageIO *io, fi_handle handle) {
 -	BYTE sgi_signature[2] = { 0x01, 0xDA };
 -	BYTE signature[2] = { 0, 0 };
 -
 -	io->read_proc(signature, 1, sizeof(sgi_signature), handle);
 -
 -	return (memcmp(sgi_signature, signature, sizeof(sgi_signature)) == 0);
 -}
 -
 -static BOOL DLL_CALLCONV
 -SupportsExportDepth(int depth) {
 -  return FALSE;
 -}
 -
 -static BOOL DLL_CALLCONV 
 -SupportsExportType(FREE_IMAGE_TYPE type) {
 -  return FALSE;
 -}
 -
 -static FIBITMAP * DLL_CALLCONV
 -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
 -	int width = 0, height = 0, zsize = 0;
 -	int i, dim;
 -	int bitcount;
 -	SGIHeader sgiHeader;
 -	RLEStatus my_rle_status;
 -	FIBITMAP *dib = NULL;
 -	LONG *pRowIndex = NULL;
 -
 -	try {
 -		// read the header
 -		memset(&sgiHeader, 0, sizeof(SGIHeader));
 -		if(io->read_proc(&sgiHeader, 1, sizeof(SGIHeader), handle) < sizeof(SGIHeader)) {
 -		   throw SGI_LESS_THAN_HEADER_LENGTH;
 -		}
 -#ifndef FREEIMAGE_BIGENDIAN
 -		SwapHeader(&sgiHeader);
 -#endif
 -		if(sgiHeader.magic != 474) {
 -			throw FI_MSG_ERROR_MAGIC_NUMBER;
 -		}
 -		
 -		BOOL bIsRLE = (sgiHeader.storage == 1) ? TRUE : FALSE;
 -	
 -		// check for unsupported image types
 -		if (sgiHeader.bpc != 1) {
 -			// Expected one byte per color component
 -			throw SGI_16_BIT_COMPONENTS_NOT_SUPPORTED; 
 -		}
 -		if (sgiHeader.colormap != 0) {
 -			// Indexed or dithered images not supported
 -			throw SGI_COLORMAPS_NOT_SUPPORTED; 
 -		}
 -
 -		// get the width & height
 -		dim = sgiHeader.dimension;
 -		width = sgiHeader.xsize;
 -		if (dim < 3) {
 -			zsize = 1;
 -		} else {
 -			zsize = sgiHeader.zsize;
 -		}
 -
 -		if (dim < 2) {
 -			height = 1;
 -		} else {
 -			height = sgiHeader.ysize;
 -		}
 -		
 -		if(bIsRLE) {
 -			// read the Offset Tables 
 -			int index_len = height * zsize;
 -			pRowIndex = (LONG*)malloc(index_len * sizeof(LONG));
 -			if(!pRowIndex) {
 -				throw FI_MSG_ERROR_MEMORY;
 -			}
 -			
 -			if ((unsigned)index_len != io->read_proc(pRowIndex, sizeof(LONG), index_len, handle)) {
 -				throw SGI_EOF_IN_RLE_INDEX;
 -			}
 -			
 -#ifndef FREEIMAGE_BIGENDIAN		
 -			// Fix byte order in index
 -			for (i = 0; i < index_len; i++) {
 -				SwapLong((DWORD*)&pRowIndex[i]);
 -			}
 -#endif
 -			// Discard row size index
 -			for (i = 0; i < (int)(index_len * sizeof(LONG)); i++) {
 -				BYTE packed = 0;
 -				if( io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1 ) {
 -					throw SGI_EOF_IN_RLE_INDEX;
 -				}
 -			}
 -		}
 -		
 -		switch(zsize) {
 -			case 1:
 -				bitcount = 8;
 -				break;
 -			case 2:
 -				//Grayscale+Alpha. Need to fake RGBA
 -				bitcount = 32;
 -				break;
 -			case 3:
 -				bitcount = 24;
 -				break;
 -			case 4:
 -				bitcount = 32;
 -				break;
 -			default:
 -				throw SGI_INVALID_CHANNEL_COUNT;
 -		}
 -		
 -		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;
 -}
 -
 +// ========================================================== +// SGI Loader +// +// Design and implementation by +// - Sherman Wilcox +// - Noam Gat +// +// References :  +// ------------ +// - The SGI Image File Format, Version 1.0 +// http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html +// - SGI RGB Image Format +// http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/ +// +// +// This file is part of FreeImage 3 +// +// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY +// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES +// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE +// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED +// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT +// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY +// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL +// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER +// THIS DISCLAIMER. +// +// Use at your own risk! +// ========================================================== + +#include "FreeImage.h" +#include "Utilities.h" + +// ---------------------------------------------------------- +//   Constants + headers +// ---------------------------------------------------------- + +#ifdef _WIN32 +#pragma pack(push, 1) +#else +#pragma pack(1) +#endif + +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 { +		return pstatus->val; +	} +} + +static const char * DLL_CALLCONV +Format() { +  return "SGI"; +} + +static const char * DLL_CALLCONV +Description() { +  return "SGI Image Format"; +} + +static const char * DLL_CALLCONV +Extension() { +  return "sgi"; +} + +static const char * DLL_CALLCONV +RegExpr() { +  return NULL; +} + +static const char * DLL_CALLCONV +MimeType() { +  return "image/x-sgi"; +} + +static BOOL DLL_CALLCONV +Validate(FreeImageIO *io, fi_handle handle) { +	BYTE sgi_signature[2] = { 0x01, 0xDA }; +	BYTE signature[2] = { 0, 0 }; + +	io->read_proc(signature, 1, sizeof(sgi_signature), handle); + +	return (memcmp(sgi_signature, signature, sizeof(sgi_signature)) == 0); +} + +static BOOL DLL_CALLCONV +SupportsExportDepth(int depth) { +  return FALSE; +} + +static BOOL DLL_CALLCONV  +SupportsExportType(FREE_IMAGE_TYPE type) { +  return FALSE; +} + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { +	int width = 0, height = 0, zsize = 0; +	int i, dim; +	int bitcount; +	SGIHeader sgiHeader; +	RLEStatus my_rle_status; +	FIBITMAP *dib = NULL; +	LONG *pRowIndex = NULL; + +	try { +		// read the header +		memset(&sgiHeader, 0, sizeof(SGIHeader)); +		if(io->read_proc(&sgiHeader, 1, sizeof(SGIHeader), handle) < sizeof(SGIHeader)) { +		   throw SGI_LESS_THAN_HEADER_LENGTH; +		} +#ifndef FREEIMAGE_BIGENDIAN +		SwapHeader(&sgiHeader); +#endif +		if(sgiHeader.magic != 474) { +			throw FI_MSG_ERROR_MAGIC_NUMBER; +		} +		 +		BOOL bIsRLE = (sgiHeader.storage == 1) ? TRUE : FALSE; +	 +		// check for unsupported image types +		if (sgiHeader.bpc != 1) { +			// Expected one byte per color component +			throw SGI_16_BIT_COMPONENTS_NOT_SUPPORTED;  +		} +		if (sgiHeader.colormap != 0) { +			// Indexed or dithered images not supported +			throw SGI_COLORMAPS_NOT_SUPPORTED;  +		} + +		// get the width & height +		dim = sgiHeader.dimension; +		width = sgiHeader.xsize; +		if (dim < 3) { +			zsize = 1; +		} else { +			zsize = sgiHeader.zsize; +		} + +		if (dim < 2) { +			height = 1; +		} else { +			height = sgiHeader.ysize; +		} +		 +		if(bIsRLE) { +			// read the Offset Tables  +			int index_len = height * zsize; +			pRowIndex = (LONG*)malloc(index_len * sizeof(LONG)); +			if(!pRowIndex) { +				throw FI_MSG_ERROR_MEMORY; +			} +			 +			if ((unsigned)index_len != io->read_proc(pRowIndex, sizeof(LONG), index_len, handle)) { +				throw SGI_EOF_IN_RLE_INDEX; +			} +			 +#ifndef FREEIMAGE_BIGENDIAN		 +			// Fix byte order in index +			for (i = 0; i < index_len; i++) { +				SwapLong((DWORD*)&pRowIndex[i]); +			} +#endif +			// Discard row size index +			for (i = 0; i < (int)(index_len * sizeof(LONG)); i++) { +				BYTE packed = 0; +				if( io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1 ) { +					throw SGI_EOF_IN_RLE_INDEX; +				} +			} +		} +		 +		switch(zsize) { +			case 1: +				bitcount = 8; +				break; +			case 2: +				//Grayscale+Alpha. Need to fake RGBA +				bitcount = 32; +				break; +			case 3: +				bitcount = 24; +				break; +			case 4: +				bitcount = 32; +				break; +			default: +				throw SGI_INVALID_CHANNEL_COUNT; +		} +		 +		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; +} +  | 
