(* ImageEn Build 7.0.0.06.2637 @ 7-4-17 14:58:42.679 *) (* Copyright (c) 1998-2017 by Carlotta Calandra. All rights reserved. Copyright (c) 2011-2017 by Xequte Software. This software comes without express or implied warranty. In no case shall the author be liable for any damage or unwanted behavior of any computer hardware and/or software. Author grants you the right to include the component in your application, whether COMMERCIAL, SHAREWARE, or FREEWARE. ImageEn, IEvolution and ImageEn ActiveX may not be included in any commercial, shareware or freeware libraries or components. www.ImageEn.com *) (* File version 1006 *) unit iewic; {$R-} {$Q-} {$I ie.inc} {$IFDEF IEINCLUDEWIC} interface uses Windows, Messages, SysUtils, Classes, ActiveX, Graphics, Controls, imageenio, hyiedefs, iexBitmaps, ieds, iewia, dialogs, hyieutils; procedure IEHDPRead(Stream: TStream; Bitmap: TIEBitmap; var IOParams: TIOParams; var xProgress: TProgressRec; Preview: boolean); procedure IEHDPWrite(Stream: TStream; Bitmap: TIEBitmap; var IOParams: TIOParams; var xProgress: TProgressRec); function IEHDPFrameCount(const FileName: WideString): integer; function IEWICAvailable: boolean; procedure IEWICResample(SrcImg: TIEBaseBitmap; DstImg: TIEBaseBitmap; SrcAlpha: TIEBaseBitmap; FilterType: TResampleFilter; OnProgressFunction: TIEProgressEvent; OnProgressSender: TObject); type IE_ProgressNotificationCallback=function(pvData: pointer; uFrameNum: dword; operation: dword; dblProgress: double): HResult; stdcall; IE_IWICBitmapCodecProgressNotification = interface(IUnknown) ['{64C1024E-C3CF-4462-8078-88C2B11C46D9}'] function RegisterProgressNotification(pfnProgressNotification: IE_ProgressNotificationCallback; pvData: pointer; dwProgressFlags: dword): HResult; stdcall; end; IE_IWICStream = interface(IStream) ['{135FF860-22B7-4ddf-B0F6-218F4F299A43}'] function InitializeFromIStream(pIStream: IIEStream): HResult; stdcall; function InitializeFromFilename(wzFileName: pwchar; dwDesiredAccess: dword): HResult; stdcall; function InitializeFromMemory(pbBuffer: pbyte; cbBufferSize: dword): HResult; stdcall; function InitializeFromIStreamRegion: HResult; stdcall; end; IE_WICRect = record X: longint; Y: longint; Width: longint; Height: longint; end; IE_PWICRect = ^IE_WICRect; IE_WICBitmapPaletteType = DWORD; IE_WICColor = DWORD; IE_PWICColor = ^IE_WICColor; IE_IWICBitmapSource = interface; IE_IWICPalette = interface(IUnknown) ['{00000040-a8f2-4877-ba0a-fd2b6645fb94}'] function InitializePredefined(ePaletteType: IE_WICBitmapPaletteType; fAddTransparentColor: longbool): HResult; stdcall; function InitializeCustom(pColors: IE_PWICColor; cCount: DWORD): HResult; stdcall; function InitializeFromBitmap(pISurface: IE_IWICBitmapSource; cCount: DWORD; fAddTransparentColor: longbool): HResult; stdcall; function InitializeFromPalette(pIPalette: IE_IWICPalette): HResult; stdcall; function GetType(out pePaletteType: IE_WICBitmapPaletteType): HResult; stdcall; function GetColorCount(out pcCount: DWORD): HResult; stdcall; function GetColors(cCount: DWORD; pColors: IE_PWICColor; out pcActualColors: DWORD): HResult; stdcall; function IsBlackWhite(out pfIsBlackWhite: longbool): HResult; stdcall; function IsGrayscale(out pfIsGrayscale: longbool): HResult; stdcall; function HasAlpha(out pfHasAlpha: longbool): HResult; stdcall; end; IE_IWICBitmapSource = interface(IUnknown) ['{00000120-a8f2-4877-ba0a-fd2b6645fb94}'] function GetSize(out puiWidth: DWORD; out puiHeight: DWORD): HResult; stdcall; function GetPixelFormat(out pPixelFormat: TGUID): HResult; stdcall; function GetResolution(out pDpiX: double; out pDpiY: double): HResult; stdcall; function CopyPalette(pIPalette: IE_IWICPalette): HResult; stdcall; function CopyPixels(prc: IE_PWICRect; cbStride: DWORD; cbBufferSize: DWORD; pbBuffer: pbyte): HResult; stdcall; end; IE_IWICFormatConverter = interface(IE_IWICBitmapSource) ['{00000301-a8f2-4877-ba0a-fd2b6645fb94}'] function Initialize(pISource: IE_IWICBitmapSource; const dstFormat: TGUID; dither: dword; pIPalette: IE_IWICPalette; alphaThresholdPercent: double; paletteTranslate: dword): HResult; stdcall; function CanConvert(const srcPixelFormat: TGUID; const dstPixelFormat: TGUID; out pfCanConvert: longbool): HResult; stdcall; end; IE_IWICMetadataQueryReader = interface(IUnknown) ['{30989668-E1C9-4597-B395-458EEDB808DF}'] function GetContainerFormat: HResult; stdcall; function GetLocation: HResult; stdcall; function GetMetadataByName(wzName: pwchar; var pvarValue: PROPVARIANT): HResult; stdcall; function GetEnumerator: HResult; stdcall; end; IE_IWICMetadataQueryWriter = interface(IE_IWICMetadataQueryReader) ['{A721791A-0DEF-4d06-BD91-2118BF1DB10B}'] function SetMetadataByName(wzName: pwchar; const pvarValue: PROPVARIANT): HResult; stdcall; function RemoveMetadataByName(wzName: pwchar): HResult; stdcall; end; IE_IWICBitmapFrameDecode = interface(IE_IWICBitmapSource) ['{3B16811B-6A43-4ec9-A813-3D930C13B940}'] function GetMetadataQueryReader(out ppIMetadataQueryReader: IE_IWICMetadataQueryReader): HResult; stdcall; function GetColorContexts: HResult; stdcall; function GetThumbnail(out ppIThumbnail: IE_IWICBitmapSource): HResult; stdcall; end; IE_IWICBitmapDecoder = interface(IUnknown) ['{9EDDE9E7-8DEE-47ea-99DF-E6FAF2ED44BF}'] function QueryCapability: HResult; stdcall; function Initialize: HResult; stdcall; function GetContainerFormat: HResult; stdcall; function GetDecoderInfo: HResult; stdcall; function CopyPalette: HResult; stdcall; function GetMetadataQueryReader: HResult; stdcall; function GetPreview: HResult; stdcall; function GetColorContexts: HResult; stdcall; function GetThumbnail: HResult; stdcall; function GetFrameCount(out pCount: longint): HResult; stdcall; function GetFrame(index: dword; out ppIBitmapFrame: IE_IWICBitmapFrameDecode): HResult; stdcall; end; IE_PROPBAG2 = record dwType: dword; vt: word; cfType: word; dwHint: dword; pstrName: pwchar; clsid: TGUID; end; IE_PPROPBAG2 = ^IE_PROPBAG2; IE_PPROPVARIANT = ^PROPVARIANT; IE_IPropertyBag2 = interface(IUnknown) ['{22F55882-280B-11d0-A8A9-00A0C90C2004}'] function Read: HResult; stdcall; function Write(cProperties: dword; pPropBag: IE_PPROPBAG2; pvarValue: IE_PPROPVARIANT): HResult; stdcall; function CountProperties: HResult; stdcall; function GetPropertyInfo: HResult; stdcall; function LoadObject: HResult; stdcall; end; IE_IWICBitmapFrameEncode = interface(IUnknown) ['{00000105-a8f2-4877-ba0a-fd2b6645fb94}'] function Initialize(pIEncoderOptions: IE_IPropertyBag2): HResult; stdcall; function SetSize(uiWidth: dword; uiHeight: dword): HResult; stdcall; function SetResolution(dpiX: double; dpiY: double): HResult; stdcall; function SetPixelFormat(const pPixelFormat: TGUID): HResult; stdcall; function SetColorContexts: HResult; stdcall; function SetPalette: HResult; stdcall; function SetThumbnail: HResult; stdcall; function WritePixels(lineCount: dword; cbStride: dword; cbBufferSize: dword; pbPixels: pbyte): HResult; stdcall; function WriteSource: HResult; stdcall; function Commit: HResult; stdcall; function GetMetadataQueryWriter(out ppIMetadataQueryWriter: IE_IWICMetadataQueryWriter): HResult; stdcall; end; IE_IWICBitmapEncoder = interface(IUnknown) ['{00000103-a8f2-4877-ba0a-fd2b6645fb94}'] function Initialize(pIStream: IStream; cacheOption: dword): HResult; stdcall; function GetContainerFormat: HResult; stdcall; function GetEncoderInfo: HResult; stdcall; function SetColorContexts: HResult; stdcall; function SetPalette: HResult; stdcall; function SetThumbnail: HResult; stdcall; function SetPreview: HResult; stdcall; function CreateNewFrame(out ppIFrameEncode: IE_IWICBitmapFrameEncode; out ppIEncoderOptions: IE_IPropertyBag2): HResult; stdcall; function Commit: HResult; stdcall; function GetMetadataQueryWriter: HResult; stdcall; end; IE_WICInProcPointer = pbyte; IE_IWICBitmapLock = interface(IUnknown) ['{00000123-a8f2-4877-ba0a-fd2b6645fb94}'] function GetSize(out puiWidth: DWORD; out puiHeight: DWORD): HResult; stdcall; function GetStride(out pcbStride: DWORD): HResult; stdcall; function GetDataPointer(out pcbBufferSize: DWORD; out ppbData: IE_WICInProcPointer): HResult; stdcall; function GetPixelFormat(out pPixelFormat: TGUID): HResult; stdcall; end; IE_IWICBitmap = interface(IE_IWICBitmapSource) ['{00000121-a8f2-4877-ba0a-fd2b6645fb94}'] function Lock(prcLock: IE_PWICRect; flags: DWORD; out ppILock: IE_IWICBitmapLock): HResult; stdcall; function SetPalette(pIPalette: IE_IWICPalette): HResult; stdcall; function SetResolution(dpiX: double; dpiY: double): HResult; stdcall; end; IE_WICBitmapCreateCacheOption = DWORD; IE_WICBitmapInterpolationMode = DWORD; IE_IWICBitmapScaler = interface(IE_IWICBitmapSource) ['{00000302-a8f2-4877-ba0a-fd2b6645fb94}'] function Initialize(pISource: IE_IWICBitmapSource; uiWidth: DWORD; uiHeight: DWORD; mode: IE_WICBitmapInterpolationMode): HResult; stdcall; end; IE_IWICImagingFactory = interface(IUnknown) ['{ec5ec8a9-c395-4314-9c77-54d7a935ff70}'] function CreateDecoderFromFilename: HResult; stdcall; function CreateDecoderFromStream(pIStream: IStream; const pguidVendor: TGUID; metadataOptions: dword; out ppIDecoder: IE_IWICBitmapDecoder): HResult; stdcall; function CreateDecoderFromFileHandle: HResult; stdcall; function CreateComponentInfo: HResult; stdcall; function CreateDecoder(const guidContainerFormat: TGuid; const pguidVendor: TGuid; out ppIDecoder: IE_IWICBitmapDecoder): HResult; stdcall; function CreateEncoder(const guidContainerFormat: TGUID; const pguidVendor: TGUID; out ppIEncoder: IE_IWICBitmapEncoder): HResult; stdcall; function CreatePalette(out ppIPalette: IE_IWICPalette): HResult; stdcall; function CreateFormatConverter(out ppIFormatConverter: IE_IWICFormatConverter): HResult; stdcall; function CreateBitmapScaler(out ppIBitmapScaler: IE_IWICBitmapScaler): HResult; stdcall; function CreateBitmapClipper: HResult; stdcall; function CreateBitmapFlipRotator: HResult; stdcall; function CreateStream(out ppIWICStream: IE_IWICStream): HResult; stdcall; function CreateColorContext: HResult; stdcall; function CreateColorTransformer: HResult; stdcall; function CreateBitmap: HResult; stdcall; function CreateBitmapFromSource(pIBitmapSource: IE_IWICBitmapSource; option: IE_WICBitmapCreateCacheOption; out ppIBitmap: IE_IWICBitmap): HResult; stdcall; function CreateBitmapFromSourceRect: HResult; stdcall; function CreateBitmapFromMemory: HResult; stdcall; function CreateBitmapFromHBITMAP: HResult; stdcall; function CreateBitmapFromHICON: HResult; stdcall; function CreateComponentEnumerator: HResult; stdcall; function CreateFastMetadataEncoderFromDecoder: HResult; stdcall; function CreateFastMetadataEncoderFromFrameDecode: HResult; stdcall; function CreateQueryWriter: HResult; stdcall; function CreateQueryWriterFromReader: HResult; stdcall; end; const // WICBitmapDitherType IE_WICBitmapDitherTypeNone = $00000000; IE_WICBitmapDitherTypeSolid = $00000000; IE_WICBitmapDitherTypeOrdered4x4 = $00000001; IE_WICBitmapDitherTypeOrdered8x8 = $00000002; IE_WICBitmapDitherTypeOrdered16x16 = $00000003; IE_WICBitmapDitherTypeSpiral4x4 = $00000004; IE_WICBitmapDitherTypeSpiral8x8 = $00000005; IE_WICBitmapDitherTypeDualSpiral4x4 = $00000006; IE_WICBitmapDitherTypeDualSpiral8x8 = $00000007; IE_WICBitmapDitherTypeErrorDiffusion = $00000008; // WICBitmapPaletteType IE_WICBitmapPaletteTypeCustom = $0; IE_WICBitmapPaletteTypeMedianCut = $1; IE_WICBitmapPaletteTypeFixedBW = $2; IE_WICBitmapPaletteTypeFixedHalftone8 = $3; IE_WICBitmapPaletteTypeFixedHalftone27 = $4; IE_WICBitmapPaletteTypeFixedHalftone64 = $5; IE_WICBitmapPaletteTypeFixedHalftone125 = $6; IE_WICBitmapPaletteTypeFixedHalftone216 = $7; IE_WICBitmapPaletteTypeFixedWebPalette = IE_WICBitmapPaletteTypeFixedHalftone216; IE_WICBitmapPaletteTypeFixedHalftone252 = $8; IE_WICBitmapPaletteTypeFixedHalftone256 = $9; IE_WICBitmapPaletteTypeFixedGray4 = $a; IE_WICBitmapPaletteTypeFixedGray16 = $b; IE_WICBitmapPaletteTypeFixedGray256 = $c; IE_WICBITMAPPALETTETYPE_FORCE_DWORD = $7fffffff; // WICBitmapInterpolationMode IE_WICBitmapInterpolationModeNearestNeighbor = 0; IE_WICBitmapInterpolationModeLinear = $1; IE_WICBitmapInterpolationModeCubic = $2; IE_WICBitmapInterpolationModeFant = $3; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// type {!! TIEWICTIFFCompressionMethod Declaration TIEWICTIFFCompressionMethod = (ieWICTiffCompressionNone, ieWICTiffCompressionCCITT3, ieWICTiffCompressionCCITT4, ieWICTiffCompressionLZW, ieWICTiffCompressionRLE, ieWICTiffCompressionZIP); Description Specifies the Tagged Image File Format (TIFF) compression options. Value Description ieWICTiffCompressionNone No compression. ieWICTiffCompressionCCITT3 A CCITT3 compression algorithm. This algorithm is only valid for 1bpp pixel formats. ieWICTiffCompressionCCITT4 A CCITT4 compression algorithm. This algorithm is only valid for 1bpp pixel formats. ieWICTiffCompressionLZW A LZW compression algorithm. ieWICTiffCompressionRLE A RLE compression algorithm. This algorithm is only valid for 1bpp pixel formats. ieWICTiffCompressionZIP A ZIP compression algorithm.
!!} TIEWICTIFFCompressionMethod = ( ieWICTiffCompressionDontCare , // don't use ieWICTiffCompressionNone, ieWICTiffCompressionCCITT3, ieWICTiffCompressionCCITT4, ieWICTiffCompressionLZW, ieWICTiffCompressionRLE, ieWICTiffCompressionZIP); {!! TIEWICReader Description TIEWICReader class encapsulates some Microsoft Windows Imaging Component (WIC) interfaces and allows you to load Microsoft HD Photo and other WIC installed file formats. WIC preinstalled decoders are TIFF, PNG, GIF, ICO, BMP, JPEG, HDP. Note: Requires Windows XP (SP2) with .Net 3.0, Windows Vista or newer. Examples // loads input.hdp in ImageEnView1, which is the same as ImageEnView1.IO.LoadFromFile('input.hdp') with TIEWICReader.Create do begin Open('input.hdp', ioHDP); GetFrame(0, ImageEnView1.IEBitmap, ImageEnView1.IO.Params); Free; end; ImageEnView1.Update; // loads input.jpg in ImageEnView1 with TIEWICReader.Create do begin Open('input.jpg', ioJPEG); GetFrame(0, ImageEnView1.IEBitmap, ImageEnView1.IO.Params); Free; end; ImageEnView1.Update; // loads page 2 from input.tif to ImageEnView1 with TIEWICReader.Create do begin Open('input.tif', ioTIFF); GetFrame(2, ImageEnView1.IEBitmap, ImageEnView1.IO.Params); Free; end; ImageEnView1.Update; Methods and Properties !!} TIEWICReader = class private fOLEInitialized: boolean; fWICImagingFactory: IE_IWICImagingFactory; fDecoder: IE_IWICBitmapDecoder; fFrame: IE_IWICBitmapFrameDecode; fQueryReader: IE_IWICMetadataQueryReader; fDPIX: double; fDPIY: double; fStream: TStream; fStreamBase: int64; fFileStream: TIEWideFileStream; function GetFrameCount: integer; public constructor Create; destructor Destroy; override; function IsAvailable: boolean; function Open(Stream: TStream; fileType: TIOFileType): boolean; overload; function Open(const FileName: WideString; fileType: TIOFileType = ioUnknown): boolean; overload; procedure Close; procedure GetFrame(frameIndex: integer; destBitmap: TIEBitmap; IOParams: TIOParams=nil; Aborting: pboolean=nil); property FrameCount: integer read GetFrameCount; function FrameWidth(): DWORD; // call after GetFrame function FrameHeight(): DWORD; // call after GetFrame {!! TIEWICReader.DPIX Declaration property DPIX: double; Description X-axis dots per inch (dpi) resolution. This property is filled by method. See also: !!} property DPIX: double read fDPIX write fDPIX; {!! TIEWICReader.DPIY Declaration property DPIY: double; Description Y-axis dots per inch (dpi) resolution. This property is filled by method. See also: !!} property DPIY: double read fDPIY write fDPIY; function QueryMetadata(const query: string): PROPVARIANT; end; {!! TIEWICWriter Description TIEWICWriter class encapsulates some Microsoft Windows Imaging Component (WIC) interfaces and allows you to write Microsoft HD Photo and other WIC installed file formats. WIC preinstalled encoders are TIFF, PNG, GIF, BMP, JPEG, HDP. Note: Requires Windows XP (SP2) with .Net 3.0, Windows Vista or newer. Examples // saves ImageEnView1 to output.hdp, which is the same as ImageEnView1.IO.SaveToFile('output.hdp') with TIEWICWriter.Create do begin Open('output.hdp', ioHDP); PutFrame(ImageEnView1.IEBitmap, ImageEnView1.IO.Params); Free; end; // saves ImageEnView1 to output.jpg with TIEWICWriter.Create do begin Open('output.jpg', ioJPEG); PutFrame(ImageEnView1.IEBitmap, ImageEnView1.IO.Params); Free; end; // saves ImageEnView1 and ImageEnView2 as two pages in output.tif with TIEWICWriter.Create do begin Open('output.tif', ioTIFF); PutFrame(ImageEnView1.IEBitmap, ImageEnView1.IO.Params); PutFrame(ImageEnView2.IEBitmap, ImageEnView2.IO.Params); Free; end; Methods and Properties Canonical Encoder Parameter Properties Specific HD Photo Encoder Parameter Properties !!} TIEWICWriter = class private fOLEInitialized: boolean; fWICImagingFactory: IE_IWICImagingFactory; fEncoder: IE_IWICBitmapEncoder; fDPIX: double; fDPIY: double; fImageQuality: double; // -1 = encoder default fCompressionQuality: double; // -1 = encoder default fLossless: boolean; fUseCodecOptions: boolean; fQuality: integer; // enabled if fUseCodecOptions=true fOverlap: integer; // enabled if fUseCodecOptions=true fSubsampling: integer; // enabled if fUseCodecOptions=true fHorizontalTileSlices: integer; fVerticalTileSlices: integer; fFrequencyOrder: boolean; fTIFFCompressionMethod: TIEWICTIFFCompressionMethod; fStream: TStream; fStreamBase: int64; fFileStream: TIEWideFileStream; protected public constructor Create; destructor Destroy; override; function IsAvailable: boolean; function Open(const FileName: WideString; fileType: TIOFileType): boolean; overload; function Open(Stream: TStream; fileType: TIOFileType): boolean; overload; procedure Close; procedure PutFrame(srcBitmap: TIEBitmap; IOParams: TIOParams = nil); {!! TIEWICWriter.DPIX Declaration property DPIX: double; Description X-axis dots per inch (dpi) resolution. You must set this property before each call. See also: !!} property DPIX: double read fDPIX write fDPIX; {!! TIEWICWriter.DPIY Declaration property DPIY: double; Description Y-axis dots per inch (dpi) resolution. You must set this property before each call. See also: !!} property DPIY: double read fDPIY write fDPIY; //// Canonical Encoder Parameter Properties //// {!! TIEWICWriter.ImageQuality Declaration property ImageQuality: double; Description 0.0 specifies the lowest possible fidelity rendition and 1.0 specifies the highest fidelity, which for HD Photo results in mathematically lossless compression. You must set this property before each call. Example with TIEWICWriter.Create do begin Open('output.hdp', ioHDP); ImageQuality := 0.7; PutFrame(ImageEnView1.IEBitmap); Free; end; !!} property ImageQuality: double read fImageQuality write fImageQuality; {!! TIEWICWriter.CompressionQuality Declaration property CompressionQuality: double; Description 0.0 specifies the least efficient compression scheme available, typically resulting in a fast encode but larger output. A value of 1.0 specifies the most efficient scheme available, typically taking more time to encode but producing smaller output. HD Photo does not support this encoder option. You must set this property before each call. !!} property CompressionQuality: double read fCompressionQuality write fCompressionQuality; {!! TIEWICWriter.Lossless Declaration property Lossless: boolean; Description Setting this parameter to true enables mathematically lossless compression mode and overrides the parameter setting. Default: False Note: You must set this property before each call. Example with TIEWICWriter.Create do begin Open('output.hdp', ioHDP); Lossless := true; PutFrame(ImageEnView1.IEBitmap); Free; end; !!} property Lossless: boolean read fLossless write fLossless; //// Specific HD Photo encoder parameter properties //// {!! TIEWICWriter.UseCodecOptions Declaration property UseCodecOptions: boolean; Description If this parameter is true, the , and parameters are used in place of the encoder canonical parameter. When false, the , and parameters are set based on a table lookup determined by the parameter. Default: False Note: You must set this property before each call. Example with TIEWICWriter.Create do begin Open('output.hdp', ioHDP); UseCodecOptions := true; Quality := 10; PutFrame(ImageEnView1.IEBitmap); Free; end; !!} property UseCodecOptions: boolean read fUseCodecOptions write fUseCodecOptions; {!! TIEWICWriter.Quality Declaration property Quality: integer; Description This parameter controls the compression quality for the main image. A value of 1 sets lossless mode. Increasing values result in higher compression ratios and lower image quality. Default: 1 Notes: - must be true - You must set this property before each call Example with TIEWICWriter.Create do begin Open('output.hdp', ioHDP); UseCodecOptions := true; Quality := 10; PutFrame(ImageEnView1.IEBitmap); Free; end; !!} property Quality: integer read fQuality write fQuality; {!! TIEWICWriter.Overlap Declaration property Overlap: integer; Description This parameter selects the optional overlap processing level: Value Description 0 No overlap processing is enabled. 1 One level of overlap processing is enabled, modifying 4x4 block encoded values based on values of neighboring blocks. 2 Two levels of overlap processing are enabled; in addition to the first level processing, encoded values of 16x16 macro blocks are modified based on the values of neighboring macro blocks.
Default: 1 Notes: -
must be true - You must set this property before each call !!} property Overlap: integer read fOverlap write fOverlap; {!! TIEWICWriter.Subsampling Declaration property Subsampling: integer; Description This parameter only applies to RGB images. It enables additional compression in the chroma space, preserving luminance detail at the expense of color detail: Value Description 3 4: 4: 4 encoding preserves full chroma resolution. 2 4: 2: 2 encoding reduces chroma resolution to 1/2 of luminance resolution. 1 4: 2: 0 encoding reduces chroma resolution to 1/4 of luminance resolution. 0 4: 0: 0 encoding discards all chroma content, preserving luminance only. Because the codec uses a slightly modified definition of luminance to improve performance, it is preferred to convert an RGB image to monochrome before encoding rather than use this chroma subsampling mode.
Any value greater than 3 returns an error. The default value is 3.
must be true. You must set this property before each call. !!} property Subsampling: integer read fSubsampling write fSubsampling; {!! TIEWICWriter.HorizontalTileSlices Declaration property HorizontalTileSlices: integer; Description HorizontalTileSlices and specify the horizontal and vertical tiling of the image prior to compression encoding for the most optimal region decode performance. Dividing the image into rectangular tiles during encoding makes it possible to decode regions of the image without the need to process the entire compressed data stream. The default value of 0 specifies no subdivision, so the entire image is treated as a single tile. A value of 1 for each parameter will create a single horizontal and a single vertical division, effectively dividing the image into four equally sized tiles. The maximum value of 4095 for each parameter divides the image into 4096 tile rows with 4096 tiles per row. In other words, the parameter values equal the number of horizontal and vertical tiles (respectively) minus 1. A tile can never be smaller than 16 pixels in width or height, so the HD Photo encoder may adjust this parameter to maintain the required minimum tile size. Because there is storage and processing overhead associated with each tile, these values should be chosen carefully to meet the specific scenario and unless there is a very specific reason, large numbers of small tiles should be avoided. The default value for both parameters is 0. You must set this property before each call. !!} property HorizontalTileSlices: integer read fHorizontalTileSlices write fHorizontalTileSlices; {!! TIEWICWriter.VerticalTileSlices Declaration property VerticalTileSlices: integer; Description and VerticalTileSlices specify the horizontal and vertical tiling of the image prior to compression encoding for the most optimal region decode performance. Dividing the image into rectangular tiles during encoding makes it possible to decode regions of the image without the need to process the entire compressed data stream. The default value of 0 specifies no subdivision, so the entire image is treated as a single tile. A value of 1 for each parameter will create a single horizontal and a single vertical division, effectively dividing the image into four equally sized tiles. The maximum value of 4095 for each parameter divides the image into 4096 tile rows with 4096 tiles per row. In other words, the parameter values equal the number of horizontal and vertical tiles (respectively) minus 1. A tile can never be smaller than 16 pixels in width or height, so the HD Photo encoder may adjust this parameter to maintain the required minimum tile size. Because there is storage and processing overhead associated with each tile, these values should be chosen carefully to meet the specific scenario and unless there is a very specific reason, large numbers of small tiles should be avoided. The default value for both parameters is 0. You must set this property before each call. !!} property VerticalTileSlices: integer read fVerticalTileSlices write fVerticalTileSlices; {!! TIEWICWriter.FrequencyOrder Declaration property FrequencyOrder: boolean; Description This parameter specifies that the image must be encoded in frequency order, with the lowest frequency data appearing first in the file, and image content grouped by its frequency rather than its spatial orientation. Organizing a file by frequency order provides the highest performance results for any frequency-based decoding, and is the preferred option. Device implementations of HD Photo encoders may choose to organize a file in spatial order to reduce the memory footprint required during encoding. The default value is true and it is recommended that applications and devices always use frequency order unless there are performance or application-specific reasons to use spatial order. You must set this property before each call. !!} property FrequencyOrder: boolean read fFrequencyOrder write fFrequencyOrder; ///// TIFF specific compression parameters ///// {!! TIEWICWriter.TIFFCompressionMethod Declaration property TIFFCompressionMethod: ; Description Specifies the Tagged Image File Format (TIFF) compression options. You must set this property before each call. Example // writes a TIFF using CCITT4 compression (make sure ImageEnView1.IEBitmap.PixelFormat=ie1g) with TIEWICWriter.Create do begin Open('output.tif', ioTIFF); TIFFCompressionMethod := ieWICTiffCompressionCCITT4; PutFrame(ImageEnView1.IEBitmap); Free; end; !!} property TIFFCompressionMethod: TIEWICTIFFCompressionMethod read fTIFFCompressionMethod write fTIFFCompressionMethod; end; // Exposes TIEBitmap as IWICBitmapSource TIEWICBitmapWrapper = class(TInterfacedObject, IE_IWICBitmapSource) private m_bitmap: TIEBaseBitmap; m_alpha: TIEBaseBitmap; public constructor Create(Bitmap: TIEBaseBitmap; Alpha: TIEBaseBitmap); destructor Destroy(); override; // implements IE_IWICBitmapSource function GetSize(out puiWidth: DWORD; out puiHeight: DWORD): HResult; stdcall; function GetPixelFormat(out pPixelFormat: TGUID): HResult; stdcall; function GetResolution(out pDpiX: double; out pDpiY: double): HResult; stdcall; function CopyPalette(pIPalette: IE_IWICPalette): HResult; stdcall; function CopyPixels(prc: IE_PWICRect; cbStride: DWORD; cbBufferSize: DWORD; pbBuffer: pbyte): HResult; stdcall; end; // provides common base functionality for format converters, scaler, etc... TIEWICBaseFunctionality = class private m_OLEInitialized: boolean; m_WICImagingFactory: IE_IWICImagingFactory; public constructor Create(); destructor Destroy; override; function IsAvailable(): boolean; end; // Encapsulates IWICFormatConverter functionality TIEWICFormatConverter = class(TIEWICBaseFunctionality) private m_paletteType: DWORD; m_ditherType: DWORD; m_palette: IE_IWICPalette; public constructor Create(); function Convert(Source: TIEBitmap; Dest: TIEBitmap; DestPixelFormat: TIEPixelFormat; CheckParametersOnly: boolean; OnProgressFunction: TIEProgressEvent = nil; OnProgressSender: TObject = nil): boolean; procedure SetPalette(Palette: array of TRGB); property PaletteType: DWORD read m_paletteType write m_paletteType; property DitherType: DWORD read m_ditherType write m_ditherType; end; // Encapsulates IWICBitmapScaler functionality TIEWICBitmapScaler = class(TIEWICBaseFunctionality) public //constructor Create(); function Resample(Source: TIEBaseBitmap; SourceAlpha: TIEBaseBitmap; Dest: TIEBaseBitmap; DestAlpha: TIEBaseBitmap; Width: DWORD; Height: DWORD; Mode: IE_WICBitmapInterpolationMode; OnProgressFunction: TIEProgressEvent = nil; OnProgressSender: TObject = nil): boolean; end; implementation uses ieview, tiffilt, iesettings, imageenproc; const ole32 = 'ole32.dll'; function CoCreateInstance(const clsid: TGUID; unkOuter: IUnknown; dwClsContext: Longint; const iid: TGUID; out pv): HResult; stdcall; external ole32 name 'CoCreateInstance'; function OleInitialize(pwReserved: Pointer): HResult; stdcall; external ole32 name 'OleInitialize'; procedure OleUninitialize; stdcall; external ole32 name 'OleUninitialize'; const CLSCTX_INPROC_SERVER = 1; CLSID_WICImagingFactory: TGUID = (D1:$cacaf262; D2:$9370; D3:$4615; D4:($a1, $3b, $9f, $55, $39, $da, $4c, $a)); CLSID_WICBmpDecoder: TGUID = (D1:$6b462062; D2:$7cbf; D3:$400d; D4:($9f, $db, $81, $3d, $d1, $f, $27, $78)); CLSID_WICPngDecoder: TGUID = (D1:$389ea17b; D2:$5078; D3:$4cde; D4:($b6, $ef, $25, $c1, $51, $75, $c7, $51)); CLSID_WICIcoDecoder: TGUID = (D1:$c61bfcdf; D2:$2e0f; D3:$4aad; D4:($a8, $d7, $e0, $6b, $af, $eb, $cd, $fe)); CLSID_WICJpegDecoder: TGUID = (D1:$9456a480; D2:$e88b; D3:$43ea; D4:($9e, $73, $b, $2d, $9b, $71, $b1, $ca)); CLSID_WICGifDecoder: TGUID = (D1:$381dda3c; D2:$9ce9; D3:$4834; D4:($a2, $3e, $1f, $98, $f8, $fc, $52, $be)); CLSID_WICTiffDecoder: TGUID = (D1:$b54e85d9; D2:$fe23; D3:$499f; D4:($8b, $88, $6a, $ce, $a7, $13, $75, $2b)); CLSID_WICWmpDecoder: TGUID = (D1:$a26cec36; D2:$234c; D3:$4950; D4:($ae, $16, $e3, $4a, $ac, $e7, $1d, $0d)); CLSID_WICBmpEncoder: TGUID = (D1:$69be8bb4; D2:$d66d; D3:$47c8; D4:($86, $5a, $ed, $15, $89, $43, $37, $82)); CLSID_WICPngEncoder: TGUID = (D1:$27949969; D2:$876a; D3:$41d7; D4:($94, $47, $56, $8f, $6a, $35, $a4, $dc)); CLSID_WICJpegEncoder: TGUID = (D1:$1a34f5c1; D2:$4a5a; D3:$46dc; D4:($b6, $44, $1f, $45, $67, $e7, $a6, $76)); CLSID_WICGifEncoder: TGUID = (D1:$114f5598; D2:$0b22; D3:$40a0; D4:($86, $a1, $c8, $3e, $a4, $95, $ad, $bd)); CLSID_WICTiffEncoder: TGUID = (D1:$0131be10; D2:$2001; D3:$4c5f; D4:($a9, $b0, $cc, $88, $fa, $b6, $4c, $e8)); CLSID_WICWmpEncoder: TGUID = (D1:$ac4ce3cb; D2:$e1c1; D3:$44cd; D4:($82, $15, $5a, $16, $65, $50, $9e, $c2)); GUID_WICPixelFormatDontCare: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $00)); GUID_WICPixelFormat1bppIndexed: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $01)); GUID_WICPixelFormat8bppIndexed: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $04)); GUID_WICPixelFormatBlackWhite: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $05)); GUID_WICPixelFormat8bppGray: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $08)); GUID_WICPixelFormat16bppGray: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $0b)); GUID_WICPixelFormat24bppBGR: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $0c)); GUID_WICPixelFormat24bppRGB: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $0d)); GUID_WICPixelFormat32bppBGRA: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $0f)); GUID_WICPixelFormat32bppPBGRA: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $10)); GUID_WICPixelFormat32bppRGBA: TGUID = (D1:$f5c7ad2d; D2:$6a8d; D3:$43dd; D4:($a7, $a8, $a2, $99, $35, $26, $1a, $e9)); GUID_WICPixelFormat32bppPRGBA: TGUID = (D1:$3cc4a650; D2:$a527; D3:$4d37; D4:($a9, $16, $31, $42, $c7, $eb, $ed, $ba)); GUID_WICPixelFormat48bppRGB: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $15)); GUID_WICPixelFormat32bppCMYK: TGUID = (D1:$6fddc324; D2:$4e03; D3:$4bfe; D4:($b1, $85, $3d, $77, $76, $8d, $c9, $1c)); GUID_ContainerFormatBmp: TGUID = (D1:$0af1d87e; D2:$fcfe; D3:$4188; D4:($bd, $eb, $a7, $90, $64, $71, $cb, $e3)); GUID_ContainerFormatPng: TGUID = (D1:$1b7cfaf4; D2:$713f; D3:$473c; D4:($bb, $cd, $61, $37, $42, $5f, $ae, $af)); GUID_ContainerFormatIco: TGUID = (D1:$a3a860c4; D2:$338f; D3:$4c17; D4:($91, $9a, $fb, $a4, $b5, $62, $8f, $21)); GUID_ContainerFormatJpeg: TGUID = (D1:$19e4a5aa; D2:$5662; D3:$4fc5; D4:($a0, $c0, $17, $58, $02, $8e, $10, $57)); GUID_ContainerFormatTiff: TGUID = (D1:$163bcc30; D2:$e2e9; D3:$4f0b; D4:($96, $1d, $a3, $e9, $fd, $b7, $88, $a3)); GUID_ContainerFormatGif: TGUID = (D1:$1f8a5601; D2:$7d4d; D3:$4cbd; D4:($9c, $82, $1b, $c8, $d4, $ee, $b9, $a5)); GUID_ContainerFormatWmp: TGUID = (D1:$57a37caa; D2:$367a; D3:$4540; D4:($91, $6b, $f1, $83, $c5, $09, $3a, $4b)); GUID_VendorMicrosoft: TGUID = (D1:$f0e749ca; D2:$edef; D3:$4589; D4:($a7, $3a, $ee, $e, $62, $6a, $2a, $2b)); // WICDecodeOptions WICDecodeMetadataCacheOnDemand = $00000000; WICDecodeMetadataCacheOnLoad = $00000001; // WICBitmapEncoderCacheOption WICBitmapEncoderCacheInMemory = $00000000; WICBitmapEncoderCacheTempFile = $00000001; WICBitmapEncoderNoCache = $00000002; // IE_WICBitmapCreateCacheOption WICBitmapNoCache = $00000000; WICBitmapCacheOnDemand = $00000001; WICBitmapCacheOnLoad = $00000002; // STREAM_SEEK STREAM_SEEK_SET = 0; STREAM_SEEK_CUR = 1; STREAM_SEEK_END = 2; PROPBAG2_TYPE_UNDEFINED = 0; PROPBAG2_TYPE_DATA = 1; PROPBAG2_TYPE_URL = 2; PROPBAG2_TYPE_OBJECT = 3; PROPBAG2_TYPE_STREAM = 4; PROPBAG2_TYPE_STORAGE = 5; PROPBAG2_TYPE_MONIKER = 6; WINCODEC_ERR_PALETTEUNAVAILABLE = HResult($88982f45); function ConvertWICPixelFormatToIEBitmapPixelFormat(wicFactory: IE_IWICImagingFactory; source: IE_IWICBitmapSource; out hasAlpha: boolean): TIEPixelFormat; var wicPixelFormat: TGUID; palette: IE_IWICPalette; lbHasAlpha: longbool; begin source.GetPixelFormat(wicPixelFormat); hasAlpha := false; if CompareGUID(wicPixelFormat, GUID_WICPixelFormat1bppIndexed) then result := ie1g // to check! else if CompareGUID(wicPixelFormat, GUID_WICPixelFormat8bppIndexed) then begin result := ie8p; palette := nil; wicFactory.CreatePalette(palette); source.CopyPalette(palette); palette.HasAlpha(lbHasAlpha); hasAlpha := lbHasAlpha; end else if CompareGUID(wicPixelFormat, GUID_WICPixelFormatBlackWhite) then result := ie1g else if CompareGUID(wicPixelFormat, GUID_WICPixelFormat8bppGray) then result := ie8g else if CompareGUID(wicPixelFormat, GUID_WICPixelFormat16bppGray) then result := ie16g else if CompareGUID(wicPixelFormat, GUID_WICPixelFormat24bppBGR) then result := ie24RGB else if CompareGUID(wicPixelFormat, GUID_WICPixelFormat32bppBGRA) then begin hasAlpha := true; result := ie24RGB; end else if CompareGUID(wicPixelFormat, GUID_WICPixelFormat48bppRGB) then result := ie48RGB else if CompareGUID(wicPixelFormat, GUID_WICPixelFormat32bppCMYK) then result := ieCMYK else result := ieNull; end; function ConvertIEBitmapPixelFormatToWICPixelFormat(IEBitmapPixelFormat: TIEPixelFormat): TGUID; begin case IEBitmapPixelFormat of ie1g: result := GUID_WICPixelFormatBlackWhite; ie8p: result := GUID_WICPixelFormat8bppIndexed; ie8g: result := GUID_WICPixelFormat8bppGray; ie16g: result := GUID_WICPixelFormat16bppGray; ie24RGB: result := GUID_WICPixelFormat24bppBGR; ieCMYK: result := GUID_WICPixelFormat32bppCMYK; ie48RGB: result := GUID_WICPixelFormat48bppRGB; else raise EIEException.Create('Unsupported pixel format'); end; end; procedure ConvertWICBitmapToIEBitmap(wicFactory: IE_IWICImagingFactory; source: IE_IWICBitmapSource; dest: TIEBitmap; nativePixelFormat: boolean = true); var converter: IE_IWICFormatConverter; pixelFormatGUID: TGUID; pixelFormat: TIEPixelFormat; i, j: longint; w, h: DWORD; rc: IE_WICRect; pb: pbyte; hasAlpha: boolean; rgbaBuf: array of TRGBA; byteBuf: array of byte; pb_dstalpha: pbyte; palette: IE_IWICPalette; paletteColors: array of IE_WICColor; colorCount: DWORD; begin source.GetPixelFormat(pixelFormatGUID); pixelFormat := ConvertWICPixelFormatToIEBitmapPixelFormat(wicFactory, source, hasAlpha); if nativePixelFormat then begin // special cases if CompareGUID(pixelFormatGUID, GUID_WICPixelFormat1bppIndexed) then begin pixelFormatGUID := GUID_WICPixelFormat8bppIndexed; pixelFormat := ie8p; end else if CompareGUID(pixelFormatGUID, GUID_WICPixelFormat8bppIndexed) then begin // palette not supported at the moment pixelFormatGUID := GUID_WICPixelFormat24bppBGR; pixelFormat := ie24RGB; end; if pixelFormat = ieNull then begin pixelFormatGUID := GUID_WICPixelFormat24bppBGR; pixelFormat := ie24RGB; end; end else begin // only 1bit and 24bitRGB are supported if CompareGUID(pixelFormatGUID, GUID_WICPixelFormatBlackWhite) then pixelFormat := ie1g else begin pixelFormatGUID := GUID_WICPixelFormat24bppBGR; pixelFormat := ie24RGB; end; end; converter := nil; wicFactory.CreateFormatConverter(converter); converter.Initialize(source, pixelFormatGUID, IE_WICBitmapDitherTypeNone, nil, 0.0, 0); converter.GetSize(w, h); dest.Allocate(w, h, pixelFormat); rc.X := 0; rc.Width := w; rc.Height := 1; for i := 0 to h - 1 do begin rc.Y := i; converter.CopyPixels(@rc, dest.Rowlen, dest.Rowlen, dest.ScanLine[i]); end; if dest.PixelFormat = ieCMYK then begin // CMYK channels need to be inverted for i := 0 to h - 1 do begin pb := dest.ScanLine[i]; for j := w * 4 - 1 downto 0 do begin pb^ := 255 - pb^; inc(pb); end; end; end; source.GetPixelFormat(pixelFormatGUID); // read again pixelFormatGUID (can be changed by previous code) if hasAlpha then begin if CompareGUID(pixelFormatGUID, GUID_WICPixelFormat32bppBGRA) then begin SetLength(rgbaBuf, w); rc.X := 0; rc.Width := w; rc.Height := 1; for i := 0 to h - 1 do begin rc.Y := i; source.CopyPixels(@rc, w * 4, w * 4, @rgbaBuf[0]); pb_dstalpha := dest.AlphaChannel.ScanLine[i]; for j := 0 to w - 1 do begin pb_dstalpha^ := rgbaBuf[j].a; inc(pb_dstalpha); end; end; end else if CompareGUID(pixelFormatGUID, GUID_WICPixelFormat8bppIndexed) then begin SetLength(byteBuf, w); rc.X := 0; rc.Width := w; rc.Height := 1; palette := nil; wicFactory.CreatePalette(palette); source.CopyPalette(palette); palette.GetColorCount(colorCount); SetLength(paletteColors, colorCount); palette.GetColors(colorCount, @paletteColors[0], colorCount); for i := 0 to h - 1 do begin rc.Y := i; source.CopyPixels(@rc, w, w, @byteBuf[0]); pb_dstalpha := dest.AlphaChannel.ScanLine[i]; for j := 0 to w - 1 do begin pb_dstalpha^ := (paletteColors[byteBuf[j]] shr 24) and $FF; inc(pb_dstalpha); end; end; end; dest.AlphaChannel.SyncFull(); end; converter := nil; end; // DestAlpha can be nil procedure CopyWICBitmapSourceToIEBitmap(WICImagingFactory: IE_IWICImagingFactory; bitmapSource: IE_IWICBitmapSource; Dest: TIEBaseBitmap; DestAlpha: TIEBaseBitmap; OnProgressFunction: TIEProgressEvent = nil; OnProgressSender: TObject = nil); var iePixelFormat: TIEPixelFormat; hasAlpha: boolean; i, j: integer; w, h, colorCount: DWORD; paletteColors: array of IE_WICColor; palette: IE_IWICPalette; rc: IE_WICRect; lper, per: integer; pb_src: pbyte; pb_dst: pbyte; pb_dstalpha: pbyte; rowbuf: array of byte; begin // get actual pixel format iePixelFormat := ConvertWICPixelFormatToIEBitmapPixelFormat(WICImagingFactory, bitmapSource, hasAlpha); // copy pixels bitmapSource.GetSize(w, h); if assigned(DestAlpha) and (Dest is TIEBitmap) and ((Dest as TIEBitmap).AlphaChannel = DestAlpha) then begin // DestAlpha belongs to Dest (that is a TIEBitmap, so Dest.AlphaChannel == DestAlpha) Dest.Allocate(w, h, iePixelFormat); DestAlpha := (Dest as TIEBitmap).AlphaChannel; end else Dest.Allocate(w, h, iePixelFormat); rc.X := 0; rc.Width := w; rc.Height := 1; lper := -1; for i := 0 to h - 1 do begin rc.Y := i; if hasAlpha and (iePixelFormat = ie24RGB) then begin SetLength(rowbuf, w * 4); bitmapSource.CopyPixels(@rc, w * 4, w * 4, @rowbuf[0]); pb_src := @rowbuf[0]; pb_dst := Dest.ScanLine[i]; if assigned(DestAlpha) then begin pb_dstalpha := DestAlpha.ScanLine[i]; for j := 0 to w - 1 do begin pb_dst^ := pb_src^; inc(pb_dst); inc(pb_src); // b pb_dst^ := pb_src^; inc(pb_dst); inc(pb_src); // g pb_dst^ := pb_src^; inc(pb_dst); inc(pb_src); // r pb_dstalpha^ := pb_src^; inc(pb_dstalpha); inc(pb_src); // a end; end else begin for j := 0 to w - 1 do begin pb_dst^ := pb_src^; inc(pb_dst); inc(pb_src); // b pb_dst^ := pb_src^; inc(pb_dst); inc(pb_src); // g pb_dst^ := pb_src^; inc(pb_dst); inc(pb_src); // r inc(pb_src); // bypass alpha end; end; end else bitmapSource.CopyPixels(@rc, Dest.Rowlen, Dest.Rowlen, Dest.ScanLine[i]); if assigned(OnProgressFunction) then begin per := trunc(i / h * 100.0); if per <> lper then begin lper := per; OnProgressFunction(OnProgressSender, per); end; end; end; // copy palette if iePixelFormat = ie8p then begin palette := nil; WICImagingFactory.CreatePalette(palette); bitmapSource.CopyPalette(palette); palette.GetColorCount(colorCount); SetLength(paletteColors, colorCount); palette.GetColors(colorCount, @paletteColors[0], colorCount); Dest.PaletteUsed := colorCount; for i := 0 to colorCount - 1 do Dest.Palette[i] := CreateRGB((paletteColors[i] shr 16) and $FF, (paletteColors[i] shr 8) and $FF, paletteColors[i] and $FF); end; end; ////////////////////////////////////////////////////////////////// // TIEWICReader constructor TIEWICReader.Create; begin inherited Create; fOLEInitialized := Succeeded(OleInitialize(nil)); fWICImagingFactory := nil; fDecoder := nil; fFrame := nil; fQueryReader := nil; fStream := nil; fStreamBase := 0; fFileStream := nil; fDPIX := IEGlobalSettings().DefaultDPIX; fDPIY := IEGlobalSettings().DefaultDPIY; CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER, IE_IWICImagingFactory, fWICImagingFactory); end; destructor TIEWICReader.Destroy; begin Close(); fWICImagingFactory := nil; if fOLEInitialized then OleUninitialize; inherited; end; {!! TIEWICReader.Close Declaration procedure Close; Description Closes currently open stream or file freeing allocated resources. This method is implicitly called by Free method. Example with TIEWICReader.Create do begin Open('input.hdp', ioHDP); GetFrame(0, ImageEnView1.IEBitmap, ImageEnView1.IO.Params); Free; // Calls Close() implicitly end; ImageEnView1.Update; !!} procedure TIEWICReader.Close; begin if assigned(fFileStream) then FreeAndNil(fFileStream); fQueryReader := nil; fFrame := nil; fDecoder := nil; end; {!! TIEWICReader.IsAvailable Declaration function IsAvailable: boolean; Description Returns true if WIC is available. This should always be true on Windows Vista or newer (or Windows XP SP2 with .NET 3.0). See also: Example with TIEWICReader.Create do if IsAvailable then begin Open('input.hdp', ioHDP); GetFrame(0, ImageEnView1.IEBitmap, ImageEnView1.IO.Params); Free; end; ImageEnView1.Update; !!} function TIEWICReader.IsAvailable: boolean; begin result := (fWICImagingFactory<>nil) and IEWICAvailable(); end; {!! TIEWICReader.Open Declaration function Open(Stream: TStream; fileType: ): boolean; overload; function Open(const FileName: WideString; fileType: = ioUnknown): boolean; overload; Description Opens a stream or file, enabling subsequent calls to . For streams, the must be specified (one of: ioBMP, ioPNG, ioICO, ioJPEG, ioGIF, ioTIFF, ioHDP). For files, the is based on the file extension if not specified. You should call Free or in order to terminate reading. Example with TIEWICReader.Create do begin Open('input.hdp', ioHDP); GetFrame(0, ImageEnView1.IEBitmap, ImageEnView1.IO.Params); Free; // Calls Close() implicitly end; ImageEnView1.Update; !!} function TIEWICReader.Open(Stream: TStream; fileType: TIOFileType): boolean; var DecoderGuid: TGUID; begin result := false; if not IsAvailable() then exit; fStream := Stream; fStreamBase := Stream.Position; case fileType of ioBMP: DecoderGuid := CLSID_WICBmpDecoder; ioPNG: DecoderGuid := CLSID_WICPngDecoder; ioICO: DecoderGuid := CLSID_WICIcoDecoder; ioJPEG: DecoderGuid := CLSID_WICJpegDecoder; ioGIF: DecoderGuid := CLSID_WICGifDecoder; ioTIFF: DecoderGuid := CLSID_WICTiffDecoder; ioHDP: DecoderGuid := CLSID_WICWmpDecoder; else exit; end; fDecoder := nil; fWICImagingFactory.CreateDecoderFromStream(TStreamAdapter.Create(Stream), DecoderGuid, WICDecodeMetadataCacheOnLoad, fDecoder); if fDecoder = nil then exit; result := true; end; function TIEWICReader.Open(const FileName: WideString; fileType: TIOFileType = ioUnknown): boolean; begin if fileType = ioUnknown then fileType := IEFilenameToInternalFileType( Filename ); fFileStream := TIEWideFileStream.create(FileName, fmOpenRead or fmShareDenyWrite); result := Open(fFileStream, fileType); end; {!! TIEWICReader.FrameCount Declaration property FrameCount: integer; Description Returns the total number of frames in the image. Example with TIEWICReader.Create do begin Open('input.tif', ioTIFF); fCount := FrameCount; for i := 0 to fCount-1 do GetFrame(i, bitmap[i]); Free; end; !!} function TIEWICReader.GetFrameCount: integer; begin result := 0; if not IsAvailable() or not assigned(fDecoder) then exit; fDecoder.GetFrameCount(result); end; {!! TIEWICReader.GetFrame Declaration procedure GetFrame(frameIndex: integer; destBitmap: ; IOParams: = nil; Aborting: pboolean = nil); Description Retrieves the specified frame of the image. If IOParams is specified then it is filled also with EXIF metatags. See also: Example with TIEWICReader.Create do begin Open('input.tif', ioTIFF); fCount := FrameCount; for i := 0 to fCount-1 do GetFrame(i, bitmap[i]); Free; end; !!} // IOParams can be nil // Aborting can be nil procedure TIEWICReader.GetFrame(frameIndex: integer; destBitmap: TIEBitmap; IOParams: TIOParams; Aborting: pboolean); var thumb: IE_IWICBitmapSource; lp: int64; nativePixelFormat: boolean; begin if not IsAvailable() or not assigned(fDecoder) then begin if assigned(Aborting) then Aborting^ := true; exit; end; // load frame "frameIndex" fFrame := nil; fDecoder.GetFrame(frameIndex, fFrame); // get info fFrame.GetResolution(fDPIX, fDPIY); // get metadata fQueryReader := nil; fFrame.GetMetadataQueryReader(fQueryReader); if assigned(IOParams) and not IOParams.IsNativePixelFormat then nativePixelFormat := false else nativePixelFormat := true; if assigned(IOParams) and IOParams.GetThumbnail then begin // get thumbnail of this frame thumb := nil; fFrame.GetThumbnail(thumb); if assigned(thumb) then // thumb available, get it ConvertWICBitmapToIEBitmap(fWICImagingFactory, thumb, destBitmap, nativePixelFormat) else // thumb not available, get full frame ConvertWICBitmapToIEBitmap(fWICImagingFactory, fFrame, destBitmap, nativePixelFormat); end else // get full image ConvertWICBitmapToIEBitmap(fWICImagingFactory, fFrame, destBitmap, nativePixelFormat); if assigned(IOParams) then begin lp := fStream.Position; fStream.Position := fStreamBase; IELoadParamsFromTIFF(fStream, IOParams, IOParams.ImageIndex); // load EXIF and other TIFF compatible tags fStream.Position := lp; // restores as WIC expects // assign non exif tags IOParams.BitsPerSample := destBitmap.BitCount div destBitmap.ChannelCount; IOParams.SamplesPerPixel := destBitmap.ChannelCount; IOParams.OriginalWidth := FrameWidth; IOParams.OriginalHeight := FrameHeight; IOParams.Width := destBitmap.Width; IOParams.Height := destBitmap.Height; IOParams.DpiX := trunc(DPIX); IOParams.DpiY := trunc(DPIY); end; end; {!! TIEWICReader.FrameWidth Declaration function FrameWidth(): DWORD; Description Retrieves the width of the frame. !!} function TIEWICReader.FrameWidth(): DWORD; var h: DWORD; begin result := 0; if assigned(fFrame) then fFrame.GetSize(result, h); end; {!! TIEWICReader.FrameHeight Declaration function FrameHeight(): DWORD; Description Retrieves the height of the frame. !!} function TIEWICReader.FrameHeight(): DWORD; var w: DWORD; begin result := 0; if assigned(fFrame) then fFrame.GetSize(w, result); end; function TIEWICReader.QueryMetadata(const query: string): PROPVARIANT; begin if not IsAvailable() or not assigned(fDecoder) then exit; if assigned(fQueryReader) then begin FillChar(result, sizeof(PROPVARIANT), 0); fQueryReader.GetMetadataByName(pwchar(WideString(query)), result); end; end; ////////////////////////////////////////////////////////////////// // TIEWICWriter constructor TIEWICWriter.Create; begin inherited Create; fOLEInitialized := Succeeded(OleInitialize(nil)); fWICImagingFactory := nil; fDPIX := IEGlobalSettings().DefaultDPIX; fDPIY := IEGlobalSettings().DefaultDPIY; fImageQuality := -1; fCompressionQuality := -1; fLossless := false; UseCodecOptions := false; fQuality := 1; fOverlap := 1; fSubsampling := 3; fHorizontalTileSlices := 0; fVerticalTileSlices := 0; fFrequencyOrder := true; fTIFFCompressionMethod := ieWICTiffCompressionNone; fEncoder := nil; fStream := nil; fStreamBase := 0; fFileStream := nil; CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER, IE_IWICImagingFactory, fWICImagingFactory); end; destructor TIEWICWriter.Destroy; begin Close(); fWICImagingFactory := nil; if fOLEInitialized then OleUninitialize; inherited; end; {!! TIEWICWriter.IsAvailable Declaration function IsAvailable: boolean; Description Returns true if WIC is available. This should always be true on Windows Vista or newer (or Windows XP SP2 with .NET 3.0). See also: Example with TIEWICWriter.Create do if IsAvailable then begin Open('output.hdp', ioHDP); PutFrame(ImageEnView1.IEBitmap, ImageEnView1.IO.Params); Free; end; !!} function TIEWICWriter.IsAvailable: boolean; begin result := fWICImagingFactory <> nil; end; {!! TIEWICWriter.Open Declaration function Open(Stream: TStream; fileType: ): boolean; function Open(const FileName: WideString; fileType: ): boolean; Description Creates specified image format in stream or file, enabling subsequent calls to calls. You should call Free or in order to commit changes. Example // saves ImageEnView1 to output.hdp, which is the same as ImageEnView1.IO.SaveToFile('output.hdp') with TIEWICWriter.Create do begin Open('output.hdp', ioHDP); PutFrame(ImageEnView1.IEBitmap, ImageEnView1.IO.Params); Free; end; !!} function TIEWICWriter.Open(Stream: TStream; fileType: TIOFileType): boolean; var ContainerGuid: TGUID; begin result := false; if not IsAvailable() then exit; fStream := Stream; fStreamBase := Stream.Position; case fileType of ioBMP: ContainerGuid := GUID_ContainerFormatBmp; ioPNG: ContainerGuid := GUID_ContainerFormatPng; ioJPEG: ContainerGuid := GUID_ContainerFormatJpeg; ioGIF: ContainerGuid := GUID_ContainerFormatGif; ioTIFF: ContainerGuid := GUID_ContainerFormatTiff; ioHDP: ContainerGuid := GUID_ContainerFormatWmp; else exit; end; fEncoder := nil; fWICImagingFactory.CreateEncoder(ContainerGuid, GUID_VendorMicrosoft, fEncoder); if fEncoder = nil then exit; fEncoder.Initialize(TStreamAdapter.Create(Stream), WICBitmapEncoderNoCache); result := true; end; function TIEWICWriter.Open(const FileName: WideString; fileType: TIOFileType): boolean; begin fFileStream := TIEWideFileStream.Create(FileName, fmCreate); result := Open(fFileStream, fileType); end; {!! TIEWICWriter.Close Declaration procedure Close; Description Commit changes to output stream or file. This method is implicitly called by Free method. !!} procedure TIEWICWriter.Close; begin if assigned(fEncoder) then begin fEncoder.Commit; fEncoder := nil; end; if assigned(fFileStream) then FreeAndNil(fFileStream); end; procedure SetPropertyBag(prop: IE_IPropertyBag2; const name: string; value: variant; propType: TVarType); var propName: IE_PROPBAG2; propValue: PROPVARIANT; begin FillChar(propName, sizeof(IE_PROPBAG2), 0); propName.dwType := PROPBAG2_TYPE_DATA; propName.vt := propType; propName.pstrName := pwchar(WideString(name)); propValue.vt := propType; case propType of VT_R4: propValue.fltVal := value; VT_BOOL: propValue.boolVal := value; VT_UI1: propValue.bVal := value; VT_UI2: propValue.uiVal := value; else assert(false); // unsupported property type end; prop.Write(1, @propName, @propValue); end; {!! TIEWICWriter.PutFrame Declaration procedure PutFrame(srcBitmap: ; IOParams: = nil); Description Adds a new frame to current open stream or file. You can call multiple PutFrame only if the writing file format accepts more than one frame. If IOParams is specified parameters (DPI, compression) are read from it. PutFrame doesn't write EXIF metatags: you must use to inject EXIF in HDPhoto or TIFF files. It is important that you close the stream/file before inject EXIF metatags. Example // saves ImageEnView1 to output.hdp, which is the same as ImageEnView1.IO.SaveToFile('output.hdp') with TIEWICWriter.Create do begin Open('output.hdp', ioHDP); PutFrame(ImageEnView1.IEBitmap, ImageEnView1.IO.Params); Free; end; ImageEnView1.IO.InjectTIFFEXIF('output.hdp'); !!} // IOParams can be nil // doesn't save/inject exif info // Note: for some unknown reason it is not possible to include multiple frames in HDP files procedure TIEWICWriter.PutFrame(srcBitmap: TIEBitmap; IOParams: TIOParams); const TIFFCOMPRESSIONMETHODTOINT: array [TIEWICTIFFCompressionMethod] of integer = (0, 1, 2, 3, 4, 5, 6); var frame: IE_IWICBitmapFrameEncode; prop: IE_IPropertyBag2; w, h, i: integer; pixelFormatGUID: TGUID; begin frame := nil; prop := nil; fEncoder.CreateNewFrame(frame, prop); if assigned(frame) and assigned(prop) then begin if assigned(IOParams) then begin DPIX := IOParams.DpiX; DPIY := IOParams.DpiY; ImageQuality := IOParams.HDP_ImageQuality; Lossless := IOParams.HDP_Lossless; end; // Canonical codec properties if fImageQuality>=0.0 then SetPropertyBag(prop, 'ImageQuality', fImageQuality, VT_R4); if fCompressionQuality>=0.0 then SetPropertyBag(prop, 'CompressionQuality', fCompressionQuality, VT_R4); SetPropertyBag(prop, 'Lossless', fLossless, VT_BOOL); // HDP codec properties if fUseCodecOptions then begin SetPropertyBag(prop, 'UseCodecOptions', fUseCodecOptions, VT_BOOL); SetPropertyBag(prop, 'Quality', fQuality, VT_UI1); SetPropertyBag(prop, 'Overlap', fOverlap, VT_UI1); SetPropertyBag(prop, 'Subsampling', fSubsampling, VT_UI1); end; SetPropertyBag(prop, 'HorizontalTileSlices', fHorizontalTileSlices, VT_UI2); SetPropertyBag(prop, 'VerticalTileSlices', fVerticalTileSlices, VT_UI2); SetPropertyBag(prop, 'FrequencyOrder', fFrequencyOrder, VT_BOOL); // TIFF codec properties SetPropertyBag(prop, 'TiffCompressionMethod', TIFFCOMPRESSIONMETHODTOINT[fTIFFCompressionMethod], VT_UI1); frame.Initialize(prop); w := srcBitmap.Width; h := srcBitmap.Height; frame.SetSize(w, h); frame.SetResolution(fDPIX, fDPIY); case srcBitmap.PixelFormat of ie1g: pixelFormatGUID := GUID_WICPixelFormatBlackWhite; ie8p: assert(false); // unsupported ie8g: pixelFormatGUID := GUID_WICPixelFormat8bppGray; ie16g: pixelFormatGUID := GUID_WICPixelFormat16bppGray; ie24RGB: pixelFormatGUID := GUID_WICPixelFormat24bppBGR; ie32f: assert(false); // unsupported ieCMYK: pixelFormatGUID := GUID_WICPixelFormat32bppCMYK; ie48RGB: pixelFormatGUID := GUID_WICPixelFormat48bppRGB; ieCIELab: assert(false); // unsupported ie32RGB: assert(false); // unsupported end; frame.SetPixelFormat(pixelFormatGUID); for i := 0 to h-1 do frame.WritePixels(1, srcBitmap.Rowlen, srcBitmap.Rowlen, srcBitmap.ScanLine[i]); frame.Commit; end; frame := nil; prop := nil; end; //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// procedure IEHDPRead(Stream: TStream; Bitmap: TIEBitmap; var IOParams: TIOParams; var xProgress: TProgressRec; Preview: boolean); procedure DoProgress(val: integer); begin with xProgress do if assigned(fOnProgress) then fOnProgress(Sender, 0); end; var wic: TIEWICReader; begin DoProgress(0); wic := TIEWICReader.Create; try wic.Open(Stream, ioHDP); wic.GetFrame(IOParams.ImageIndex, Bitmap, IOParams, xProgress.Aborting); // exif loaded in GetFrame finally wic.Free; // wic.Close called in Free DoProgress(100); end; end; // support writing of a single page procedure IEHDPWrite(Stream: TStream; Bitmap: TIEBitmap; var IOParams: TIOParams; var xProgress: TProgressRec); procedure DoProgress(val: integer); begin with xProgress do if assigned(fOnProgress) then fOnProgress(Sender, 0); end; var wic: TIEWICWriter; lp: int64; begin if not IEWICAvailable() then begin xProgress.Aborting^ := true; exit; end; DoProgress(0); lp := Stream.Position; wic := TIEWICWriter.Create; try wic.Open(Stream, ioHDP); wic.PutFrame(Bitmap, IOParams); // exif not written in PutFrame finally wic.Free; Stream.Position := lp; {$ifdef IEINCLUDETIFFHANDLER} IEInjectTIFFEXIF(Stream, Stream, '', '', 0, IOParams); {$endif} DoProgress(100); end; end; function IEHDPFrameCount(const FileName: WideString): integer; var wic: TIEWICReader; fs: TIEWideFileStream; begin if IEWICAvailable() then begin wic := TIEWICReader.Create; fs := TIEWideFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); try wic.Open(fs, ioHDP); result := wic.FrameCount; finally wic.Free; fs.Free; end; end else result := 0; end; var iegWICAvailable: boolean = false; iegWICTested: boolean = false; {!! IEWICAvailable Declaration function IEWICAvailable: boolean; Description Returns True if WIC interfaces are available. This means that Microsoft HD Photo is also available. !!} {$ifdef IEDOTNETVERSION} function IEWICAvailable: boolean; begin iegWICTested := true; iegWICAvailable := true; result := true; end; {$else} function IEWICAvailable: boolean; var factory: IE_IWICImagingFactory; oleInit: boolean; begin if not iegWICTested then begin oleInit := Succeeded(OleInitialize(nil)); try factory := nil; CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER, IE_IWICImagingFactory, factory); iegWICAvailable := assigned(factory); factory := nil; finally if oleInit then OleUninitialize; end; iegWICTested := true; end; result := iegWICAvailable; end; {$endif} //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// constructor TIEWICBitmapWrapper.Create(Bitmap: TIEBaseBitmap; Alpha: TIEBaseBitmap); begin inherited Create(); m_bitmap := Bitmap; m_alpha := Alpha; end; destructor TIEWICBitmapWrapper.Destroy(); begin inherited; end; function TIEWICBitmapWrapper.GetSize(out puiWidth: DWORD; out puiHeight: DWORD): HResult; begin puiWidth := m_bitmap.Width; puiHeight := m_bitmap.Height; result := S_OK; end; function TIEWICBitmapWrapper.GetPixelFormat(out pPixelFormat: TGUID): HResult; begin result := S_OK; case m_bitmap.PixelFormat of ie1g: pPixelFormat := GUID_WICPixelFormatBlackWhite; ie8g: pPixelFormat := GUID_WICPixelFormat8bppGray; ie8p: pPixelFormat := GUID_WICPixelFormat8bppIndexed; ie16g: pPixelFormat := GUID_WICPixelFormat16bppGray; ie24RGB: begin if assigned(m_alpha) then pPixelFormat := GUID_WICPixelFormat32bppBGRA else pPixelFormat := GUID_WICPixelFormat24bppBGR; end; ieCMYK: pPixelFormat := GUID_WICPixelFormat32bppCMYK; ie48RGB: pPixelFormat := GUID_WICPixelFormat48bppRGB; else result := E_NOTIMPL; end; end; function TIEWICBitmapWrapper.GetResolution(out pDpiX: double; out pDpiY: double): HResult; begin pDpiX := IEGlobalSettings().DefaultDPIX; pDpiY := IEGlobalSettings().DefaultDPIY; result := S_OK; end; function TIEWICBitmapWrapper.CopyPalette(pIPalette: IE_IWICPalette): HResult; var colors: array of IE_WICColor; i: integer; begin if m_bitmap.PixelFormat = ie8p then begin SetLength(colors, m_bitmap.PaletteUsed); for i := 0 to m_bitmap.PaletteUsed - 1 do colors[i] := m_bitmap.Palette[i].b or (m_bitmap.Palette[i].g shl 8) or (m_bitmap.Palette[i].r shl 16); pIPalette.InitializeCustom(@colors[0], m_bitmap.PaletteUsed); result := S_OK; end else result := WINCODEC_ERR_PALETTEUNAVAILABLE; end; function TIEWICBitmapWrapper.CopyPixels(prc: IE_PWICRect; cbStride: DWORD; cbBufferSize: DWORD; pbBuffer: pbyte): HResult; var x, y, width, height: integer; row: integer; dstrow: DWORD; dst, src: pbyte; i: integer; pb: pbyte; begin if prc <> nil then begin x := prc^.X; y := prc^.Y; width := prc^.Width; height := prc^.Height; end else begin x := 0; y := 0; width := m_bitmap.Width; height := m_bitmap.Height; end; dstrow := 0; for row := y to y + height - 1 do begin dst := pbBuffer; inc(dst, dstrow * cbStride); if m_bitmap.PixelFormat = ie1g then begin IECopyBits_large(dst, m_bitmap.ScanLine[row], 0, x, width, cbStride); end else if (m_bitmap.PixelFormat = ie24RGB) and assigned(m_alpha) then begin src := m_bitmap.ScanLine[row]; inc(src, x * sizeof(TRGB)); pb := m_alpha.ScanLine[row]; // alpha channel inc(pb, x); for i := 0 to width - 1 do begin dst^ := src^; inc(dst); inc(src); // b dst^ := src^; inc(dst); inc(src); // g dst^ := src^; inc(dst); inc(src); // r dst^ := pb^; inc(dst); inc(pb); // a end; end else begin src := m_bitmap.ScanLine[row]; inc(src, x * m_bitmap.BitCount div 8); CopyMemory(dst, src, width * m_bitmap.BitCount div 8); if m_bitmap.PixelFormat = ieCMYK then begin // CMYK channels need to be inverted pb := dst; for i := width * 4 - 1 downto 0 do begin pb^ := 255 - pb^; inc(pb); end; end; end; inc(dstrow); end; result := S_OK; end; //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // TIEWICBaseFunctionality constructor TIEWICBaseFunctionality.Create(); begin inherited Create(); m_OLEInitialized := Succeeded(OleInitialize(nil)); m_WICImagingFactory := nil; CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER, IE_IWICImagingFactory, m_WICImagingFactory); end; destructor TIEWICBaseFunctionality.Destroy(); begin m_WICImagingFactory := nil; if m_OLEInitialized then OleUninitialize(); inherited; end; function TIEWICBaseFunctionality.IsAvailable(): boolean; begin result := m_WICImagingFactory <> nil; end; ////////////////////////////////////////////////////////////////// // TIEWICFormatConverter constructor TIEWICFormatConverter.Create(); begin inherited Create(); m_paletteType := IE_WICBitmapPaletteTypeMedianCut; m_ditherType := IE_WICBitmapDitherTypeSolid; m_palette := nil; end; procedure TIEWICFormatConverter.SetPalette(Palette: array of TRGB); var paletteColors: array of IE_WICColor; paletteLength: integer; i: integer; begin paletteLength := length(Palette); if paletteLength > 0 then begin m_WICImagingFactory.CreatePalette(m_palette); SetLength(paletteColors, paletteLength); for i := 0 to paletteLength - 1 do paletteColors[i] := Palette[i].b or (Palette[i].g shl 8) or (Palette[i].r shl 16); m_palette.InitializeCustom(@paletteColors[0], paletteLength); end else m_palette := nil; end; // cannot convert to CMYK (from CMYK is supported) function TIEWICFormatConverter.Convert(Source: TIEBitmap; Dest: TIEBitmap; DestPixelFormat: TIEPixelFormat; CheckParametersOnly: boolean; OnProgressFunction: TIEProgressEvent; OnProgressSender: TObject): boolean; var sourceWrapper: TIEWICBitmapWrapper; converter: IE_IWICFormatConverter; dstPixelFormat: TGUID; begin result := false; converter := nil; m_WICImagingFactory.CreateFormatConverter(converter); sourceWrapper := TIEWICBitmapWrapper.Create(Source, Source.AlphaChannelOpt); dstPixelFormat := ConvertIEBitmapPixelFormatToWICPixelFormat(DestPixelFormat); if SUCCEEDED(converter.Initialize(sourceWrapper, dstPixelFormat, m_ditherType, m_palette, 0.0, m_paletteType)) then begin if not CheckParametersOnly then CopyWICBitmapSourceToIEBitmap(m_WICImagingFactory, converter, Dest, nil, OnProgressFunction, OnProgressSender); result := true; end; end; ////////////////////////////////////////////////////////////////// // TIEWICBitmapScaler function TIEWICBitmapScaler.Resample(Source: TIEBaseBitmap; SourceAlpha: TIEBaseBitmap; Dest: TIEBaseBitmap; DestAlpha: TIEBaseBitmap; Width: DWORD; Height: DWORD; Mode: IE_WICBitmapInterpolationMode; OnProgressFunction: TIEProgressEvent; OnProgressSender: TObject): boolean; var sourceWrapper: TIEWICBitmapWrapper; scaler: IE_IWICBitmapScaler; begin result := false; scaler := nil; m_WICImagingFactory.CreateBitmapScaler(scaler); sourceWrapper := TIEWICBitmapWrapper.Create(Source, SourceAlpha); if SUCCEEDED(scaler.Initialize(sourceWrapper, Width, Height, Mode)) then begin CopyWICBitmapSourceToIEBitmap(m_WICImagingFactory, scaler, Dest, DestAlpha, OnProgressFunction, OnProgressSender); result := true; end; end; // just an helper for TIEWICBitmapScaler // FilterType can be: rfWICNearestNeighbor, rfWICLinear, rfWICCubic, rfWICFant procedure IEWICResample(SrcImg: TIEBaseBitmap; DstImg: TIEBaseBitmap; SrcAlpha: TIEBaseBitmap; FilterType: TResampleFilter; OnProgressFunction: TIEProgressEvent; OnProgressSender: TObject); var scaler: TIEWICBitmapScaler; mode: IE_WICBitmapInterpolationMode; begin scaler := TIEWICBitmapScaler.Create(); try mode := 0; case FilterType of rfWICNearestNeighbor: mode := IE_WICBitmapInterpolationModeNearestNeighbor; rfWICLinear: mode := IE_WICBitmapInterpolationModeLinear; rfWICCubic: mode := IE_WICBitmapInterpolationModeCubic; rfWICFant: mode := IE_WICBitmapInterpolationModeFant; end; scaler.Resample(SrcImg, SrcAlpha, DstImg, nil, DstImg.Width, DstImg.Height, Mode, OnProgressFunction, OnProgressSender); finally scaler.Free(); end; end; {$ELSE} // {$ifdef IEINCLUDEWIC} interface function IEWICAvailable: boolean; implementation function IEWICAvailable: boolean; begin result := false; end; {$ENDIF} end.