Axiom.Plugins.FreeImageCodecs.FreeImageCodec.Decode C# (CSharp) Method

Decode() public method

public Decode ( System input, System output ) : object
input System
output System
return object
		public override object Decode( System.IO.Stream input, System.IO.Stream output, params object[] args )
		{
			// Set error handler
			FI.FreeImageEngine.Message += new FI.OutputMessageFunction( FreeImageLoadErrorHandler );
			// Buffer stream into memory (TODO: override IO functions instead?)
			byte[] data = new byte[ (int)input.Length ];
			input.Read( data, 0, data.Length );
			IntPtr datPtr = Memory.PinObject( data );
			FI.FIMEMORY fiMem = FI.FreeImage.OpenMemory( datPtr, (uint)data.Length );
			FI.FREE_IMAGE_FORMAT ff = (FI.FREE_IMAGE_FORMAT)_freeImageType;
			FI.FIBITMAP fiBitmap = FI.FreeImage.LoadFromMemory( (FI.FREE_IMAGE_FORMAT)_freeImageType, fiMem, FI.FREE_IMAGE_LOAD_FLAGS.DEFAULT );
			if ( fiBitmap.IsNull )
			{
			    Debugger.Break();
				throw new AxiomException( "Error decoding image" );
			}

			ImageData imgData = new ImageData();
			//output = new System.IO.MemoryStream();
			imgData.depth = 1;// only 2D formats handled by this codec
			imgData.width = (int)FI.FreeImage.GetWidth( fiBitmap );
			imgData.height = (int)FI.FreeImage.GetHeight( fiBitmap );
			imgData.numMipMaps = 0;// no mipmaps in non-DDS

			// Must derive format first, this may perform conversions
			FI.FREE_IMAGE_TYPE imageType = FI.FreeImage.GetImageType( fiBitmap );
			FI.FREE_IMAGE_COLOR_TYPE colorType = FI.FreeImage.GetColorType( fiBitmap );
			int bpp = (int)FI.FreeImage.GetBPP( fiBitmap );

			switch ( imageType )
			{
				case FI.FREE_IMAGE_TYPE.FIT_UNKNOWN:
				case FI.FREE_IMAGE_TYPE.FIT_COMPLEX:
				case FI.FREE_IMAGE_TYPE.FIT_UINT32:
				case FI.FREE_IMAGE_TYPE.FIT_INT32:
				case FI.FREE_IMAGE_TYPE.FIT_DOUBLE:
				default:
					throw new AxiomException( "Unknown or unsupported image format" );
					break;
				case FI.FREE_IMAGE_TYPE.FIT_BITMAP:
					// Standard image type
					// Perform any colour conversions for greyscale
					if ( colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_MINISWHITE || colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_MINISBLACK )
					{
						FI.FIBITMAP newBitmap = FI.FreeImage.ConvertToGreyscale( fiBitmap );
						// free old bitmap and replace
						FI.FreeImage.Unload( fiBitmap );
						fiBitmap = newBitmap;
						// get new formats
						bpp = (int)FI.FreeImage.GetBPP( fiBitmap );
						colorType = FI.FreeImage.GetColorType( fiBitmap );
					}
					// Perform any colour conversions for RGB
					else if ( bpp < 8 || colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_PALETTE || colorType == FI.FREE_IMAGE_COLOR_TYPE.FIC_CMYK )
					{
						FI.FIBITMAP newBitmap;
						if ( FI.FreeImage.IsTransparent( fiBitmap ) )
						{
							// convert to 32 bit to preserve the transparency 
							// (the alpha byte will be 0 if pixel is transparent)
							newBitmap = FI.FreeImage.ConvertTo32Bits( fiBitmap );
						}
						else
						{
							// no transparency - only 3 bytes are needed
							newBitmap = FI.FreeImage.ConvertTo24Bits( fiBitmap );
						}

						// free old bitmap and replace
						FI.FreeImage.Unload( fiBitmap );
						fiBitmap = newBitmap;
						// get new formats
						bpp = (int)FI.FreeImage.GetBPP( fiBitmap );
						colorType = FI.FreeImage.GetColorType( fiBitmap );
					}

					// by this stage, 8-bit is greyscale, 16/24/32 bit are RGB[A]
					switch ( bpp )
					{
						case 8:
							imgData.format = PixelFormat.L8;
							break;
						case 16:
							// Determine 555 or 565 from green mask
							// cannot be 16-bit greyscale since that's FIT_UINT16
							if ( FI.FreeImage.GetGreenMask( fiBitmap ) == FI.FreeImage.FI16_565_GREEN_MASK )
							{
								imgData.format = PixelFormat.R5G6B5;
							}
							else
							{
								// FreeImage doesn't support 4444 format so must be 1555
								imgData.format = PixelFormat.A1R5G5B5;
							}
							break;
						case 24:
							// FreeImage differs per platform
							//     PixelFormat.BYTE_BGR[A] for little endian (== PixelFormat.ARGB native)
							//     PixelFormat.BYTE_RGB[A] for big endian (== PixelFormat.RGBA native)
							if ( FI.FreeImage.IsLittleEndian() )
							{
								imgData.format = PixelFormat.BYTE_BGR;
							}
							else
							{
								imgData.format = PixelFormat.BYTE_RGB;
							}
							break;
						case 32:
							if ( FI.FreeImage.IsLittleEndian() )
							{
								imgData.format = PixelFormat.BYTE_BGRA;
							}
							else
							{
								imgData.format = PixelFormat.BYTE_RGBA;
							}
							break;


					};
					break;
				case FI.FREE_IMAGE_TYPE.FIT_UINT16:
				case FI.FREE_IMAGE_TYPE.FIT_INT16:
					// 16-bit greyscale
					imgData.format = PixelFormat.L16;
					break;
				case FI.FREE_IMAGE_TYPE.FIT_FLOAT:
					// Single-component floating point data
					imgData.format = PixelFormat.FLOAT32_R;
					break;
				case FI.FREE_IMAGE_TYPE.FIT_RGB16:
					imgData.format = PixelFormat.SHORT_RGB;
					break;
				case FI.FREE_IMAGE_TYPE.FIT_RGBA16:
					imgData.format = PixelFormat.SHORT_RGBA;
					break;
				case FI.FREE_IMAGE_TYPE.FIT_RGBF:
					imgData.format = PixelFormat.FLOAT32_RGB;
					break;
				case FI.FREE_IMAGE_TYPE.FIT_RGBAF:
					imgData.format = PixelFormat.FLOAT32_RGBA;
					break;
			}

			IntPtr srcData = FI.FreeImage.GetBits( fiBitmap );
			int srcPitch = (int)FI.FreeImage.GetPitch( fiBitmap );
			// Final data - invert image and trim pitch at the same time
			int dstPitch = imgData.width * PixelUtil.GetNumElemBytes( imgData.format );
			imgData.size = dstPitch * imgData.height;
			// Bind output buffer
			byte[] outPutData = new byte[ imgData.size ];
			unsafe
			{
				fixed ( byte* pDstPtr = outPutData )//(byte*)Memory.PinObject( outPutData );
				{
					byte* pDst = pDstPtr;
					byte* pSrc = (byte*)IntPtr.Zero;
					byte* byteSrcData = (byte*)srcData;
					for ( int y = 0; y < imgData.height; y++ )
					{
						pSrc = byteSrcData + ( imgData.height - y - 1 ) * srcPitch;
						Memory.Copy( (IntPtr)pSrc, (IntPtr)pDst, dstPitch );
						pDst += dstPitch;
					}
				}
			}
			//for ( int z = 0; z < outPutData.Length; z += 4 )
			//{
			//    byte tmp = outPutData[ z ];
			//    outPutData[ z ] = outPutData[ z + 2 ];
			//    outPutData[ z + 2 ] = tmp;
			//}
			//output = new System.IO.MemoryStream( outPutData );//.Write( outPutData, 0, outPutData.Length );
			output.Write( outPutData, 0, outPutData.Length );
			FI.FreeImage.Unload( fiBitmap );
			FI.FreeImage.CloseMemory( fiMem );


			return imgData;
		}
		/// <summary>