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

Encode() private method

private Encode ( System input, object codecData ) : FreeImageAPI.FIBITMAP
input System
codecData object
return FreeImageAPI.FIBITMAP
		private FI.FIBITMAP Encode( System.IO.Stream input, object codecData )
		{
			FI.FIBITMAP ret = new FI.FIBITMAP();
			ret.SetNull();
			ImageData imgData = codecData as ImageData;
			if ( imgData != null )
			{
				byte[] data = new byte[ (int)input.Length ];
				input.Read( data, 0, data.Length );
				IntPtr dataPtr = Memory.PinObject( data );
				PixelBox src = new PixelBox( imgData.width, imgData.height, imgData.depth, imgData.format, dataPtr );

				// The required format, which will adjust to the format
				// actually supported by FreeImage.
				PixelFormat requiredFormat = imgData.format;

				// determine the settings
				FI.FREE_IMAGE_TYPE imageType = FI.FREE_IMAGE_TYPE.FIT_UNKNOWN;

				PixelFormat determiningFormat = imgData.format;

				switch ( determiningFormat )
				{
					case PixelFormat.R5G6B5:
					case PixelFormat.B5G6R5:
					case PixelFormat.R8G8B8:
					case PixelFormat.B8G8R8:
					case PixelFormat.A8R8G8B8:
					case PixelFormat.X8R8G8B8:
					case PixelFormat.A8B8G8R8:
					case PixelFormat.X8B8G8R8:
					case PixelFormat.B8G8R8A8:
					case PixelFormat.R8G8B8A8:
					case PixelFormat.A4L4:
					case PixelFormat.BYTE_LA:
					case PixelFormat.R3G3B2:
					case PixelFormat.A4R4G4B4:
					case PixelFormat.A1R5G5B5:
					case PixelFormat.A2R10G10B10:
					case PixelFormat.A2B10G10R10:
						// I'd like to be able to use r/g/b masks to get FreeImage to load the data
						// in it's existing format, but that doesn't work, FreeImage needs to have
						// data in RGB[A] (big endian) and BGR[A] (little endian), always.
						if ( PixelUtil.HasAlpha( determiningFormat ) )
						{
							if ( FI.FreeImageEngine.IsLittleEndian )
							{
								requiredFormat = PixelFormat.BYTE_BGRA;
							}
							else
							{
								requiredFormat = PixelFormat.BYTE_RGBA;
							}

						}
						else
						{
							if ( FI.FreeImageEngine.IsLittleEndian )
							{
								requiredFormat = PixelFormat.BYTE_BGR;
							}
							else
							{
								requiredFormat = PixelFormat.BYTE_RGB;
							}
						}
						imageType = FI.FREE_IMAGE_TYPE.FIT_BITMAP;
						break;
					case PixelFormat.L8:
					case PixelFormat.A8:
						imageType = FI.FREE_IMAGE_TYPE.FIT_BITMAP;
						break;
					case PixelFormat.L16:
						imageType = FI.FREE_IMAGE_TYPE.FIT_UINT16;
						break;
					case PixelFormat.SHORT_GR:
						requiredFormat = PixelFormat.SHORT_RGB;
						break;
					case PixelFormat.SHORT_RGB:
						imageType = FI.FREE_IMAGE_TYPE.FIT_RGB16;
						break;
					case PixelFormat.SHORT_RGBA:
						imageType = FI.FREE_IMAGE_TYPE.FIT_RGBA16;
						break;
					case PixelFormat.FLOAT16_R:
						requiredFormat = PixelFormat.FLOAT32_R;
						break;
					case PixelFormat.FLOAT32_R:
						imageType = FI.FREE_IMAGE_TYPE.FIT_FLOAT;
						break;
					case PixelFormat.FLOAT16_GR:
					case PixelFormat.FLOAT16_RGB:
					case PixelFormat.FLOAT32_GR:
						requiredFormat = PixelFormat.FLOAT32_RGB;
						break;
					case PixelFormat.FLOAT32_RGB:
						imageType = FI.FREE_IMAGE_TYPE.FIT_RGBF;
						break;

					case PixelFormat.FLOAT16_RGBA:
						requiredFormat = PixelFormat.FLOAT32_RGBA;
						break;
					case PixelFormat.FLOAT32_RGBA:
						imageType = FI.FREE_IMAGE_TYPE.FIT_RGBAF;
						break;
					default:
						throw new AxiomException( "Not Supported image format :" + determiningFormat.ToString() );
				}//end switch

				// Check support for this image type & bit depth
				if ( !FI.FreeImage.FIFSupportsExportType( (FI.FREE_IMAGE_FORMAT)_freeImageType, imageType ) ||
					!FI.FreeImage.FIFSupportsExportBPP( (FI.FREE_IMAGE_FORMAT)_freeImageType, PixelUtil.GetNumElemBits( requiredFormat ) ) )
				{
					// Ok, need to allocate a fallback
					// Only deal with RGBA . RGB for now
					switch ( requiredFormat )
					{
						case PixelFormat.BYTE_RGBA:
							requiredFormat = PixelFormat.BYTE_RGB;
							break;
						case PixelFormat.BYTE_BGRA:
							requiredFormat = PixelFormat.BYTE_BGR;
							break;
						default:
							break;
					}
				}

				bool conversionRequired = false;
				input.Position = 0;
				byte[] srcData = new byte[ (int)input.Length ];
				input.Read( srcData, 0, srcData.Length );
				IntPtr srcDataPtr = Memory.PinObject( srcData );
				int bpp = PixelUtil.GetNumElemBits( requiredFormat );
				if ( !FI.FreeImage.FIFSupportsExportBPP( (FI.FREE_IMAGE_FORMAT)_freeImageType, bpp ) )
				{
					if ( bpp == 32 && PixelUtil.HasAlpha( imgData.format ) && FI.FreeImage.FIFSupportsExportBPP( (FI.FREE_IMAGE_FORMAT)_freeImageType, 24 ) )
					{
						// drop to 24 bit (lose alpha)
						if ( FI.FreeImage.IsLittleEndian() )
						{
							requiredFormat = PixelFormat.BYTE_BGR;
						}
						else
						{
							requiredFormat = PixelFormat.BYTE_RGB;
						}
					}
					else if ( bpp == 128 && PixelUtil.HasAlpha( imgData.format ) && FI.FreeImage.FIFSupportsExportBPP( (FI.FREE_IMAGE_FORMAT)_freeImageType, 96 ) )
					{
						//// drop to 96-bit floating point
						requiredFormat = PixelFormat.FLOAT32_RGB;
					}
				}

				PixelBox convBox = new PixelBox( imgData.width, imgData.height, 1, requiredFormat );
				if ( requiredFormat != imgData.format )
				{
					conversionRequired = true;
					// Allocate memory
					byte[] convData = new byte[ convBox.ConsecutiveSize ];
					convBox.Data = Memory.PinObject( convData );

					PixelBox newSrc = new PixelBox( imgData.width, imgData.height, 1, imgData.format, dataPtr );
					PixelConverter.BulkPixelConversion( newSrc, convBox );
					srcDataPtr = convBox.Data;
				}

				ret = FI.FreeImage.AllocateT( imageType, imgData.width, imgData.height, bpp );
				if ( ret.IsNull )
				{
					if ( conversionRequired )
					{
						Memory.UnpinObject( srcData );
						convBox = null;
					}

					throw new AxiomException( "FreeImage.AllocateT failed - possibly out of memory. " );
				}

				if ( requiredFormat == PixelFormat.L8 || requiredFormat == PixelFormat.A8 )
				{
					// Must explicitly tell FreeImage that this is greyscale by setting
					// a "grey" palette (otherwise it will save as a normal RGB
					// palettized image).
					FI.FIBITMAP tmp = FI.FreeImage.ConvertToGreyscale( ret );
					FI.FreeImage.Unload( ret );
					ret = tmp;
				}

				int dstPitch = (int)FI.FreeImage.GetPitch( ret );
				int srcPitch = imgData.width * PixelUtil.GetNumElemBytes( requiredFormat );
				// Copy data, invert scanlines and respect FreeImage pitch
				IntPtr pSrc = srcDataPtr;
				IntPtr pDest = FI.FreeImage.GetBits( ret );
				unsafe
				{
					byte* byteSrcData = (byte*)( pSrc );
					byte* byteDstData = (byte*)( pDest );
					for ( int y = 0; y < imgData.height; y++ )
					{
						byteSrcData = byteSrcData + ( imgData.height - y - 1 ) * srcPitch;
						Memory.Copy( pSrc, pDest, srcPitch );
						byteDstData += dstPitch;
					}
				}

				if ( conversionRequired )
				{
					// delete temporary conversion area
					Memory.UnpinObject( srcData );
					convBox = null;
				}
			}
			return ret;
		}
		public override void Encode( System.IO.Stream input, System.IO.Stream output, params object[] args )

Same methods

FreeImageCodec::Encode ( System input, System output ) : void