(* 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: iexHelperFunctions.pas Description: ImageEn Helper functions File version: 1010 Notes: - Requires Delphi 2005 or newer - Some additions by William Miller, Adirondack Software & Graphics *) unit iexHelperFunctions; interface {$I ie.inc} // Enable to include TImageEnIO helpers for loading and saving to blob fields {.$Define IE_DB_Helpers} uses Windows, Graphics, Classes, {$ifdef IEHASTYPES} Types, {$endif} {$ifdef IE_DB_Helpers} Db, {$endif} ImageEnProc, hyiedefs, ImageEnIO, iexBitmaps, hyieutils; type {!! TLightOrigin Declaration } TLightOrigin = (_loTopLeft, _loTopRight, _loBottomLeft, _loBottomRight); {!!} {!! TIEQuality Declaration } TIEQuality = (ieLow, ieMedium, ieHigh); {!!} {$IFDEF Delphi2005orNewer} // TImageEnIO Helper Functions TImageEnIOHelper = class helper for TImageEnIO private function ImageSize : TPoint; function IsEmpty : Boolean; function _LoadFromFileEx(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1; bUseFileExt : Boolean = true): Boolean; function _LoadFromStreamEx(Stream: TStream; FileType: integer; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1): Boolean; {$IFDEF IEINCLUDERAWFORMATS} function LoadFromStreamRawFast(Stream: TStream; iMaxX, iMaxY: integer): Boolean; {$ENDIF} public function Reload : Boolean; function LoadFromFileEx(const sFilename: string; bAutoAdjustOrientation: Boolean; iImageIndex : Integer = -1): Boolean; function LoadFromFileFast(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False ): Boolean; function LoadFromFileJPEGFast(const sFilename: string; iMaxX, iMaxY: integer; var iFastScaleUsed: Integer; bAutoAdjustOrientation: Boolean = False ): Boolean; function LoadFromStreamJPEGFast(Stream: TStream; iMaxX, iMaxY: integer; var iFastScaleUsed: Integer; bAutoAdjustOrientation: Boolean = False ): Boolean; function LoadFromFileAutoEx(const sFilename: string; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1): Boolean; {$IFDEF IEINCLUDERAWFORMATS} function LoadFromFileRawFast(const sFilename: string; iMaxX, iMaxY: integer): Boolean; {$ENDIF} function LoadFromStreamEx(Stream: TStream; FileType: integer = 0; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1): Boolean; function LoadFromStreamFast(Stream: TStream; FileType: integer; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False ): Boolean; function SaveToFileEx(const sFilename : string; iJpegQuality: integer = 0): Boolean; function SaveToStreamEx(Stream: TStream; FileType: integer; iJpegQuality: integer = 0): Boolean; {$IFDEF IEINCLUDEPDFWRITING} function CreatePDFFromFileList(const sDestFilename : string; ssFileList : TStrings; const aPaperSize : TIOPDFPaperSize; const aCompression : TIOPDFCompression; const sTitle : string; const sAuthor : string; const bFailOnUnsupportedImage : Boolean = True; const bRaiseExceptions : Boolean = False ) : Boolean; {$ENDIF} function CreatePSFromFileList(const sDestFilename : string; ssFileList : TStrings; const aPaperSize : TIOPDFPaperSize; const aCompression : TIOPSCompression; const sTitle : string = ''; const bFailOnUnsupportedImage : Boolean = True; const bRaiseExceptions : Boolean = False ) : Boolean; {$IFDEF IE_DB_Helpers} function LoadFromBlob(aField: TBlobField; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1 ): Boolean; function LoadFromBlobFast(aField: TBlobField; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1 ): Boolean; function SaveToBlob(aField : TBlobField; aFileType : TIOFileType; iJpegQuality: integer = 0): Boolean; {$ENDIF} end; {$ENDIF} {$IFDEF Delphi2005orNewer} // TBitmap Helper Functions TBitmapHelper = class helper for TBitmap private procedure ConvertTo24Bit; public procedure IEInitialize(iWidth, iHeight: Integer; ABackgroundColor : TColor = clNone); procedure IERotate(Angle: double; AntiAliasMode: TIEAntialiasMode = ierFast; BackgroundColor: TColor = -1); procedure IEFlip(Direction: TFlipDir); procedure IEResample(iNewWidth, iNewHeight: integer; QualityFilter: TResampleFilter = rfNone; bMaintainAspectRatio : Boolean = False); function IELoadFromFile(const sFilename : string): Boolean; function IELoadFromFileFast(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False ): Boolean; function IELoadFromStream(Stream: TStream; FileType: integer = 0): Boolean; function IELoadFromStreamFast(Stream: TStream; FileType: integer; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False ): Boolean; function IESaveToFile(const sFilename : string; iJPEGQuality : Integer): Boolean; function IESaveToStream(Stream: TStream; FileType: integer; iJPEGQuality : Integer): Boolean; function LoadFromURL(const URL : WideString; const sProxyAddress : WideString = ''; const sProxyUser : WideString = ''; const sProxyPassword : WideString = '' ): Boolean; function IELoadAsThumbnail(const sFilename: string; iMaxX, iMaxY: integer; bCanStretch: Boolean; bAutoAdjustOrientation: Boolean = False; QualityFilter : TResampleFilter = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius : Integer = 4; iShadowOffset : Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite ) : Boolean; procedure IEConvertToThumbnail(iMaxX, iMaxY: integer; bCanStretch: Boolean; QualityFilter : TResampleFilter = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius : Integer = 4; iShadowOffset : Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite); procedure IEAddSoftShadow(iBlurRadius: integer; iShadowOffset : Integer; cBGColor: TColor; LightOrigin: TLightOrigin = _loTopLeft; cShadowColor: TColor = clblack); procedure PrintImage(PrtCanvas: TCanvas = nil; MarginLeft: double = 1; MarginTop: double = 1; MarginRight: double = 1; MarginBottom: double = 1; VerticalPos: TIEVerticalPos = ievpCenter; HorizontalPos: TIEHorizontalPos = iehpCenter; Size: TIESize = iesFitToPage; SpecWidth: double = 0; SpecHeight: double = 0; GammaCorrection: double = 1; SubsampleFilter: TResampleFilter = rfFastLinear); end; {$ENDIF} {$IFDEF Delphi2005orNewer} // TIEBitmap Helper Functions TIEBitmapHelper = class helper for TIEBitmap private procedure ConvertTo24Bit; function IELoadFromFileEx(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean; IOParams: TIOParams; iImageIndex: Integer ): Boolean; function IELoadFromStreamEx(Stream: TStream; FileType: integer; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean; IOParams: TIOParams; iImageIndex: Integer ): Boolean; public procedure IEInitialize(iWidth, iHeight: Integer; ABackgroundColor: TColor = clNone); overload; procedure IEInitialize(iWidth, iHeight: Integer; Transparent: Boolean); overload; function IELoadFromFile(const sFilename: string; IOParams: TIOParams = nil; iImageIndex: Integer = 0): Boolean; function IELoadFromFileFast(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; IOParams: TIOParams = nil): Boolean; function IELoadFromStream(Stream: TStream; FileType: integer = 0; IOParams: TIOParams = nil; iImageIndex: Integer = 0): Boolean; function IELoadFromStreamFast(Stream: TStream; FileType: integer; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; IOParams: TIOParams = nil): Boolean; function IESaveToFile(const sFilename: string; iJPEGQuality: Integer; IOParams: TIOParams = nil): Boolean; function IESaveToStream(Stream: TStream; FileType: integer; iJPEGQuality: Integer; IOParams: TIOParams = nil): Boolean; function LoadFromURL(const URL : WideString; const sProxyAddress : WideString = ''; const sProxyUser : WideString = ''; const sProxyPassword : WideString = '' ): Boolean; function IELoadAsThumbnail(const sFilename: string; iMaxX, iMaxY: integer; bCanStretch: Boolean; bAutoAdjustOrientation: Boolean = False; QualityFilter: TResampleFilter = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius: Integer = 4; iShadowOffset: Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite ): Boolean; procedure IEConvertToThumbnail(iMaxX, iMaxY: integer; bCanStretch: Boolean; QualityFilter: TResampleFilter = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius: Integer = 4; iShadowOffset: Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite); procedure IEAddSoftShadow(iBlurRadius: integer; iShadowOffset: Integer; cBGColor: TColor; LightOrigin: TLightOrigin = _loTopLeft; cShadowColor: TColor = clblack); procedure PrintImage(PrtCanvas: TCanvas = nil; MarginLeft: double = 1; MarginTop: double = 1; MarginRight: double = 1; MarginBottom: double = 1; VerticalPos: TIEVerticalPos = ievpCenter; HorizontalPos: TIEHorizontalPos = iehpCenter; Size: TIESize = iesFitToPage; SpecWidth: double = 0; SpecHeight: double = 0; GammaCorrection: double = 1; SubsampleFilter: TResampleFilter = rfFastLinear); {$IFDEF IEINCLUDEWIC} function WicRead(const sFilename: string; iImageIndex: Integer = 0; IOParams: TIOParams = nil): Boolean; overload; function WicRead(Stream: TStream; FileType: integer = 0; iImageIndex: Integer = 0; IOParams: TIOParams = nil): Boolean; overload; {$ENDIF} end; {$ENDIF} // FILE FUNCTIONS {$IFDEF Delphi2005orNewer} function IEResampleImageFile(const sInFilename, sOutFilename: string; iJpegQuality: Integer; iMaxX: Integer; iMaxY: Integer; bCanStretch: Boolean = False; QualityFilter: TResampleFilter = rfLanczos3; bAutoAdjustOrientation: Boolean = False; bStripMetaData: Boolean = False ): Boolean; {$ENDIF} {$IFDEF Delphi2005orNewer} function IEConvertImageFile(const sInFilename, sOutFilename: string; iJpegQuality: Integer; bAutoAdjustOrientation: Boolean = False ): Boolean; {$ENDIF} {$IFDEF Delphi2005orNewer} function IECreateThumbnailFromFile(const sInFilename: string; const sOutFilename: string; iMaxX, iMaxY: integer; bCanStretch: Boolean; iJPEGQuality: integer; bAutoAdjustOrientation: Boolean = False; QualityFilter : TResampleFilter = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius : Integer = 4; iShadowOffset : Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite ): Boolean; {$ENDIF} function GetImageDetails(const sFilename: string; out iWidth: Integer; out iHeight: Integer; out iBitsPerPixel: Integer ): Boolean; overload; function GetImageDetails(const sFilename: string): TPoint; overload; function GetExifOrFileCreationDate(const sFilename: string; bReturnCreateDate: Boolean = true {if true then the create date is returned if there is no exif date} ): TDateTime; function JPEGLosslessRotateFile(const sInFilename : WideString; const sOutFilename : WideString; iRotateAngle : integer) : Boolean; overload; function JPEGLosslessRotateFile(const sFilename : WideString; iRotateAngle : integer) : Boolean; overload; function JPEGLosslessFlipFile(const sInFilename : WideString; const sOutFilename : WideString; Direction: TFlipDir) : Boolean; overload; function JPEGLosslessFlipFile(const sFilename : WideString; Direction: TFlipDir) : Boolean; overload; {$IFDEF Delphi2005orNewer} function IERotateImageFile(const sFilename : string; iJpegQuality : integer; iRotateAngle : integer; AntiAliasMode: TIEAntialiasMode = ierFast; bCanUseLossless: Boolean = true; // if true then a lossless rotate is used for JPEG images cBackgroundColor: TColor = clWhite): Boolean; overload; function IERotateImageFile(const sInFilename, sOutFilename : string; iJpegQuality : integer; iRotateAngle : integer; AntiAliasMode: TIEAntialiasMode = ierFast; bCanUseLossless: Boolean = true; // if true then a lossless rotate is used for JPEG images cBackgroundColor: TColor = clWhite): Boolean; overload; function IEFlipImageFile(const sFilename : string; iJpegQuality : integer; Direction: TFlipDir; bCanUseLossless: Boolean = true // if true then a lossless rotate is used for JPEG images ): Boolean; overload; function IEFlipImageFile(const sInFilename, sOutFilename : string; iJpegQuality : integer; Direction: TFlipDir; bCanUseLossless: Boolean = true // if true then a lossless rotate is used for JPEG images ): Boolean; overload; {$ENDIF} function IEReadCorrectOrientationOfImageFile(const sFilename : string; bConservativeChecking : Boolean = True) : Integer; function IEAutomaticallyRotateImageFile(const sFilename : string; bConservativeChecking : Boolean = True) : Integer; function BitsPerPixelToStr(iBitsPerPixel: Integer) : string; function ShowTempHourglass: IUnknown; function QualityToZoomFilter(Quality: TIEQuality): TResampleFilter; implementation uses {$IFDEF IEINCLUDEWIC} iewic, {$ENDIF} SysUtils, ImageEnView, Controls, Math, Forms, iesettings; {$IFDEF Delphi2005orNewer} { TImageEnIOHelper } function TImageEnIOHelper.ImageSize: TPoint; begin if Assigned(IEBitmap) then result := Point(IEBitmap.width, IEBitmap.height) else if Assigned(Bitmap) then result := Point(Bitmap.width, Bitmap.height) else result := Point(0, 0); end; function TImageEnIOHelper.IsEmpty: Boolean; begin Result := (ImageSize.X <= 2) or (ImageSize.Y <= 2); end; function TImageEnIOHelper._LoadFromFileEx(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1; bUseFileExt : Boolean = true): Boolean; var bFastLoad: Boolean; iFastScaleUsed : Integer; begin bFastLoad := (iMaxX > 0) and (iMaxY > 0); try {$IFDEF IEINCLUDERAWFORMATS} if bFastLoad and (IEFileIsOfFormat(sFilename, ioRaw) or IEFileIsOfFormat(sFilename, ioRaw)) then begin Result := LoadFromFileRawFast(sFilename, iMaxX, iMaxY); end else {$ENDIF} if bFastLoad and IEFileIsOfFormat(sFilename, ioJPEG) then begin Result := LoadFromFileJPEGFast(sFilename, iMaxX, iMaxY, iFastScaleUsed, bAutoAdjustOrientation); end else begin // reset any fast loading variables Params.JPEG_Scale := ioJPEG_FullSize; Params.JPEG_DCTMethod := ioJPEG_ISLOW; Params.EnableAdjustOrientation := bAutoAdjustOrientation; {$IFDEF IEINCLUDERAWFORMATS} Params.RAW_HalfSize := false; Params.RAW_GetExifThumbnail := false; {$ENDIF} Params.IEN_GetThumbnail := bFastLoad and ( iMaxX <= IEGlobalSettings().ThumbnailSize ) and ( iMaxY <= IEGlobalSettings().ThumbnailSize ); if iImageIndex <> -1 then Params.ImageIndex := iImageIndex; if bUseFileExt then LoadFromFile(sFilename) else LoadFromFileAuto(sFilename); Result := not (Aborting or IsEmpty); end; except result := false; end; end; function TImageEnIOHelper._LoadFromStreamEx(Stream: TStream; FileType: integer; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1): Boolean; var bFastLoad: Boolean; iFastScaleUsed : Integer; begin try bFastLoad := (iMaxX > 0) and (iMaxY > 0); if FileType = ioUnknown then FileType := FindStreamFormat( Stream ); if FileType = ioUnknown then raise EIEException.create('Unknown File Type'); {$IFDEF IEINCLUDERAWFORMATS} if bFastLoad and ( FileType = ioRaw ) then begin Result := LoadFromStreamRawFast(Stream, iMaxX, iMaxY); end else {$ENDIF} if bFastLoad and ( FileType = ioJPEG ) then begin Result := LoadFromStreamJPEGFast(Stream, iMaxX, iMaxY, iFastScaleUsed, bAutoAdjustOrientation); end else begin // reset any fast loading variables Params.JPEG_Scale := ioJPEG_FullSize; Params.JPEG_DCTMethod := ioJPEG_ISLOW; Params.EnableAdjustOrientation := bAutoAdjustOrientation; {$IFDEF IEINCLUDERAWFORMATS} Params.RAW_HalfSize := false; Params.RAW_GetExifThumbnail := false; {$ENDIF} Params.IEN_GetThumbnail := bFastLoad and ( iMaxX <= IEGlobalSettings().ThumbnailSize ) and ( iMaxY <= IEGlobalSettings().ThumbnailSize ); if iImageIndex <> -1 then Params.ImageIndex := iImageIndex; LoadFromStream(Stream, FileType); Result := not (Aborting or IsEmpty); end; except result := false; end; end; {!! TImageEnIO.LoadFromFileFast Declaration function LoadFromFileFast(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False): Boolean; Description Calls and allows you to specify a maximum size that you require an image so that it can be loaded as fast as possible, by using: - for JPEGs - and for Camera Raw files - for IEN files You can also set to automatically re-orient JPEG camera images Returns True if loading was successful, or False on error Example // Load the image specified in an open dialog as fast as possible, but bigger than the displaying TImageEnView ImageEnView1.AutoShrink := True; ImageEnView1.IO.LoadFromFileFast(OpenPictureDialog1.FileName, ImageEnView1.Width, ImageEnView1.Height) !!} function TImageEnIOHelper.LoadFromFileFast(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False): Boolean; begin Result := _LoadFromFileEx(sFilename, iMaxX, iMaxY, bAutoAdjustOrientation); end; {!! TImageEnIO.LoadFromStreamFast Declaration function LoadFromStreamFast(Stream: TStream; FileType: = 0; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False): Boolean; Description Calls and allows you to specify a maximum size that you require an image so that it can be loaded as fast as possible, by using: - for JPEGs - and for Camera Raw files - for IEN files You can also set to automatically re-orient JPEG camera images. If you know the FileType type of the stream, pass it to speed up loading. Returns True if loading was successful, or False on error Example // Load an image as fast as possible, but bigger than the displaying TImageEnView ImageEnView1.AutoShrink := True; ImageEnView1.IO.LoadFromStreamFast( MyStream, ImageEnView1.Width, ImageEnView1.Height ) !!} function TImageEnIOHelper.LoadFromStreamFast(Stream: TStream; FileType: integer; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False): Boolean; begin Result := _LoadFromStreamEx(Stream, FileType, iMaxX, iMaxY, bAutoAdjustOrientation); end; {!! TImageEnIO.LoadFromFileEx Declaration function LoadFromFileEx(const sFilename: string; bAutoAdjustOrientation: Boolean; iImageIndex : Integer = -1): Boolean; Description Calls , optionally setting to automatically re-orient JPEG camera images and to display a specific image. Returns True if loading was successful, or False on error Example // Load the third page of MyImage.tiff ImageEnView1.IO.LoadFromFileEx('D:\MyImage.tiff', False, 2); !!} function TImageEnIOHelper.LoadFromFileEx(const sFilename: string; bAutoAdjustOrientation: Boolean; iImageIndex : Integer = -1): Boolean; begin Result := _LoadFromFileEx(sFilename, -1, -1, bAutoAdjustOrientation, iImageIndex); end; {!! TImageEnIO.LoadFromStreamEx Declaration function LoadFromStreamEx(Stream: TStream; FileType: = 0; bAutoAdjustOrientation: Boolean; iImageIndex : Integer = -1): Boolean; Description Calls , optionally setting to automatically re-orient JPEG camera images and to display a specific image. If you know the FileType type of the stream, pass it to speed up loading. Returns True if loading was successful, or False on error Example // Load the third page of a TIFF stream ImageEnView1.IO.LoadFromStreamEx(MyStream, False, 2); !!} function TImageEnIOHelper.LoadFromStreamEx(Stream: TStream; FileType: integer = 0; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1): Boolean; begin Result := _LoadFromStreamEx(Stream, FileType, -1, -1, bAutoAdjustOrientation, iImageIndex); end; {!! TImageEnIO.LoadFromFileAutoEx Declaration function LoadFromFileAutoEx(const sFilename: string; bAutoAdjustOrientation: Boolean; iImageIndex : Integer = -1): Boolean; Description A modified version of that copes with image files with a incorrect extension (e.g. a GIF file named MyImage.jpg). This function will attempt to load the file using its extension (using ) but on failure will examine the message content to determine its type (i.e. falling back to ). Optionally it will set to automatically re-orient JPEG camera images and to display a specific image. Returns True if loading was successful, or False on error (i.e. the file could not be loaded even by examining its content). Example // Load MyImage.tiff (even if it is a JPEG or GIF) ImageEnView1.IO.LoadFromFileAutoEx('D:\MyImage.tiff'); !!} function TImageEnIOHelper.LoadFromFileAutoEx(const sFilename: string; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1): Boolean; begin Result := _LoadFromFileEx(sFilename, -1, -1, bAutoAdjustOrientation, iImageIndex); // Try loading without extension if not Result then Result := _LoadFromFileEx(sFilename, -1, -1, bAutoAdjustOrientation, iImageIndex, False); end; {!! TImageEnIO.LoadFromFileJPEGFast Declaration function LoadFromFileJPEGFast(const sFilename: string; iMaxX, iMaxY: integer; var iFastScaleUsed: Integer; bAutoAdjustOrientation: Boolean = False ): Boolean; Description Calls to load a JPEG image and allows you to specify a maximum size that you require an image so that it can be loaded as fast as possible, by using . You can also set to automatically re-orient JPEG camera images Returns True if loading was successful, or False on error. iFastScaleUsed is set with the scaling that was used, i.e. 1 = loaded full size, 2 = loaded at half size, etc. Example // Load the JPEG specified in an open dialog as fast as possible, but bigger than the displaying TImageEnView ImageEnView1.AutoShrink := True; ImageEnView1.IO.LoadFromFileJpegFast(OpenPictureDialog1.FileName, ImageEnView1.Width, ImageEnView1.Height, iFastScaleUsed) !!} function TImageEnIOHelper.LoadFromFileJPEGFast(const sFilename: string; iMaxX, iMaxY: integer; var iFastScaleUsed: Integer; bAutoAdjustOrientation: Boolean = False ): Boolean; begin Result := True; try iFastScaleUsed := 1; if (iMaxX < 1) or (iMaxY < 1) then Params.JPEG_Scale := ioJPEG_FullSize else begin // Fast Loading Params.Width := iMaxX; Params.Height := iMaxY; Params.JPEG_Scale := ioJPEG_AUTOCALC; // Is it a thumbnail? if iMaxX + iMaxY < 500 then Params.JPEG_DCTMethod := ioJPEG_IFAST; end; Params.EnableAdjustOrientation := bAutoAdjustOrientation; LoadFromFileJpeg(sFilename); if Aborting or IsEmpty then raise EIEException.create('Load Error'); iFastScaleUsed := Params.Jpeg_Scale_Used; except result := false; end; end; {!! TImageEnIO.LoadFromStreamJPEGFast Declaration function LoadFromStreamJPEGFast(Stream: TStream; iMaxX, iMaxY: integer; var iFastScaleUsed: Integer; bAutoAdjustOrientation: Boolean = False ): Boolean; Description Calls to load a JPEG image and allows you to specify a maximum size that you require an image so that it can be loaded as fast as possible, by using . You can also set to automatically re-orient JPEG camera images Returns True if loading was successful, or False on error. iFastScaleUsed is set with the scaling that was used, i.e. 1 = loaded full size, 2 = loaded at half size, etc. Example // Load the JPEG from a stream as fast as possible, but bigger than the displaying TImageEnView ImageEnView1.AutoShrink := True; ImageEnView1.IO.LoadFromStreamJpegFast(MyStream, ImageEnView1.Width, ImageEnView1.Height, iFastScaleUsed) !!} function TImageEnIOHelper.LoadFromStreamJPEGFast(Stream: TStream; iMaxX, iMaxY: integer; var iFastScaleUsed: Integer; bAutoAdjustOrientation: Boolean = False ): Boolean; begin Result := True; try iFastScaleUsed := 1; if (iMaxX < 1) or (iMaxY < 1) then Params.JPEG_Scale := ioJPEG_FullSize else begin // Fast Loading Params.Width := iMaxX; Params.Height := iMaxY; Params.JPEG_Scale := ioJPEG_AUTOCALC; // Is it a thumbnail? if iMaxX + iMaxY < 500 then Params.JPEG_DCTMethod := ioJPEG_IFAST; end; Params.EnableAdjustOrientation := bAutoAdjustOrientation; LoadFromStreamJpeg(Stream); if Aborting or IsEmpty then raise EIEException.create('Load Error'); iFastScaleUsed := Params.Jpeg_Scale_Used; except result := false; end; end; const // SOME APPROXIMATE VALUES TO OPTIMIZE RAW LOADING SMALLEST_RAW_THUMBNAIL_WIDTH = 150; SMALLEST_RAW_THUMBNAIL_HEIGHT = 100; SMALLEST_RAW_IMAGE_WIDTH = 1800; SMALLEST_RAW_IMAGE_HEIGHT = 1400; {!! TImageEnIO.LoadFromFileRawFast Declaration function LoadFromFileRawFast(const sFilename: string; iMaxX, iMaxY: integer): Boolean; Description Calls to load a camera Raw image and allows you to specify a maximum size that you require an image so that it can be loaded as fast as possible, by using and for Camera Raw files. Returns True if loading was successful, or False on error Example // Load the image specified in an open dialog as fast as possible, but bigger than the displaying TImageEnView ImageEnView1.AutoShrink := True; ImageEnView1.IO.LoadFromFileRawFast(OpenPictureDialog1.FileName, ImageEnView1.Width, ImageEnView1.Height) !!} {$IFDEF IEINCLUDERAWFORMATS} function TImageEnIOHelper.LoadFromFileRawFast(const sFilename: string; iMaxX, iMaxY: integer): Boolean; begin try Params.RAW_HalfSize := (iMaxX <= SMALLEST_RAW_IMAGE_WIDTH) and (iMaxY <= SMALLEST_RAW_IMAGE_HEIGHT); Params.RAW_GetExifThumbnail := (iMaxX <= SMALLEST_RAW_THUMBNAIL_WIDTH) and (iMaxY <= SMALLEST_RAW_THUMBNAIL_HEIGHT); LoadFromFileRaw(sFilename); result := not (Aborting or IsEmpty); except on E:Exception do result := false; end; end; {$ENDIF} {$IFDEF IEINCLUDERAWFORMATS} function TImageEnIOHelper.LoadFromStreamRawFast(Stream: TStream; iMaxX, iMaxY: integer): Boolean; begin try Params.RAW_HalfSize := (iMaxX <= SMALLEST_RAW_IMAGE_WIDTH) and (iMaxY <= SMALLEST_RAW_IMAGE_HEIGHT); Params.RAW_GetExifThumbnail := (iMaxX <= SMALLEST_RAW_THUMBNAIL_WIDTH) and (iMaxY <= SMALLEST_RAW_THUMBNAIL_HEIGHT); LoadFromStreamRaw(Stream); result := not (Aborting or IsEmpty); except on E:Exception do result := false; end; end; {$ENDIF} {!! TImageEnIO.Reload Declaration function Reload(const sFilename : Boolean; Description Reload the image. Example ImageEnView1.IO.Reload; !!} function TImageEnIOHelper.Reload : Boolean; begin Result := True; try if Params.FileName = '' then raise EIEException.create('Nothing to Load'); LoadFromFile(Params.FileName); if Aborting or IsEmpty then raise EIEException.create('Load Error'); except result := false; end; end; {!! TImageEnIO.SaveToFileEx Declaration function SaveToFileEx(const sFilename : string; iJpegQuality: integer = 0): Boolean; Description Calls , optionally setting . Returns True if saving was successful, or False on error Example // Save the image to MyImage.jpeg at 90% quality ImageEnView1.IO.SaveToFileEx('D:\MyImage.jpeg', 90); !!} function TImageEnIOHelper.SaveToFileEx(const sFilename: string; iJpegQuality: integer = 0): Boolean; const Reset_Jpeg_Orientation_On_Save = False; begin try if iJpegQuality > 0 then Params.JPEG_Quality := iJpegQuality; if Reset_Jpeg_Orientation_On_Save then Params.EXIF_Orientation := _exoCorrectOrientation; SavetoFile(sFilename); Result := not Aborting; except result := false; end; end; {!! TImageEnIO.SaveToStreamEx Declaration function SaveToStreamEx(Stream: TStream; FileType: ; iJpegQuality: integer = 0): Boolean; Description Calls , optionally setting . You must specify the file format. Returns True if saving was successful, or False on error Example // Save the image to MyImage.jpeg at 90% quality ImageEnView1.IO.SaveToStreamEx( DestStream, ioJPEG, 90 ); !!} function TImageEnIOHelper.SaveToStreamEx(Stream: TStream; FileType: integer; iJpegQuality: integer = 0): Boolean; const Reset_Jpeg_Orientation_On_Save = False; begin try if FileType = ioUnknown then raise EIEException.create('Invalid File Type'); if iJpegQuality > 0 then Params.JPEG_Quality := iJpegQuality; if Reset_Jpeg_Orientation_On_Save then Params.EXIF_Orientation := _exoCorrectOrientation; SaveToStream(Stream, FileType); Result := not Aborting; except result := false; end; end; {!! TImageEnIO.CreatePDFFromFileList Declaration function CreatePDFFromFileList(const sDestFilename : string; ssFileList : TStrings; const aPaperSize : ; const aCompression : ; const sTitle : string; const sAuthor : string; const bFailOnUnsupportedImage : Boolean = True; const bRaiseExceptions : Boolean = False ) : Boolean; Description Generates a PDF file from all images specified in a TStrings list, by combining the functions of , and . Result is true unless an error is encountered. Parameter Description sDestFilename The .PDF filename to save the file to ssFileList A list of all images to add to the PDF file aPaperSize The size at which to create the PDF file aCompression The level of compression to use sTitle The title for the PDF document (appears in "Properties") sAuthor The author for the PDF document (appears in "Properties") bFailOnUnsupportedImage When true this procedure will fail if unsupported images (or other file types) are found in ssFileList. If false, unsupported file types are skipped bRaiseExceptions When true this procedure will generate an exception if it fails. If false, you will need to check the result to detect failure
Example CreatePDFFromFileList('D:\MyNewPDF.pdf', ssMyImageList, iepA4, ioPDF_JPEG, 'My Cool PDF', 'Mr Developer'); !!} {$IFDEF IEINCLUDEPDFWRITING} function TImageEnIOHelper.CreatePDFFromFileList(const sDestFilename : string; ssFileList : TStrings; const aPaperSize : TIOPDFPaperSize; const aCompression : TIOPDFCompression; const sTitle : string; const sAuthor : string; const bFailOnUnsupportedImage : Boolean = True; const bRaiseExceptions : Boolean = False ) : Boolean; var I: Integer; sCurrFile: string; begin Result := True; try Params.PDF_PaperSize := aPaperSize; Params.PDF_Title := AnsiString(sTitle); Params.PDF_Author := AnsiString(sAuthor); CreatePDFFile(sDestFilename); for I := 0 to ssFileList.Count - 1 do begin sCurrFile := ssFileList[I]; if (bFailOnUnsupportedImage = False) or IsKnownFormat(sCurrFile) then begin LoadFromFile(sCurrFile); Params.PDF_Compression := aCompression; SaveToPDF; end; end; ClosePDFFile; Except Result := False; end; end; {$ENDIF} {!! TImageEnIO.CreatePSFromFileList Declaration function CreatePSFromFileList(const sDestFilename : string; ssFileList : TStrings; const aPaperSize :
; const aCompression : ; const sTitle : string = ''; const bFailOnUnsupportedImage : Boolean = True; const bRaiseExceptions : Boolean = False ) : Boolean; Description Generates a PS file from all images specified in a TStrings list, by combining the functions of , and . Result is true unless an error is encountered. Parameter Description sDestFilename The .PS filename to save the file to ssFileList A list of all images to add to the PS file aPaperSize The size at which to create the PS file aCompression The level of compression to use sTitle The title for the PS document bFailOnUnsupportedImage When true this procedure will fail if unsupported images (or other file types) are found in ssFileList. If false, unsupported file types are skipped bRaiseExceptions When true this procedure will generate an exception if it fails. If false, you will need to check the result to detect failure
Example CreatePSFromFileList('D:\MyNewPS.PS', ssMyImageList, iepA4, ioPS_JPEG); !!} function TImageEnIOHelper.CreatePSFromFileList(const sDestFilename : string; ssFileList : TStrings; const aPaperSize : TIOPDFPaperSize; const aCompression : TIOPSCompression; const sTitle : string = ''; const bFailOnUnsupportedImage : Boolean = True; const bRaiseExceptions : Boolean = False ) : Boolean; var I: Integer; sCurrFile: string; begin Result := True; try Params.PS_PaperSize := aPaperSize; Params.PS_Title := AnsiString(sTitle); CreatePSFile(sDestFilename); for I := 0 to ssFileList.Count - 1 do begin sCurrFile := ssFileList[I]; if (bFailOnUnsupportedImage = False) or IsKnownFormat(sCurrFile) then begin LoadFromFile(sCurrFile); Params.PS_Compression := aCompression; SaveToPS; end; end; ClosePSFile; Except Result := False; end; end; {!! TImageEnIO.LoadFromBlob Declaration function LoadFromBlob(aField: TBlobField; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1 ): Boolean; Description Uses streams to load an image from the blob field of a database table, optionally setting
to automatically re-orient JPEG camera images and to display a specific image. Returns True if loading was successful, or False on error Note: You must define IE_DB_Helpers in iexHelperFunctions.pas to use this method Example // Load the image from the MyTableImageBlob field at the current position in the database ImageEnView1.IO.LoadFromBlob(MyTableImageBlob); !!} {$IFDEF IE_DB_Helpers} function TImageEnIOHelper.LoadFromBlob(aField: TBlobField; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1 ): Boolean; begin Result := LoadFromBlobFast( aField, 0, 0, bAutoAdjustOrientation, iImageIndex); end; {$ENDIF} {!! TImageEnIO.LoadFromBlobFast Declaration function LoadFromBlobFast(aField: TBlobField; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1 ): Boolean; Description Uses streams to load an image from the blob field of a database table and allows you to specify a maximum size that you require an image so that it can be loaded as fast as possible, by using: - for JPEGs - and for Camera Raw files - for IEN files You can also set to automatically re-orient JPEG camera images Returns True if loading was successful, or False on error Note: You must define IE_DB_Helpers in iexHelperFunctions.pas to use this method Example // Load the image from the MyTableImageBlob field as fast as possible, but bigger than the displaying TImageEnView ImageEnView1.AutoShrink := True; ImageEnView1.IO.LoadFromBlobFast(MyTableImageBlob, ImageEnView1.Width, ImageEnView1.Height) !!} {$IFDEF IE_DB_Helpers} function TImageEnIOHelper.LoadFromBlobFast(aField: TBlobField; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; iImageIndex : Integer = -1 ): Boolean; var aMemStream: TMemoryStream; bFastLoad: Boolean; begin Result := True; try // SET PARAMS bFastLoad := (iMaxX > 0) and (iMaxY > 0); if bFastLoad then begin {$IFDEF IEINCLUDERAWFORMATS} // RAW PARAMS Params.RAW_HalfSize := (iMaxX <= SMALLEST_RAW_IMAGE_WIDTH) and (iMaxY <= SMALLEST_RAW_IMAGE_HEIGHT); Params.RAW_GetExifThumbnail := (iMaxX <= SMALLEST_RAW_THUMBNAIL_WIDTH) and (iMaxY <= SMALLEST_RAW_THUMBNAIL_HEIGHT); {$ENDIF} // JPEG PARAMS Params.Width := iMaxX; Params.Height := iMaxY; Params.JPEG_Scale := ioJPEG_AUTOCALC; Params.IEN_GetThumbnail := ( iMaxX <= IEGlobalSettings().ThumbnailSize ) and ( iMaxY <= IEGlobalSettings().ThumbnailSize ); // Is it a thumbnail? if iMaxX + iMaxY < 500 then Params.JPEG_DCTMethod := ioJPEG_IFAST; end else begin // reset any fast loading variables Params.RAW_HalfSize := false; Params.RAW_GetExifThumbnail := false; Params.JPEG_Scale := ioJPEG_fullsize; Params.JPEG_DCTMethod := ioJPEG_ISLOW; end; Params.EnableAdjustOrientation := bAutoAdjustOrientation; if iImageIndex <> -1 then Params.ImageIndex := iImageIndex; aMemStream := TMemoryStream.create; try aField.SaveToStream( aMemStream ); aMemStream.Position := 0; LoadFromStream(aMemStream); finally aMemStream.free; end; except result := false; end; end; {$ENDIF} {!! TImageEnIO.SaveToBlob Declaration function SaveToBlob(aField : TBlobField; aFileType : TIOFileType; iJpegQuality: integer = 0): Boolean; Description Uses streams to set a blob field with an image, optionally setting . You must specify a file type, e.g. ioJPEG. Returns True if saving was successful, or False on error Note: You must define IE_DB_Helpers in iexHelperFunctions.pas to use this method Example // Update the current image in the table with that displayed in our TImageEnView MyDBTable.Edit; ImageEnView1.IO.SaveToFileEx(MyDBTableImageField, ioJPEG, 90) MyDBTableEditDate.AsDateTime := Now; MyDBTable.Post; !!} {$IFDEF IE_DB_Helpers} function TImageEnIOHelper.SaveToBlob(aField : TBlobField; aFileType : TIOFileType; iJpegQuality: integer = 0): Boolean; const Reset_Jpeg_Orientation_On_Save = False; var aMemStream: TMemoryStream; aBlobStream: TStream; begin Result := False; if aFileType <> ioUnknown then try if iJpegQuality > 0 then Params.JPEG_Quality := iJpegQuality; if Reset_Jpeg_Orientation_On_Save then Params.EXIF_Orientation := _exoCorrectOrientation; aMemStream := TMemoryStream.create; try SaveToStream(aMemStream, aFileType); aMemStream.Position := 0; aBlobStream := aField.DataSet.CreateBlobStream( aField, bmWrite ); try aMemStream.SaveToStream(aBlobStream); finally aBlobStream.Free; end; result := true; finally aMemStream.free; end; except result := False; end; end; {$ENDIF} {$ENDIF} {$IFDEF Delphi2005orNewer} { TBitmapHelper } // Provide link to TBitmap references {!! TBitmap Description Standard Windows TBitmap class. See Delphi documentation for more detail. ImageEn provides a similar class for holding images in memory, . !!} {!! TBitmap.IEInitialize Declaration procedure IEInitialize(iWidth, iHeight: Integer; ABackgroundColor : TColor = clNone); Description Resizes a bitmap and optionally fills it with the specified color. Example // Make a bitmap of screen size and black background MyBitmap.IEInitialize(Screen.Width, Screen.Height, clBlack); !!} procedure TBitmapHelper.IEInitialize(iWidth, iHeight: Integer; ABackgroundColor : TColor = clNone); begin Width := iWidth; Height := iHeight; if ABackgroundColor <> clNone then begin Canvas.Brush.Color := ABackgroundColor; Canvas.FillRect(Rect(0, 0, Width, Height)); end; end; {!! TBitmap.IERotate Declaration procedure IERotate(Angle: double; AntiAliasMode: = ierFast; BackgroundColor: TColor = -1); Description Calls to rotate a TBitmap. Example // Rotate the image 90 deg. counter-clockwise MyBitmap.IERotate(90); // Rotate the image 45 deg. clockwise and fill new areas with black MyBitmap.IERotate(315, ierFast, clBlack); !!} procedure TBitmapHelper.IERotate(Angle: double; AntiAliasMode: TIEAntialiasMode = ierFast; BackgroundColor: TColor = -1); var AImageEnProc: TImageEnProc; begin AImageEnProc := TImageEnProc.CreateFromBitmap(self); try AImageEnProc.Rotate(Angle, AntialiasMode, BackgroundColor); finally AImageEnProc.Free; end; end; {!! TBitmap.IEFlip Declaration procedure IEFlip(Direction: ); Description Calls to flip a TBitmap. Example // Flip the bitmap image horizontally MyBitmap.IEFlip(fdHorizontal); !!} procedure TBitmapHelper.IEFlip(Direction: TFlipDir); var AImageEnProc: TImageEnProc; begin AImageEnProc := TImageEnProc.CreateFromBitmap(self); try AImageEnProc.Flip(Direction); finally AImageEnProc.Free; end; end; {!! TBitmap.IEResample Declaration procedure IEResample(iNewWidth, iNewHeight: integer; QualityFilter: TResampleFilter = rfNone; bMaintainAspectRatio : Boolean = False); Description Calls to resize a TBitmap and its content. Example // Resize the bitmap to screen dimensions (and good quality) MyBitmap.IEResample(Screen.Width, Screen.Height, rfLanczos3); !!} procedure TBitmapHelper.IEResample(iNewWidth, iNewHeight: integer; QualityFilter: TResampleFilter = rfNone; bMaintainAspectRatio : Boolean = False); var AImageEnProc: TImageEnProc; begin if (Width = iNewWidth) and (Height = iNewHeight) then exit; AImageEnProc := TImageEnProc.CreateFromBitmap(Self); try AImageEnProc.Resample(iNewWidth, iNewHeight, QualityFilter, bMaintainAspectRatio); finally AImageEnProc.Free; end; end; {!! TBitmap.IELoadFromFile Declaration function IELoadFromFile(const sFilename : string): Boolean; Description Allows a TBitmap to load any format supported by ImageEn. Returns True if loading was successful, or False on error Example // Load MyImage.jpeg into a bitmap MyBitmap.IELoadFromFile('D:\MyImage.jpeg') !!} function TBitmapHelper.IELoadFromFile(const sFilename: string): Boolean; begin Result := IELoadFromFileFast(sFilename, -1, -1); end; {!! TBitmap.IELoadFromStream Declaration function IELoadFromStream(Stream: TStream; FileType: = 0): Boolean; Description Allows a TBitmap to load any format supported by ImageEn. If you know the FileType type of the stream, pass it to speed up loading. Returns True if loading was successful, or False on error Example // Load MyImage.jpeg into a bitmap MyBitmap.IELoadFromStream( MyStream ) !!} function TBitmapHelper.IELoadFromStream(Stream: TStream; FileType: integer = 0): Boolean; begin Result := IELoadFromStreamFast(Stream, FileType, -1, -1); end; {!! TBitmap.IELoadFromFileFast Declaration function IELoadFromFileFast(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False ): Boolean; Description Allows you to load an image into a TBitmap using the fastest method by specifying the maximum size it is required. It uses: - for JPEGs - and for Camera Raw files - for IEN files You can also set to automatically re-orient JPEG camera images. Returns True if loading was successful, or False on error. Example // Load the specified image as fast as possible, but bigger than screen size MyBitmap.IELoadFromFileFast('D:\MyImage.jpeg', Screen.Width, Screen.Height) !!} function TBitmapHelper.IELoadFromFileFast(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False ): Boolean; var AImageEnIO: TImageEnIO; begin Result := True; try if IEFilenameInExtensions(sFilename, '.bmp') then begin LoadFromFile(sFilename); end else begin AImageEnIO := TImageEnIO.CreateFromBitmap(Self); // Loaded image may have transparency (e.g. WMF files), so match background color to existing background of images (i.e. honour IEInitialize) if (Width > 0) and (Height > 0) then AImageEnIO.Background := Canvas.Pixels[0, 0]; Result := AImageEnIO.LoadFromFileFast(sFilename, iMaxX, iMaxY, bAutoAdjustOrientation); AImageEnIO.Free; end; except result := False; end; end; {!! TBitmap.IELoadFromStreamFast Declaration function IELoadFromStreamFast(Stream: TStream; FileType: ; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False ): Boolean; Description Allows you to load an image into a TBitmap using the fastest method by specifying the maximum size it is required. It uses: - for JPEGs - and for Camera Raw files - for IEN files You can also set to automatically re-orient JPEG camera images. If you know the FileType type of the stream, pass it to speed up loading. Otherwise specify ioUnknown. Returns True if loading was successful, or False on error. Example // Load the specified image as fast as possible, but bigger than screen size MyBitmap.IELoadFromStreamFast( MyStream, ioUnknown, Screen.Width, Screen.Height ) !!} function TBitmapHelper.IELoadFromStreamFast(Stream: TStream; FileType: Integer; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False ): Boolean; var AImageEnIO: TImageEnIO; begin try AImageEnIO := TImageEnIO.CreateFromBitmap(Self); // Loaded image may have transparency (e.g. WMF files), so match background color to existing background of images (i.e. honour IEInitialize) if (Width > 0) and (Height > 0) then AImageEnIO.Background := Canvas.Pixels[0, 0]; Result := AImageEnIO.LoadFromStreamFast(Stream, FileType, iMaxX, iMaxY, bAutoAdjustOrientation); AImageEnIO.Free; except result := False; end; end; {!! TBitmap.LoadFromURL Declaration function LoadFromURL(const URL : WideString; const sProxyAddress : WideString = ''; const sProxyUser : WideString = ''; const sProxyPassword : WideString = '' ): Boolean; Description Load an image from the internet using the HTTP or FTP protocol. Note: See documentation for TImageEnIO.LoadFromURL Example MyBitmapLoadFromURL('http://www.imageen.com/image.jpg'); !!} function TBitmapHelper.LoadFromURL(const URL : WideString; const sProxyAddress : WideString = ''; const sProxyUser : WideString = ''; const sProxyPassword : WideString = '' ): Boolean; var AImageEnIO: TImageEnIO; begin try AImageEnIO := TImageEnIO.CreateFromBitmap(Self); IEGlobalSettings().ProxyAddress := sProxyAddress; IEGlobalSettings().ProxyUser := sProxyUser; IEGlobalSettings().ProxyPassword := sProxyPassword; Result := AImageEnIO.LoadFromURL(URL); AImageEnIO.Free; except result := False; end; end; {!! TBitmap.IESaveToFile Declaration function IESaveToFile(const sFilename : string; iJPEGQuality : Integer): Boolean; Description Allows a TBitmap to save to any format supported by ImageEn. If you are saving to JPEG you can also specify the . Returns True if saving was successful, or False on error Example // Save the image at 90% quality MyBitmap.IESaveToFile(SavePictureDialog1.FileName, 90); !!} function TBitmapHelper.IESaveToFile(const sFilename: string; iJPEGQuality : Integer): Boolean; var AImageEnIO: TImageEnIO; begin result := True; try if IEFilenameInExtensions(sFilename, '.bmp') then begin SaveToFile(sFilename); end else begin if PixelFormat = pfDevice then PixelFormat := pf24bit; AImageEnIO := TImageEnIO.CreateFromBitmap(Self); Result := AImageEnIO.SaveToFileEx(sFilename, iJPEGQuality); AImageEnIO.Free; end; except Result := False; end; end; {!! TBitmap.IESaveToStream Declaration function IESaveToStream(Stream: TStream; FileType: integer; iJPEGQuality : Integer): Boolean; Description Allows a TBitmap to save to any format supported by ImageEn. If you are saving to JPEG you can also specify the . You must specify the file format. Returns True if saving was successful, or False on error Example // Save the image at 90% quality MyBitmap.IESaveToStream( DestStream, ioJPEG, 90 ); !!} function TBitmapHelper.IESaveToStream(Stream: TStream; FileType: integer; iJPEGQuality : Integer): Boolean; var AImageEnIO: TImageEnIO; begin try if PixelFormat = pfDevice then PixelFormat := pf24bit; AImageEnIO := TImageEnIO.CreateFromBitmap(Self); Result := AImageEnIO.SaveToStreamEx(Stream, FileType, iJPEGQuality); AImageEnIO.Free; except Result := False; end; end; // CalcSoftShadowWidth: Use IESoftShadowSize {!! TBitmap.IELoadAsThumbnail Declaration function IELoadAsThumbnail(const sFilename: string; iMaxX, iMaxY: integer; bCanStretch: Boolean; bAutoAdjustOrientation: Boolean = False; QualityFilter : = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius : Integer = 4; iShadowOffset : Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite ) : Boolean; Description Loads an image of any format into a TBitmap reducing it to the specified size (while maintaining the aspect ratio, thus one of the dimensions is likely to be less than the specified value). Parameter Description iMaxX, iMaxY The maximum size of the new image (as the aspect ratio is maintained, one of the dimensions is likely to be less than the specified value) bCanStretch Set to false to avoid images smaller than iMaxX x iMaxY from being made larger bAutoAdjustOrientation Sets to automatically re-orient JPEG camera images QualityFilter Specify the quality that is used for rescaling the image bAddBorder Set to true to add a 1 pixel border to the thumbnail cBorderColor The color of the added border bAddShadow Add a solid or soft shadow to the image iBlurRadius Set to 0 to add a solid shadow or any other value for the width of the Soft Shadow iShadowOffset The offset of the shadow from the image cShadowColor The shadow color cBGColor The color of the image behind the shadow
Example // Load an image at the size 160x120 MyBitmap.IELoadAsThumbnail('D:\MyImage.jpeg', 160, 120, False); !!} function TBitmapHelper.IELoadAsThumbnail(const sFilename: string; iMaxX, iMaxY: integer; bCanStretch: Boolean; bAutoAdjustOrientation: Boolean = False; QualityFilter : TResampleFilter = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius : Integer = 4; iShadowOffset : Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite ) : Boolean; begin try Result := IELoadFromFileFast(sFilename, iMaxX, iMaxY, bAutoAdjustOrientation); if Result then IEConvertToThumbnail(iMaxX, iMaxY, bCanStretch, QualityFilter, bAddBorder, cBorderColor, bAddShadow, iBlurRadius, iShadowOffset, cShadowColor, cBGColor); except Result := False; end; end; procedure TBitmapHelper.ConvertTo24Bit; var AImageEnProc: TImageEnProc; begin AImageEnProc := TImageEnProc.CreateFromBitmap(Self); try AImageEnProc.ConvertTo24Bit; finally AImageEnProc.Free; end; end; {!! TBitmap.IEConvertToThumbnail Declaration procedure IEConvertToThumbnail(iMaxX, iMaxY: integer; bCanStretch: Boolean; QualityFilter : = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius : Integer = 4; iShadowOffset : Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite); Description Resize an image in a TBitmap to the specified size (while maintaining the aspect ratio, thus one of the dimensions is likely to be less than the specified value). Parameter Description iMaxX, iMaxY The maximum size of the new image (as the aspect ratio is maintained, one of the dimensions is likely to be less than the specified value) bCanStretch Set to false to avoid images smaller than iMaxX x iMaxY from being made larger bAutoAdjustOrientation Sets to automatically re-orient JPEG camera images QualityFilter Specify the quality that is used for rescaling the image bAddBorder Set to true to add a 1 pixel border to the thumbnail cBorderColor The color of the added border bAddShadow Add a solid or soft shadow to the image iBlurRadius Set to 0 to add a solid shadow or any other value for the width of the Soft Shadow iShadowOffset The offset of the shadow from the image cShadowColor The shadow color cBGColor The color of the image behind the shadow
Example // Resize the current bitmap image to 160x120 with a black border MyBitmap.IEConvertToThumbnail(160, 120, True, rfFastLinear, True, clBlack); !!} procedure TBitmapHelper.IEConvertToThumbnail(iMaxX, iMaxY: integer; bCanStretch: Boolean; QualityFilter : TResampleFilter = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius : Integer = 4; iShadowOffset : Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite); var ASize: TPoint; bUseSoftShadow : Boolean; begin bUseSoftShadow := iBlurRadius > 0; // if a shadow is to be added remove the size of the shadow from the bitmap dimension if bAddShadow and bUseSoftShadow then begin Dec(iMaxX, IESoftShadowSize(iBlurRadius, iShadowOffset, iShadowOffset)); Dec(iMaxY, IESoftShadowSize(iBlurRadius, iShadowOffset, iShadowOffset)); end else if bAddShadow and (bUseSoftShadow = false) then begin Dec(iMaxX, iShadowOffset); Dec(iMaxY, iShadowOffset); end; if baddshadow or bAddBorder then ConvertTo24Bit; if PixelFormat = pfCustom then PixelFormat := pf24bit; // RESIZE ASize := GetImageSizeWithinArea(Width, Height, iMaxX, iMaxY); if bCanStretch or (Width > ASize.X) then IEResample(ASize.X, ASize.Y, QualityFilter, false); // BORDER if bAddBorder then begin Canvas.pen.color := cBorderColor; Canvas.Polyline([Point(0, 0), Point(Width - 1, 0), Point(Width - 1, Height - 1), Point(0, Height - 1), Point(0, 0)]); end; // SHADOW if bAddShadow then begin if bUseSoftShadow then IEAddSoftShadow(iBlurRadius, iShadowOffset, cBGColor, _loTopLeft, cShadowColor) else begin // add back the pixels we removed width := width + iShadowOffset; Height := Height + iShadowOffset; // Draw the shadowm Canvas.Brush.color := cShadowColor; // along the right Canvas.FillRect(Rect(Width - iShadowOffset, 0, Width, Height)); // along the bottom Canvas.FillRect(Rect(0, Height - iShadowOffset, Width, Height)); // now add the background color Canvas.Brush.color := cBGColor; // at the top right Canvas.FillRect(Rect(Width - iShadowOffset, 0, Width, iShadowOffset)); // at the bottom left Canvas.FillRect(Rect(0, Height - iShadowOffset, iShadowOffset, Height)); end; end; end; {!! TBitmap.IEAddSoftShadow Declaration procedure IEAddSoftShadow(iBlurRadius: integer; iShadowOffset : Integer; cBGColor: TColor; LightOrigin: = _loTopLeft; cShadowColor: TColor = clblack); Description Calls to add a soft shadow to an image in a TBitmap Example // Add a soft shadow to the bitmap image MyBitmap.IEAddSoftShadow(3, 3, clWhite); !!} procedure TBitmapHelper.IEAddSoftShadow(iBlurRadius: integer; iShadowOffset : Integer; cBGColor: TColor; LightOrigin: TLightOrigin = _loTopLeft; cShadowColor: TColor = clblack); var ie: TImageEnView; iOffSetX, iOffSetY: integer; begin ie := TImageEnView.Create(nil); try ie.Background := cBGColor; ie.Bitmap.assign(Self); ie.update; iOffSetX := iShadowOffset; iOffSetY := iShadowOffset; if LightOrigin in [_loTopRight, _loBottomRight] then iOffSetX := -iOffSetX; if LightOrigin in [_loBottomLeft, _loBottomRight] then iOffSetY := -iOffSetY; ie.Proc.AddSoftShadow(iBlurRadius, iOffSetX, iOffSetY, TRUE, cShadowColor); ie.RemoveAlphaChannel(True); Self.assign(ie.bitmap); finally ie.Free; end; end; {!! TBitmap.PrintImage Declaration procedure PrintImage(PrtCanvas: TCanvas = nil; MarginLeft: double = 1; MarginTop: double = 1; MarginRight: double = 1; MarginBottom: double = 1; VerticalPos: TIEVerticalPos = ievpCenter; HorizontalPos: TIEHorizontalPos = iehpCenter; Size: TIESize = iesFitToPage; SpecWidth: double = 0; SpecHeight: double = 0; GammaCorrection: double = 1; SubsampleFilter: = rfFastLinear); Description Print the current bitmap by specifying margins, vertical position, horizontal position and size. Parameter Description PrtCanvas The canvas to bring to. Generally the application will pass this as Printer.Canvas MarginLeft Left page margin in inches (Specify zero for no margin) MarginTop Top page margin in inches (Specify zero for no margin) MarginRight Right page margin in inches (Specify zero for no margin) MarginBottom Bottom page margin in inches (Specify zero for no margin) VerticalPos How the image is vertically aligned on the page HorizontalPos How the image horizontally aligned on the page Size How the image should be sized for printing SpecWidth The absolute width of the image in inches if Size = iesSpecifiedSize. The number of pages wide if Size = iesMultiplePages SpecHeight The absolute height of the image in inches if Size = iesSpecifiedSize. The number of pages high if Size = iesMultiplePages GammaCorrection The gamma correction value (Specify 1.0 to disable gamma correction) SubsampleFilter The filter that is used to enhance quality if hte image needs to be resampled for printing
Example // Print the image in the center of the page at the original size Printer.BeginDoc; ABitmap.PrintImage(Printer.Canvas, 0, 0, 0, 0, ievpCenter, iehpCenter, iesNormal, 0, 0, 1); Printer.EndDoc; // Print the image in the center of the page stretched to page dimensions (respecting the proportions) Printer.BeginDoc; ABitmap.PrintImage(Printer.Canvas, 0, 0, 0, 0, ievpCenter, iehpCenter, iesFitToPage, 0, 0, 1); Printer.EndDoc; // Print the image as a poster, four pages wide and six pages high Printer.BeginDoc; ABitmap.PrintImage(Printer.Canvas, 0, 0, 0, 0, ievpCenter, iehpCenter, iesMultiplePages, 4, 6, 1); Printer.EndDoc; !!} procedure TBitmapHelper.PrintImage(PrtCanvas: TCanvas = nil; MarginLeft: double = 1; MarginTop: double = 1; MarginRight: double = 1; MarginBottom: double = 1; VerticalPos: TIEVerticalPos = ievpCenter; HorizontalPos: TIEHorizontalPos = iehpCenter; Size: TIESize = iesFitToPage; SpecWidth: double = 0; SpecHeight: double = 0; GammaCorrection: double = 1; SubsampleFilter: TResampleFilter = rfFastLinear); var AImageEnIO: TImageEnIO; begin AImageEnIO := TImageEnIO.CreateFromBitmap(Self); try AImageEnIO.PrintingFilterOnSubsampling := SubsampleFilter; AImageEnIO.PrintImage(PrtCanvas, MarginLeft, MarginTop, MarginRight, MarginBottom, VerticalPos, HorizontalPos, Size, SpecWidth, SpecHeight, GammaCorrection); finally AImageEnIO.Free; end; end; {$ENDIF} {$IFDEF Delphi2005orNewer} { TIEBitmapHelper } {!! TIEBitmap.IEInitialize Declaration procedure IEInitialize(iWidth, iHeight: Integer; ABackgroundColor : TColor = clNone); overload; procedure IEInitialize(iWidth, iHeight: Integer; Transparent: Boolean); overload; Description Resizes a TIEBitmap and optionally fills it with the specified color (or make transparent). Example // Resize the IEBitmap to screen size with a black background MyIEBitmap.IEInitialize(Screen.Width, Screen.Height, clBlack); // Resize the IEBitmap to screen size with transparency MyIEBitmap.IEInitialize(Screen.Width, Screen.Height, clBlack, True); !!} procedure TIEBitmapHelper.IEInitialize(iWidth, iHeight: Integer; ABackgroundColor: TColor = clNone); begin Width := iWidth; Height := iHeight; if ABackgroundColor <> clNone then begin Canvas.Brush.Color := ABackgroundColor; Canvas.FillRect(Rect(0, 0, Width, Height)); end; end; procedure TIEBitmapHelper.IEInitialize(iWidth, iHeight: Integer; Transparent: Boolean); begin Width := iWidth; Height := iHeight; if Transparent then AlphaChannel.Fill(0); end; const // The ImageEn types that can be loaded via WIC WIC_SUPPORTED_FILETYPES = [ ioBMP, ioPNG, ioICO, ioJPEG, ioGIF, ioTIFF, ioHDP ]; function TIEBitmapHelper.IELoadFromFileEx(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean; IOParams: TIOParams; iImageIndex: Integer ): Boolean; var AImageEnIO: TImageEnIO; bFastJPEG: Boolean; begin try // Can we use WIC to speed up loading? bFastJPEG := (iMaxX > 0) and (iMaxY > 0) and IEFilenameInExtensions(sFilename, '*.jpeg;*.jpg;*.jpe;'); {$IFDEF IEINCLUDEWIC} if ( IOParams = nil ) and ( bAutoAdjustOrientation = False ) and ( bFastJPEG = False ) and ( IEFilenameToInternalFileType( sFileName ) in WIC_SUPPORTED_FILETYPES ) then begin Result := WicRead( sFilename, iImageIndex ); end else {$ENDIF} begin AImageEnIO := TImageEnIO.CreateFromBitmap(Self); if assigned( IOParams ) then AImageEnIO.Params.Assign( IOParams as TIOParams ); if iImageIndex > 0 then Result := AImageEnIO.LoadFromFileEx(sFilename, bAutoAdjustOrientation, iImageIndex) else Result := AImageEnIO.LoadFromFileFast(sFilename, iMaxX, iMaxY, bAutoAdjustOrientation); if assigned( IOParams ) then TIOParams( IOParams ).Assign( AImageEnIO.Params ); AImageEnIO.Free; end; except result := False; end; end; {!! TIEBitmap.IELoadFromFile Declaration function IELoadFromFile(const sFilename : string; IOParams:
= nil; iImageIndex: Integer = 0): Boolean; Description Allows a TIEBitmap to load any format supported by ImageEn. You can optionally pass an object for the I/O parameters of the file. The index of an image to load within a multiframe format can also be specified. Returns True if loading was successful, or False on error Note: Unlike , IELoadFromStream will use for better performance where possible Example // Load the image specified in an open dialog ImageEnView1.Bitmap.IELoadFromFile(OpenPictureDialog1.FileName) !!} function TIEBitmapHelper.IELoadFromFile(const sFilename: string; IOParams: TIOParams = nil; iImageIndex: Integer = 0): Boolean; begin Result := IELoadFromFileEx(sFilename, -1, -1, False, IOParams, iImageIndex); end; {!! TIEBitmap.IELoadFromFileFast Declaration function IELoadFromFileFast(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; IOParams: = nil ): Boolean; Description Allows you to load an image into a TIEBitmap using the fastest method by specifying the maximum size it is required. It uses: - for JPEGs - and for Camera Raw files - for IEN files - for other file types (where possible) You can also set to automatically re-orient JPEG camera images. You can optionally pass an object for the I/O parameters of the file. Returns True if loading was successful, or False on error. Example // Load the specified image as fast as possible, but bigger than the screen dimensions MyIEBitmap.IELoadFromFileFast('D:\MyImage.jpeg', Screen.Width, Screen.Height) !!} function TIEBitmapHelper.IELoadFromFileFast(const sFilename: string; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; IOParams: TIOParams = nil ): Boolean; begin Result := IELoadFromFileEx( sFilename, iMaxX, iMaxY, bAutoAdjustOrientation, IOParams, 0 ); end; function TIEBitmapHelper.IELoadFromStreamEx(Stream: TStream; FileType: integer; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean; IOParams: TIOParams; iImageIndex: Integer ): Boolean; var AImageEnIO: TImageEnIO; bFastJPEG: Boolean; begin try if FileType = ioUnknown then FileType := FindStreamFormat( Stream ); // Can we use WIC to speed up loading? bFastJPEG := ( FileType = ioJPEG) and ( iMaxX > 0 ) and ( iMaxY > 0 ); {$IFDEF IEINCLUDEWIC} if ( IOParams = nil ) and ( bAutoAdjustOrientation = False ) and ( bFastJPEG = False ) and ( FileType in WIC_SUPPORTED_FILETYPES ) then begin Result := WicRead( Stream, FileType ); end else {$ENDIF} begin AImageEnIO := TImageEnIO.CreateFromBitmap(Self); if assigned( IOParams ) then AImageEnIO.Params.Assign( IOParams as TIOParams ); if iImageIndex > 0 then Result := AImageEnIO.LoadFromStreamEx(Stream, FileType, bAutoAdjustOrientation, iImageIndex) else Result := AImageEnIO.LoadFromStreamFast(Stream, FileType, iMaxX, iMaxY, bAutoAdjustOrientation); if assigned( IOParams ) then TIOParams( IOParams ).Assign( AImageEnIO.Params ); AImageEnIO.Free; end; except result := False; end; end; {!! TIEBitmap.IELoadFromStream Declaration function IELoadFromStream(Stream: TStream; FileType: integer = 0; IOParams: = nil; iImageIndex: Integer = 0): Boolean; Description Allows a TIEBitmap to load any format supported by ImageEn. If you know the FileType type of the stream, pass it to speed up loading. You can optionally pass an object for the I/O parameters of the file. The index of an image to load within a multiframe format can also be specified. Returns True if loading was successful, or False on error Note: Unlike , IELoadFromStream will use for better performance where possible Example ImageEnView1.Bitmap.IELoadFromStream(MyStream) !!} function TIEBitmapHelper.IELoadFromStream(Stream: TStream; FileType: integer = 0; IOParams: TIOParams = nil; iImageIndex: Integer = 0): Boolean; begin Result := IELoadFromStreamEx(Stream, FileType, -1, -1, False, IOParams, iImageIndex); end; {!! TIEBitmap.IELoadFromStreamFast Declaration function IELoadFromStreamFast(Stream: TStream; FileType: ; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; IOParams: = nil ): Boolean; Description Allows you to load an image into a TIEBitmap using the fastest method by specifying the maximum size it is required. It uses: - for JPEGs - and for Camera Raw files - for IEN files - for other file types (where possible) You can also set to automatically re-orient JPEG camera images. If you know the FileType type of the stream, pass it to speed up loading. Otherwise specify ioUnknown. You can optionally pass an object for the I/O parameters of the file. Returns True if loading was successful, or False on error. Example // Load the specified image as fast as possible, but bigger than the screen dimensions MyIEBitmap.IELoadFromStreamFast( MyStream, ioUnknown, Screen.Width, Screen.Height ) !!} function TIEBitmapHelper.IELoadFromStreamFast(Stream: TStream; FileType: integer; iMaxX, iMaxY: integer; bAutoAdjustOrientation: Boolean = False; IOParams: TIOParams = nil ): Boolean; begin Result := IELoadFromStreamEx(Stream, FileType, iMaxX, iMaxY, bAutoAdjustOrientation, IOParams, 0); end; {!! TIEBitmap.LoadFromURL Declaration function LoadFromURL(const URL : WideString; const sProxyAddress : WideString = ''; const sProxyUser : WideString = ''; const sProxyPassword : WideString = '' ): Boolean; Description Load an image from the internet using the HTTP or FTP protocol. Note: See documentation for TImageEnIO.LoadFromURL Example MyBitmap.LoadFromURL('http://www.imageen.com/image.jpg'); !!} function TIEBitmapHelper.LoadFromURL(const URL : WideString; const sProxyAddress : WideString = ''; const sProxyUser : WideString = ''; const sProxyPassword : WideString = '' ): Boolean; var AImageEnIO: TImageEnIO; begin try AImageEnIO := TImageEnIO.CreateFromBitmap(Self); IEGlobalSettings().ProxyAddress := sProxyAddress; IEGlobalSettings().ProxyUser := sProxyUser; IEGlobalSettings().ProxyPassword := sProxyPassword; Result := AImageEnIO.LoadFromURL(URL); AImageEnIO.Free; except result := False; end; end; {!! TIEBitmap.WicRead Declaration function WicRead(const sFilename: string; iImageIndex: Integer = 0; IOParams: = nil): Boolean; overload; function WicRead(Stream: TStream; FileType: integer = 0; iImageIndex: Integer = 0; IOParams: = nil): Boolean; overload; Description Use to load an image into a from a file or a stream. This will often be more than 100% faster than loading via native Delphi code. The index of an image to load within a multiframe format can also be specified. For streams you must specify the must be specified (one of: ioBMP, ioPNG, ioICO, ioJPEG, ioGIF, ioTIFF, ioHDP). Note: only supports BMP, PNG, ICO, JPEG, GIF, TIFF and HDP file types. Example if dlgOpenImage.Execute() then begin ImageEnView1.IEBitmap.WicRead( dlgOpenImage.FileName ); ImageEnView1.Update(); end; !!} {$IFDEF IEINCLUDEWIC} function TIEBitmapHelper.WicRead(const sFilename: string; iImageIndex: Integer = 0; IOParams: TIOParams = nil): Boolean; var fs: TIEWideFileStream; begin fs := TIEWideFileStream.create(sFileName, fmOpenRead or fmShareDenyWrite); try Result := WicRead( fs, IEFilenameToInternalFileType( sFilename ), iImageIndex, IOParams ); finally FreeAndNil(fs); end; end; {$ENDIF} {$IFDEF IEINCLUDEWIC} function TIEBitmapHelper.WicRead(Stream: TStream; FileType: integer = 0; iImageIndex: Integer = 0; IOParams: TIOParams = nil): Boolean; var wic: TIEWICReader; begin Result := True; try wic := TIEWICReader.Create; try wic.Open(Stream, FileType); if ( iImageIndex = 0 ) and ( IOParams <> nil ) and ( IOParams is TIOParams ) then iImageIndex := TIOParams( IOParams ).ImageIndex; IEInitialize( 0, 0 ); wic.GetFrame(iImageIndex, Self, TIOParams( IOParams ), nil ); if IsEmpty() then raise EIEException.create( 'Load error' ); finally wic.Free; // wic.Close called in Free end; except Result := False; end; end; {$ENDIF} {!! TIEBitmap.IESaveToFile Declaration function IESaveToFile(const sFilename : string; iJPEGQuality : Integer; IOParams: = nil): Boolean; Description Allows a TIEBitmap to save to any format supported by ImageEn. If you are saving to JPEG you can also specify the . You can optionally specify an object containing the I/O parameters of the file. Returns True if saving was successful, or False on error. Example // Save the image at 90% quality MyIEBitmap.IESaveToFile(SavePictureDialog1.FileName, 90) !!} function TIEBitmapHelper.IESaveToFile(const sFilename: string; iJPEGQuality: Integer; IOParams: TIOParams = nil): Boolean; var AImageEnIO: TImageEnIO; begin try if IEFilenameInExtensions(sFilename, '*.jpeg;*.jpg;*.jpe;') = False then begin Result := Write(sFilename, IOParams); end else begin AImageEnIO := TImageEnIO.CreateFromBitmap(Self); if assigned( IOParams ) then AImageEnIO.Params.Assign( IOParams as TIOParams ); Result := AImageEnIO.SaveToFileEx(sFilename, iJPEGQuality); if assigned( IOParams ) then TIOParams( IOParams ).Assign( AImageEnIO.Params ); AImageEnIO.Free; end; except Result := False; end; end; {!! TIEBitmap.IESaveToStream Declaration function IESaveToStream(Stream: TStream; FileType: ; iJPEGQuality : Integer; IOParams: = nil): Boolean; Description Allows a TIEBitmap to save to any format supported by ImageEn. If you are saving to JPEG you can also specify the . You must specify the file format. You can optionally specify an object containing the I/O parameters of the file. Returns True if saving was successful, or False on error. Example // Save the image at 90% quality MyIEBitmap.IESaveToStream(DestStream, ioJPEG, 90) !!} function TIEBitmapHelper.IESaveToStream(Stream: TStream; FileType: integer; iJPEGQuality: Integer; IOParams: TIOParams = nil): Boolean; var AImageEnIO: TImageEnIO; begin try if FileType <> ioJPEG then begin Result := Write(Stream, FileType, IOParams); end else begin AImageEnIO := TImageEnIO.CreateFromBitmap(Self); if assigned( IOParams ) then AImageEnIO.Params.Assign( IOParams as TIOParams ); Result := AImageEnIO.SaveToStreamEx(Stream, FileType, iJPEGQuality); if assigned( IOParams ) then TIOParams( IOParams ).Assign( AImageEnIO.Params ); AImageEnIO.Free; end; except Result := False; end; end; {!! TIEBitmap.IELoadAsThumbnail Declaration function IELoadAsThumbnail(const sFilename: string; iMaxX, iMaxY: integer; bCanStretch: Boolean; bAutoAdjustOrientation: Boolean = False; QualityFilter : = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius : Integer = 4; iShadowOffset : Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite ) : Boolean; Description Loads an image of any format into a TIEBitmap reducing it to the specified size (while maintaining the aspect ratio, thus one of the dimensions is likely to be less than the specified value). Parameter Description iMaxX, iMaxY The maximum size of the new image (as the aspect ratio is maintained, one of the dimensions is likely to be less than the specified value) bCanStretch Set to false to avoid images smaller than iMaxX x iMaxY from being made larger bAutoAdjustOrientation Sets to automatically re-orient JPEG camera images QualityFilter Specify the quality that is used for rescaling the image bAddBorder Set to true to add a 1 pixel border to the thumbnail cBorderColor The color of the added border bAddShadow Add a solid or soft shadow to the image iBlurRadius Set to 0 to add a solid shadow or any other value for the width of the Soft Shadow iShadowOffset The offset of the shadow from the image cShadowColor The shadow color cBGColor The color of the image behind the shadow
Example // Load an image at the size 160x120 MyIEBitmap.IELoadAsThumbnail('D:\MyImage.jpeg', 160, 120, False); !!} function TIEBitmapHelper.IELoadAsThumbnail(const sFilename: string; iMaxX, iMaxY: integer; bCanStretch: Boolean; bAutoAdjustOrientation: Boolean = False; QualityFilter: TResampleFilter = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius: Integer = 4; iShadowOffset: Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite ): Boolean; begin try Result := IELoadFromFileFast(sFilename, iMaxX, iMaxY, bAutoAdjustOrientation); if Result then IEConvertToThumbnail(iMaxX, iMaxY, bCanStretch, QualityFilter, bAddBorder, cBorderColor, bAddShadow, iBlurRadius, iShadowOffset, cShadowColor, cBGColor); except Result := False; end; end; procedure TIEBitmapHelper.ConvertTo24Bit; var AImageEnProc: TImageEnProc; begin AImageEnProc := TImageEnProc.CreateFromBitmap(Self); try AImageEnProc.ConvertTo24Bit; finally AImageEnProc.Free; end; end; {!! TIEBitmap.IEConvertToThumbnail Declaration procedure IEConvertToThumbnail(iMaxX, iMaxY: integer; bCanStretch: Boolean; QualityFilter : = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius : Integer = 4; iShadowOffset : Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite); Description Resize an image in a TIEBitmap to the specified size (while maintaining the aspect ratio, thus one of the dimensions is likely to be less than the specified value). Parameter Description iMaxX, iMaxY The maximum size of the new image (as the aspect ratio is maintained, one of the dimensions is likely to be less than the specified value) bCanStretch Set to false to avoid images smaller than iMaxX x iMaxY from being made larger bAutoAdjustOrientation Sets to automatically re-orient JPEG camera images QualityFilter Specify the quality that is used for rescaling the image bAddBorder Set to true to add a 1 pixel border to the thumbnail cBorderColor The color of the added border bAddShadow Add a solid or soft shadow to the image iBlurRadius Set to 0 to add a solid shadow or any other value for the width of the Soft Shadow iShadowOffset The offset of the shadow from the image cShadowColor The shadow color cBGColor The color of the image behind the shadow
Example // Resize the IEBitmap to 160x120 with a black border MyIEBitmap.IEConvertToThumbnail(160, 120, True, rfFastLinear, True, clBlack); !!} procedure TIEBitmapHelper.IEConvertToThumbnail(iMaxX, iMaxY: integer; bCanStretch: Boolean; QualityFilter: TResampleFilter = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius: Integer = 4; iShadowOffset: Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite); var ASize: tpoint; bUseSoftShadow: Boolean; begin bUseSoftShadow := iBlurRadius > 0; // if a shadow is to be added remove the size of the shadow from the bitmap dimension if bAddShadow and bUseSoftShadow then begin Dec(iMaxX, IESoftShadowSize(iBlurRadius, iShadowOffset, iShadowOffset)); Dec(iMaxY, IESoftShadowSize(iBlurRadius, iShadowOffset, iShadowOffset)); end else if bAddShadow and (bUseSoftShadow = false) then begin Dec(iMaxX, iShadowOffset); Dec(iMaxY, iShadowOffset); end; if baddshadow or bAddBorder then ConvertTo24Bit; // RESIZE ASize := GetImageSizeWithinArea(Width, Height, iMaxX, iMaxY); if bCanStretch or (Width > ASize.X) then Resample(ASize.X, ASize.Y, QualityFilter, false); // BORDER if bAddBorder then begin Canvas.pen.color := cBorderColor; Canvas.Polyline([Point(0, 0), Point(Width - 1, 0), Point(Width - 1, Height - 1), Point(0, Height - 1), Point(0, 0)]); end; // SHADOW if bAddShadow then begin if bUseSoftShadow then IEAddSoftShadow(iBlurRadius, iShadowOffset, cBGColor, _loTopLeft, cShadowColor) else begin // add back the pixels we removed width := width + iShadowOffset; Height := Height + iShadowOffset; // Draw the shadowm Canvas.Brush.color := cShadowColor; // along the right Canvas.FillRect(Rect(Width - iShadowOffset, 0, Width, Height)); // along the bottom Canvas.FillRect(Rect(0, Height - iShadowOffset, Width, Height)); // now add the background color Canvas.Brush.color := cBGColor; // at the top right Canvas.FillRect(Rect(Width - iShadowOffset, 0, Width, iShadowOffset)); // at the bottom left Canvas.FillRect(Rect(0, Height - iShadowOffset, iShadowOffset, Height)); end; end; end; {!! TIEBitmap.IEAddSoftShadow Declaration procedure IEAddSoftShadow(iBlurRadius: integer; iShadowOffset : Integer; cBGColor: TColor; LightOrigin: = _loTopLeft; cShadowColor: TColor = clblack); Description Calls to add a soft shadow to an image in a TIEBitmap Example // Add a soft shadow to the bitmap image MyIEBitmap.IEAddSoftShadow(3, 3, clWhite); !!} procedure TIEBitmapHelper.IEAddSoftShadow(iBlurRadius: integer; iShadowOffset: Integer; cBGColor: TColor; LightOrigin: TLightOrigin = _loTopLeft; cShadowColor: TColor = clblack); var ie: TImageEnView; iOffSetX, iOffSetY: integer; begin ie := TImageEnView.Create(nil); try ie.Background := cBGColor; ie.IEBitmap.assign(Self); ie.update; iOffSetX := iShadowOffset; iOffSetY := iShadowOffset; if LightOrigin in [_loTopRight, _loBottomRight] then iOffSetX := -iOffSetX; if LightOrigin in [_loBottomLeft, _loBottomRight] then iOffSetY := -iOffSetY; ie.Proc.AddSoftShadow(iBlurRadius, iOffSetX, iOffSetY, TRUE, cShadowColor); ie.RemoveAlphaChannel(True); Self.assign(ie.IEBitmap); finally ie.Free; end; end; {!! TIEBitmap.PrintImage Declaration procedure PrintImage(PrtCanvas: TCanvas = nil; MarginLeft: double = 1; MarginTop: double = 1; MarginRight: double = 1; MarginBottom: double = 1; VerticalPos: TIEVerticalPos = ievpCenter; HorizontalPos: TIEHorizontalPos = iehpCenter; Size: TIESize = iesFitToPage; SpecWidth: double = 0; SpecHeight: double = 0; GammaCorrection: double = 1; SubsampleFilter: = rfFastLinear); Description Print the current bitmap by specifying margins, vertical position, horizontal position and size. Parameter Description PrtCanvas The canvas to bring to. Generally the application will pass this as Printer.Canvas MarginLeft Left page margin in inches (Specify zero for no margin) MarginTop Top page margin in inches (Specify zero for no margin) MarginRight Right page margin in inches (Specify zero for no margin) MarginBottom Bottom page margin in inches (Specify zero for no margin) VerticalPos How the image is vertically aligned on the page HorizontalPos How the image horizontally aligned on the page Size How the image should be sized for printing SpecWidth The absolute width of the image in inches if Size = iesSpecifiedSize. The number of pages wide if Size = iesMultiplePages SpecHeight The absolute height of the image in inches if Size = iesSpecifiedSize. The number of pages high if Size = iesMultiplePages GammaCorrection The gamma correction value (Specify 1.0 to disable gamma correction) SubsampleFilter The filter that is used to enhance quality if hte image needs to be resampled for printing
Example // Print the image in the center of the page at the original size Printer.BeginDoc; ABitmap.PrintImage(Printer.Canvas, 0, 0, 0, 0, ievpCenter, iehpCenter, iesNormal, 0, 0, 1); Printer.EndDoc; // Print the image in the center of the page stretched to page dimensions (respecting the proportions) Printer.BeginDoc; ABitmap.PrintImage(Printer.Canvas, 0, 0, 0, 0, ievpCenter, iehpCenter, iesFitToPage, 0, 0, 1); Printer.EndDoc; // Print the image as a poster, four pages wide and six pages high Printer.BeginDoc; ABitmap.PrintImage(Printer.Canvas, 0, 0, 0, 0, ievpCenter, iehpCenter, iesMultiplePages, 4, 6, 1); Printer.EndDoc; !!} procedure TIEBitmapHelper.PrintImage(PrtCanvas: TCanvas = nil; MarginLeft: double = 1; MarginTop: double = 1; MarginRight: double = 1; MarginBottom: double = 1; VerticalPos: TIEVerticalPos = ievpCenter; HorizontalPos: TIEHorizontalPos = iehpCenter; Size: TIESize = iesFitToPage; SpecWidth: double = 0; SpecHeight: double = 0; GammaCorrection: double = 1; SubsampleFilter: TResampleFilter = rfFastLinear); var AImageEnIO: TImageEnIO; begin AImageEnIO := TImageEnIO.CreateFromBitmap(Self); try AImageEnIO.PrintingFilterOnSubsampling := SubsampleFilter; AImageEnIO.PrintImage(PrtCanvas, MarginLeft, MarginTop, MarginRight, MarginBottom, VerticalPos, HorizontalPos, Size, SpecWidth, SpecHeight, GammaCorrection); finally AImageEnIO.Free; end; end; {$ENDIF} // FILE FUNCTIONS {!! IEResampleImageFile Declaration function IEResampleImageFile(const sInFilename, sOutFilename: string; iJpegQuality: Integer; iMaxX: Integer; iMaxY: Integer; bCanStretch: Boolean = False; QualityFilter:
= rfLanczos3; bAutoAdjustOrientation: Boolean = False; bStripMetaData: Boolean = False ): Boolean; Description Loads an image of any format, resizes it and saves it to file (of any format). Parameter Description iJPEGQuality Specify the if sOutFilename is a JPEG iMaxX, iMaxY The maximum size of the new image (as the aspect ratio is maintained, one of the dimensions is likely to be less than the specified value) bCanStretch Set to false to avoid images smaller than iMaxX x iMaxY from being made larger QualityFilter Specify the quality that is used for rescaling the image bAutoAdjustOrientation Sets to automatically re-orient JPEG camera images bStripMetaData If enabled is used to strip meta-data from the image and make it smaller
Example // Resize MyImage.jpeg to the screen dimensions and save to MyImage_Screen.jpeg IEResampleImageFile('D:\MyImage.jpeg', 'D:\MyImage_Screen.jpeg', 90, Screen.Width, Screen.Height, False); !!} {$IFDEF Delphi2005orNewer} function IEResampleImageFile(const sInFilename, sOutFilename: string; iJpegQuality: Integer; iMaxX: Integer; iMaxY: Integer; bCanStretch: Boolean = False; QualityFilter: TResampleFilter = rfLanczos3; bAutoAdjustOrientation: Boolean = False; bStripMetaData: Boolean = False ): Boolean; var ABitmap : TBitmap; io: TImageEnIO; ASize: TPoint; SaveCursor: TCursor; begin result := true; saveCursor := Screen.Cursor; try Screen.Cursor := crHourGlass; ABitmap := TBitmap.create; io := TImageEnIO.CreateFromBitmap(ABitmap); try // Load full size for best quality (and avoid size discrepency if we are auto-rotating) if io.LoadFromFileFast(sInFilename, -1, -1, bAutoAdjustOrientation) = False then raise EIEException.create('Load error'); if bCanStretch or (ABitmap.width > iMaxX) or (ABitmap.height > iMaxY) then begin // Resize the image ASize := GetImageSizeWithinArea(ABitmap.width, ABitmap.height, iMaxX, iMaxY); ABitmap.IEResample(ASize.X, ASize.Y, QualityFilter); end; if bStripMetaData then io.Params.ResetInfo(); if not io.SaveToFileEx(sOutFilename, iJpegQuality) then raise EIEException.create('Save Error'); finally io.Free; ABitmap.free; Screen.Cursor := saveCursor; end; except result := false; end; end; {$ENDIF} {!! IEConvertImageFile Declaration function IEConvertImageFile(const sInFilename, sOutFilename: string; iJpegQuality: Integer; bAutoAdjustOrientation: Boolean = False ): Boolean; Description Change the format of a file (e.g. from BMP to JPEG). Specify the if sOutFilename is a JPEG. Returns False if an error was encountered. Example // Convert MyImage.jpeg to a BMP file IEConvertImageFile('D:\MyImage.jpeg', 'D:\MyImage.bmp', 90); !!} {$IFDEF Delphi2005orNewer} function IEConvertImageFile(const sInFilename, sOutFilename: string; iJpegQuality: Integer; bAutoAdjustOrientation: Boolean = False ): Boolean; var ABitmap: TIEBitmap; io: TImageEnIO; SaveCursor: TCursor; begin Result := True; if sInFilename = sOutFilename then exit; saveCursor := Screen.Cursor; try Screen.Cursor := crHourGlass; ABitmap := TIEBitmap.create; io := TImageEnIO.CreateFromBitmap(ABitmap); try if io.LoadFromFileFast(sInFilename, -1, -1, bAutoAdjustOrientation) = False then raise EIEException.create('Load error'); if bAutoAdjustOrientation then io.params.EXIF_Orientation := _exoCorrectOrientation; if io.SaveToFileEx(sOutFilename, iJpegQuality) = False then raise EIEException.create('Save error'); finally io.Free; ABitmap.free; Screen.Cursor := saveCursor; end; except result := false; end; end; {$ENDIF} {!! IECreateThumbnailFromFile Declaration function IECreateThumbnailFromFile(const sInFilename: string; const sOutFilename: string; iMaxX, iMaxY: integer; bCanStretch: Boolean; iJPEGQuality: integer; bAutoAdjustOrientation: Boolean = False; QualityFilter : = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius : Integer = 4; iShadowOffset : Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite ): Boolean; Description Creates a thumbnail from an image. Parameter Description iMaxX, iMaxY The maximum size of the new image (as the aspect ratio is maintained, one of the dimensions is likely to be less than the specified value) bCanStretch Set to false to avoid images smaller than iMaxX x iMaxY from being made larger bAutoAdjustOrientation Sets to automatically re-orient JPEG camera images QualityFilter Specify the quality that is used for rescaling the image bAddBorder Set to true to add a 1 pixel border to the thumbnail cBorderColor The color of the added border bAddShadow Add a solid or soft shadow to the image iBlurRadius Set to 0 to add a solid shadow or any other value for the width of the Soft Shadow iShadowOffset The offset of the shadow from the image cShadowColor The shadow color cBGColor The color of the image behind the shadow
Example // Create a thumbnail of MyImage.jpeg at size 160x120 and save to MyImage_Thumb.jpeg IECreateThumbnailFromFile('D:\MyImage.jpeg', 'D:\MyImage_Thumb.jpeg', 160, 120, False, 75) !!} {$IFDEF Delphi2005orNewer} function IECreateThumbnailFromFile(const sInFilename: string; const sOutFilename: string; iMaxX, iMaxY: integer; bCanStretch: Boolean; iJPEGQuality: integer; bAutoAdjustOrientation: Boolean = False; QualityFilter : TResampleFilter = rfLanczos3; bAddBorder: Boolean = False; cBorderColor: TColor = clBlack; bAddShadow: Boolean = False; iBlurRadius : Integer = 4; iShadowOffset : Integer = 4; cShadowColor: TColor = clBlack; cBGColor: TColor = clWhite ): Boolean; var ABitmap: TBitmap; SaveCursor: TCursor; begin result := True; saveCursor := Screen.Cursor; try Screen.Cursor := crHourGlass; ABitmap := TBitmap.create; try if ABitmap.IELoadAsThumbnail(sInFilename, iMaxX, iMaxY, bCanStretch, bAutoAdjustOrientation, QualityFilter, bAddBorder, cBorderColor, bAddShadow, iBlurRadius, iShadowOffset, cShadowColor, cBGColor) = False then raise EIEException.create('Thumb creation error'); if not ABitmap.IESaveToFile(sOutFilename, iJpegQuality) then raise EIEException.create('Save Error'); finally ABitmap.free; Screen.Cursor := saveCursor; end; except result := false; end; end; {$ENDIF} {!! GetImageDetails Declaration function GetImageDetails(const sFilename: string; out iWidth: Integer; out iHeight: Integer; out iBitsPerPixel: Integer ): Boolean; overload; function GetImageDetails(const sFilename: string): TPoint; overload; Description Return the size and color depth of an image. Result is false if a load error occurs. The second overload only returns only the width and height (which will be -1,-1 if a load error is encountered). Note: Color depth is TImageEnIO.Params.BitsPerSample * TImageEnIO.Params.SamplesPerPixel. See also: Example if GetImageDetails('D:\MyImage.jpeg', iWidth, iHeight, iBitsPerPixel) then begin lblWidth.Caption := IntToStr(iWidth); lblHeight.Caption := IntToStr(iHeight); lblColorDepth.Caption := BitsPerPixelToStr(iBitsPerPixel); end; !!} function GetImageDetails(const sFilename: string; out iWidth: Integer; out iHeight: Integer; out iBitsPerPixel: Integer ): Boolean; var io: TImageEnIO; begin result := False; iWidth := 0; iHeight := 0; iBitsPerPixel := 0; try io := TImageEnIO.Create(nil); try io.ParamsFromFile(sFilename); if (io.Aborting = False) and (io.params.Width > 0) then begin result := True; iWidth := io.params.Width; iHeight := io.params.Height; iBitsPerPixel := io.Params.BitsPerSample * io.Params.SamplesPerPixel; end; finally io.free; end; except // LOAD ERROR end; end; function GetImageDetails(const sFilename: string): TPoint; var iWidth: Integer; iHeight: Integer; iBitsPerPixel: Integer; begin Result.x := -1; Result.y := -1; if GetImageDetails(sFilename, iWidth, iHeight, iBitsPerPixel) then begin Result.x := iWidth; Result.y := iHeight; end; end; {!! GetExifOrFileCreationDate Declaration function GetExifOrFileCreationDate(const sFilename: string; bReturnCreateDate: Boolean = true ): TDateTime; Description Calls to retrieve the creation date specified in a camera image. If the image does not contain a date, you can optionally return the Windows File Creation Date. Example // Get digital camera date for for MyImage.jpeg aCreateDate := GetExifOrFileCreationDate('D:\MyImage.jpeg', True); !!} function GetExifOrFileCreationDate(const sFilename: string; bReturnCreateDate: Boolean = true {if true then the create date is returned if there is no exif date} ): TDateTime; var iFileSizeBytes: Int64; dtModifiedDate: TDateTime; io: TImageEnIO; begin result := 0; try if IEFileIsOfFormat(sFilename, ioJPEG) then try io := TImageEnIO.Create(nil); try io.ParamsFromFile(sFilename); if (io.Aborting = False) and (io.params.EXIF_HasEXIFData) then Result := EXIFDateToDateTime(string(io.params.EXIF_DateTimeOriginal)); finally io.free; end; except // LOAD ERROR end; if (Result < 1) and bReturnCreateDate then IEGetFileDetails(sFilename, iFileSizeBytes, Result, dtModifiedDate); except // GetFileDateTime Error end; end; {!! JPEGLosslessRotateFile Declaration function JPEGLosslessRotateFile(const sInFilename : WideString; const sOutFilename : WideString; iRotateAngle : integer) : Boolean; overload; function JPEGLosslessRotateFile(const sFilename : WideString; iRotateAngle : integer) : Boolean; overload; Description Calls or to losslessly rotate a JPEG image, but allows you to specify a rotation angle that matches the Angle parameter. Note: All comments and markers are copied and the EXIF orientation and thumbnail are updated. All values other than -90, 90, 180, -180, 270 and -270 are ignored Example // Rotate MyImage.jpeg 90 deg. counter-clockwise and save to MyImage_ROT.jpeg JPEGLosslessRotateFile('D:\MyImage.jpeg', 'D:\MyImage_ROT.jpeg', 90); !!} function JPEGLosslessRotateFile(const sInFilename : WideString; const sOutFilename : WideString; iRotateAngle : integer) : Boolean; const Update_EXIF_On_Transform = True; // write updated orientation detail and rotate thumbnail var SaveCursor: TCursor; RotType: TIEJpegTransform; begin // Note: ImageEn Rotation is the opposite of JpegLosslessTransform case iRotateAngle of 270, -90 : RotType := jtRotate90; 180, -180 : RotType := jtRotate180; 90, -270 : RotType := jtRotate270; else {90} raise EIEException.create('Unsupported lossless rotation angle'); end; saveCursor := Screen.Cursor; Screen.Cursor := crHourGlass; try if (sOutFilename = '') or SameText(sInFilename, sOutFilename) then result := JpegLosslessTransform2(sInFilename, RotType, false, jcCopyAll, rect(0, 0, 0, 0), Update_EXIF_On_Transform) else result := JpegLosslessTransform(sInFilename, sOutFilename, RotType, false, jcCopyAll, rect(0, 0, 0, 0), Update_EXIF_On_Transform); finally Screen.Cursor := saveCursor; end; end; function JPEGLosslessRotateFile(const sFilename : WideString; iRotateAngle : integer) : Boolean; begin Result := JPEGLosslessRotateFile(sFilename, '', iRotateAngle); end; {!! JPEGLosslessFlipFile Declaration function JPEGLosslessFlipFile(const sInFilename : WideString; const sOutFilename : WideString; Direction: TFlipDir) : Boolean; overload; function JPEGLosslessFlipFile(const sFilename : WideString; Direction: TFlipDir) : Boolean; overload; Description Calls or to losslessly flip a JPEG image. Note: All comments and markers are copied and the EXIF orientation and thumbnail are updated. Example // Flip MyImage.jpeg horizontally JPEGLosslessRotateFile('D:\MyImage.jpeg', fdHorizontal); !!} function JPEGLosslessFlipFile(const sInFilename : WideString; const sOutFilename : WideString; Direction: TFlipDir) : Boolean; const Update_EXIF_On_Transform = True; // write updated orientation detail and rotate thumbnail var SaveCursor: TCursor; RotType: TIEJpegTransform; begin saveCursor := Screen.Cursor; Screen.Cursor := crHourGlass; try if Direction = fdVertical then RotType := jtVertFlip else RotType := jtHorizFlip; if (sOutFilename = '') or SameText(sInFilename, sOutFilename) then result := JpegLosslessTransform2(sInFilename, RotType, false, jcCopyAll, rect(0, 0, 0, 0), Update_EXIF_On_Transform) else result := JpegLosslessTransform(sInFilename, sOutFilename, RotType, false, jcCopyAll, rect(0, 0, 0, 0), Update_EXIF_On_Transform); finally Screen.Cursor := saveCursor; end; end; function JPEGLosslessFlipFile(const sFilename : WideString; Direction: TFlipDir) : Boolean; begin Result := JPEGLosslessFlipFile(sFilename, '', Direction); end; {!! IERotateImageFile Declaration function IERotateImageFile(const sFilename : string; iJpegQuality : integer; iRotateAngle : integer; AntiAliasMode: TIEAntialiasMode = ierFast; bCanUseLossless: Boolean = true; cBackgroundColor: TColor = clWhite): Boolean; overload; function IERotateImageFile(const sInFilename, sOutFilename : string; iJpegQuality : integer; iRotateAngle : integer; AntiAliasMode: TIEAntialiasMode = ierFast; bCanUseLossless: Boolean = true; cBackgroundColor: TColor = clWhite): Boolean; overload; Description Calls to rotate an image file and resave it (optionally to an alternative file). if bCanUseLossless is specified then is used where possible for JPEG files. See also: Example // This will result in a lossless rotation IERotateImageFile('D:\MyImage.jpg', 90, ierFast, True); // This will be a lossy rotation IERotateImageFile('D:\MyImage.jpg', 45, ierFast, True, clBlack); !!} {$IFDEF Delphi2005orNewer} function IERotateImageFile(const sInFilename, sOutFilename : string; iJpegQuality : integer; iRotateAngle : integer; AntiAliasMode: TIEAntialiasMode = ierFast; bCanUseLossless: Boolean = true; // if true then a lossless Flip is used for JPEG images cBackgroundColor: TColor = clWhite): Boolean; var ABitmap: TIEBitmap; io: TImageEnIO; saveCursor : TCursor; begin result := True; if iRotateAngle = 0 then begin // Result will not be valid (exist) if we we are outputting a different file Result := SameText(sInFilename, sOutFilename); exit; end; // can we rotate it losslessly? if bCanUseLossless and IEFileIsOfFormat(sInFilename, ioJPEG) and IEFileIsOfFormat(sOutFilename, ioJPEG) and (iRotateAngle mod 90 = 0 {i.e. =90, 180 or 270}) then begin // rotate the image losslessly Result := JPEGLosslessRotateFile(sInFilename, sOutFilename, iRotateAngle); exit; end; try saveCursor := Screen.Cursor; ABitmap := TIEBitmap.create; io := TImageEnIO.CreateFromBitmap(ABitmap); try Screen.Cursor := crHourGlass; if io.LoadFromFileEx(sInFilename, False) = False then raise EIEException.create('Load Error'); ABitmap.Rotate(iRotateAngle, AntialiasMode, cBackgroundColor); if io.SaveToFileEx(sOutFilename, iJpegQuality) = False then raise EIEException.create('Save Error'); finally io.free; ABitmap.free; Screen.Cursor := saveCursor; end; except result := false; end; end; function IERotateImageFile(const sFilename : string; iJpegQuality : integer; iRotateAngle : integer; AntiAliasMode: TIEAntialiasMode = ierFast; bCanUseLossless: Boolean = true; // if true then a lossless Flip is used for JPEG images cBackgroundColor: TColor = clWhite): Boolean; begin Result := IERotateImageFile(sFilename, sFilename, iJpegQuality, iRotateAngle, AntiAliasMode, bCanUseLossless, cBackgroundColor); end; {$ENDIF} {!! IEFlipImageFile Declaration function IEFlipImageFile(const sFilename : string; iJpegQuality : integer; Direction: TFlipDir; bCanUseLossless: Boolean = true ): Boolean; overload; function IEFlipImageFile(const sInFilename, sOutFilename : string; iJpegQuality : integer; Direction: TFlipDir; bCanUseLossless: Boolean = true ): Boolean; overload; Description Calls to Flip an image file and resave it (optionally to an alternative file). if bCanUseLossless is specified then is used where possible for JPEG files. Example // Flip an image horizontally and save to a JPEG IEFlipImageFile('D:\Source.bmp', 'D:\MyImage.jpg', 90, fdHorizontal); // Flip an image vertically. This will be lossless as source and destination are JPEG IEFlipImageFile('D:\MyJPEG.jpg', 90, fdVertical); !!} {$IFDEF Delphi2005orNewer} function IEFlipImageFile(const sInFilename, sOutFilename : string; iJpegQuality : integer; Direction: TFlipDir; bCanUseLossless: Boolean = true ): Boolean; var ABitmap: TIEBitmap; io: TImageEnIO; saveCursor : TCursor; begin result := True; // can we Flip it losslessly? if bCanUseLossless and IEFileIsOfFormat(sInFilename, ioJPEG) and IEFileIsOfFormat(sOutFilename, ioJPEG) then begin // Flip the image losslessly Result := JPEGLosslessFlipFile(sInFilename, sOutFilename, Direction); exit; end; try saveCursor := Screen.Cursor; ABitmap := TIEBitmap.create; io := TImageEnIO.CreateFromBitmap(ABitmap); try Screen.Cursor := crHourGlass; if io.LoadFromFileEx(sInFilename, False) = False then raise EIEException.create('Load Error'); ABitmap.Flip(Direction); if io.SaveToFileEx(sOutFilename, iJpegQuality) = False then raise EIEException.create('Save Error'); finally io.free; ABitmap.free; Screen.Cursor := saveCursor; end; except result := false; end; end; function IEFlipImageFile(const sFilename : string; iJpegQuality : integer; Direction: TFlipDir; bCanUseLossless: Boolean = true ): Boolean; overload; begin Result := IEFlipImageFile(sFilename, sFilename, iJpegQuality, Direction, bCanUseLossless); end; {$ENDIF} {!! IEReadCorrectOrientationOfImageFile Declaration function IEReadCorrectOrientationOfImageFile(const sFilename : string; bConservativeChecking : Boolean = True) : Integer; Description Upmarket digital cameras will automatically store the correct orientation of an image when the camera is rotated to take a portrait photo. This function calls to retrieve the desired orientation for a JPEG camera image. If bConservativeChecking is true it performs some further checking to ensure the returned value is accurate (e.g. to avoid problems where the photo has already been rotated in another program). Example iBestOrientation := IEReadCorrectOrientationOfImageFile('D:\MyImage.jpeg', True); !!} // checks the EXIF orientation flag of the image to see whether it needs rotating { For a file returns: -1 : Error 0 : Is not a JPEG _exoCorrectOrientation : Doesn't need rotating Or: _exoNeeds90RotateCW, _exoNeeds180Rotate, _exoNeeds270RotateCW Here is an explanation of EXIF Rotate Values: 1 2 3 4 5 6 7 8 888888 888888 88 88 8888888888 88 88 8888888888 88 88 88 88 88 88 88 88 88 88 88 88 8888 8888 8888 8888 88 8888888888 8888888888 88 88 88 88 88 88 88 888888 888888 } function IEReadCorrectOrientationOfImageFile(const sFilename : string; bConservativeChecking : Boolean = True) : Integer; var io: TImageEnIO; SaveCursor: TCursor; bIsPortraitImage: Boolean; bSizeMatchesFields: Boolean; begin Result := 0; // if it is not a JPEG then it can't be processed if IEFileIsOfFormat(sFilename, ioJPEG) = False then exit; try saveCursor := Screen.Cursor; io := TImageEnIO.Create(nil); try Screen.Cursor := crHourGlass; io.ParamsFromFile(sFilename); if io.Aborting then raise EIEException.create('Load Error'); if io.params.EXIF_HasEXIFData then begin Result := io.params.EXIF_Orientation; // check to see if hte image dimensions match those in the EXIF data if (bConservativeChecking) and (Result <> _exoCorrectOrientation) then begin bIsPortraitImage := io.params.Height > io.params.Width; bSizeMatchesFields := (io.params.EXIF_EXIFImageWidth = io.params.width) and (io.params.EXIF_EXIFImageHeight = io.params.Height); if (Result in [_exoNeeds90RotateCW, _exoNeeds270RotateCW]) and bIsPortraitImage then // camera photos are already landscape so it looks like this one is already rotated result := _exoCorrectOrientation else if bSizeMatchesFields = False then result := _exoCorrectOrientation; end; // The following are not used by cameras so just report as correct if result in [_exoNeedsHorizontalFlip, _exoNeedsVerticalFlip, _exoNeedsHorzAndVertFlip, _exoNeedsFlipHorzAnd90Rotate] then result := _exoCorrectOrientation; end; finally io.free; Screen.Cursor := saveCursor; end; except Result := -1; end; end; {!! IEAutomaticallyRotateImageFile Declaration function IEAutomaticallyRotateImageFile(const sFilename : string) : Integer; Description Upmarket digital cameras will automatically store the correct orientation of an image when the camera is rotated to take a portrait photo. This function calls to retrieve the desired orientation for a JPEG camera image and then calls to losslessly rotate it. If bConservativeChecking is true it performs some further checking to ensure the orientation data is accurate (e.g. to avoid problems where the photo has already been rotated in another program). Example // Rotate MyImage.jpeg if it is not correctly oriented IEAutomaticallyRotateImageFile('D:\MyImage.jpeg', True); !!} function IEAutomaticallyRotateImageFile(const sFilename : string; bConservativeChecking : Boolean = True) : Integer; var SaveCursor: TCursor; RotType: TIEJpegTransform; begin saveCursor := Screen.Cursor; try Screen.Cursor := crHourGlass; Result := IEReadCorrectOrientationOfImageFile(sFilename, bConservativeChecking); // Needs rotation? if Result in [_exoNeeds90RotateCW, _exoNeeds180Rotate, _exoNeeds270RotateCW] then begin // Note: ImageEn Rotation is the opposite of JpegLosslessTransform case Result of _exoNeeds90RotateCW : RotType := jtRotate90; _exoNeeds180Rotate : RotType := jtRotate180; _exoNeeds270RotateCW : RotType := jtRotate270; else exit; // avoid compiler warning end; if JpegLosslessTransform2(sFilename, RotType, false, jcCopyAll, rect(0, 0, 0, 0), True) = False then Result := -1; end; finally Screen.Cursor := saveCursor; end; end; {!! BitsPerPixelToStr Declaration function BitsPerPixelToStr(iBitsPerPixel: Integer) : string; Description Provides a suitable textual representation of a Bits per Sample value (i.e. BitsPerSample * SamplesPerPixel). Example outputs: Monochrome, 128 colors, 24 bit color, etc. Example // Display the color depth of the currently displayed image lblColorDepth.Caption := BitsPerPixelToStr(ImageEnView1.IO.Params.BitsPerSample * ImageEnView1.IO.Params.SamplesPerPixel); !!} function BitsPerPixelToStr(iBitsPerPixel: Integer) : string; var iColors: Integer; begin if iBitsPerPixel < 1 then result := '' else if iBitsPerPixel = 1 then result := 'Monochrome' else if iBitsPerPixel <= 8 then begin iColors := Trunc(Power(2, iBitsPerPixel)); result := format('%d colors', [iColors]) end else if iBitsPerPixel = 12 then result := '4,096 colors' else if (iBitsPerPixel = 15) or (iBitsPerPixel = 16) then result := '65,536 colors' // Note: Generally true, but there are exceptions else {24, 32, etc} result := format('%d bit color', [iBitsPerPixel]); end; {!! QualityToZoomFilter Declaration function QualityToZoomFilter(Quality: ): ; Description Provide quick access to the most common zoom filters ieLow : Returns rfNone, no quality filtering is used ieMedium : Returns rfFastLinear, a good quality but very fast filter ieHigh : Returns rfLanczos3, a very high quality filter Example // Set Quality filter to ComboBox selection (which contains values: Low, Medium and High) frmMain.ImageEnView1.ZoomFilter := QualityToZoomFilter( cmbQuality.ItemIndex ); See Also - !!} function QualityToZoomFilter(Quality: TIEQuality): TResampleFilter; const High_Quality_Filter = rfLanczos3; Medium_Quality_Filter = rfFastLinear; Low_Quality_Filter = rfNone; begin case Quality of ieHigh : result := HIGH_QUALITY_FILTER; ieMedium : result := MEDIUM_QUALITY_FILTER; else {ieLow} result := LOW_QUALITY_FILTER; end; end; type HourglassHandler = class(TInterfacedObject) private fOldCursor: TCursor; public constructor Create; destructor Destroy; override; end; { HourglassHandler } constructor HourglassHandler.Create; begin fOldCursor := Screen.Cursor; Screen.Cursor := crHourGlass; end; destructor HourglassHandler.Destroy; begin Screen.Cursor := fOldCursor; inherited; end; {!! ShowTempHourglass Declaration function ShowTempHourglass: IUnknown; Description Change the cursor to an hourglass during the current procedure (i.e. will revert to the previous cursor once we go out of scope) Example Load an image when a button is clicked. Show hourglass during loading procedure TMain.Button1Click(Sender: TObject); begin ShowTempHourglass; ImageEnView1.IO.LoadFromFile('C:\MyImage.jpg'); end; !!} function ShowTempHourglass: IUnknown; begin result := HourglassHandler.Create end; {!! iexHelperFunctions iexHelperFunctions.pas provides helper functions for , TBitmap and , plus a variety of file functions. These methods provide quicker access to some ImageEn functionality for common tasks. Simply add iexHelperFunctions to your uses clause to access the new methods IMAGEENIO HELPER FUNCTIONS Adds shortcut methods to the class: BITMAP HELPER FUNCTIONS Adds more functionality to the TBitmap class: IEBITMAP HELPER FUNCTIONS Adds more functionality to the class: FILE FUNCTIONS Perform image manipulation functions without direct use of ImageEn components: CANVAS FUNCTIONS Functions to output custom shapes and wallpaper to a TCanvas or TBitmap OTHER FUNCTIONS Other functions that may be useful with ImageEn: * Note: Delphi/C++ 2005 or newer is required to use helper classes !!} end.