root / Imaging / ImagingComponents.pas @ 0:95bd93c28625
History | View | Annotate | Download (41.2 kB)
| 1 | {
|
|---|---|
| 2 | $Id: ImagingComponents.pas 110 2007-11-18 21:23:59Z galfar $ |
| 3 | Vampyre Imaging Library |
| 4 | by Marek Mauder |
| 5 | http://imaginglib.sourceforge.net |
| 6 | |
| 7 | The contents of this file are used with permission, subject to the Mozilla |
| 8 | Public License Version 1.1 (the "License"); you may not use this file except |
| 9 | in compliance with the License. You may obtain a copy of the License at |
| 10 | http://www.mozilla.org/MPL/MPL-1.1.html |
| 11 | |
| 12 | Software distributed under the License is distributed on an "AS IS" basis, |
| 13 | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for |
| 14 | the specific language governing rights and limitations under the License. |
| 15 | |
| 16 | Alternatively, the contents of this file may be used under the terms of the |
| 17 | GNU Lesser General Public License (the "LGPL License"), in which case the |
| 18 | provisions of the LGPL License are applicable instead of those above. |
| 19 | If you wish to allow use of your version of this file only under the terms |
| 20 | of the LGPL License and not to allow others to use your version of this file |
| 21 | under the MPL, indicate your decision by deleting the provisions above and |
| 22 | replace them with the notice and other provisions required by the LGPL |
| 23 | License. If you do not delete the provisions above, a recipient may use |
| 24 | your version of this file under either the MPL or the LGPL License. |
| 25 | |
| 26 | For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html |
| 27 | } |
| 28 | |
| 29 | { This unit contains VCL/CLX/LCL TGraphic descendant which uses Imaging library
|
| 30 | for saving and loading.} |
| 31 | unit ImagingComponents;
|
| 32 | |
| 33 | {$I ImagingOptions.inc}
|
| 34 | |
| 35 | interface
|
| 36 | |
| 37 | uses
|
| 38 | SysUtils, Types, Classes, |
| 39 | {$IFDEF MSWINDOWS}
|
| 40 | Windows, |
| 41 | {$ENDIF}
|
| 42 | {$IFDEF COMPONENT_SET_VCL}
|
| 43 | Graphics, |
| 44 | {$ENDIF}
|
| 45 | {$IFDEF COMPONENT_SET_CLX}
|
| 46 | Qt, |
| 47 | QGraphics, |
| 48 | {$ENDIF}
|
| 49 | {$IFDEF COMPONENT_SET_LCL}
|
| 50 | InterfaceBase, |
| 51 | GraphType, |
| 52 | Graphics, |
| 53 | LCLType, |
| 54 | LCLIntf, |
| 55 | {$ENDIF}
|
| 56 | ImagingTypes, Imaging, ImagingClasses; |
| 57 | |
| 58 | type
|
| 59 | { Graphic class which uses Imaging to load images.
|
| 60 | It has standard TBitmap class as ancestor and it can |
| 61 | Assign also to/from TImageData structres and TBaseImage |
| 62 | classes. For saving is uses inherited TBitmap methods. |
| 63 | This class is automatically registered to TPicture for all |
| 64 | file extensions supported by Imaging (useful only for loading). |
| 65 | If you just want to load images in various formats you can use this |
| 66 | class or simply use TPicture.LoadFromXXX which will create this class |
| 67 | automatically. For TGraphic class that saves with Imaging look |
| 68 | at TImagingGraphicForSave class.} |
| 69 | TImagingGraphic = class(TBitmap)
|
| 70 | protected
|
| 71 | procedure ReadDataFromStream(Stream: TStream); virtual; |
| 72 | procedure AssignTo(Dest: TPersistent); override; |
| 73 | public
|
| 74 | { Loads new image from the stream. It can load all image
|
| 75 | file formats supported by Imaging (and enabled of course) |
| 76 | even though it is called by descendant class capable of |
| 77 | saving only one file format.} |
| 78 | procedure LoadFromStream(Stream: TStream); override; |
| 79 | { Copies the image contained in Source to this graphic object.
|
| 80 | Supports also TBaseImage descendants from ImagingClasses unit. } |
| 81 | procedure Assign(Source: TPersistent); override; |
| 82 | { Copies the image contained in TBaseImage to this graphic object.}
|
| 83 | procedure AssignFromImage(Image: TBaseImage);
|
| 84 | { Copies the current image to TBaseImage object.}
|
| 85 | procedure AssignToImage(Image: TBaseImage);
|
| 86 | { Copies the image contained in TImageData structure to this graphic object.}
|
| 87 | procedure AssignFromImageData(const ImageData: TImageData); |
| 88 | { Copies the current image to TImageData structure.}
|
| 89 | procedure AssignToImageData(var ImageData: TImageData); |
| 90 | end;
|
| 91 | |
| 92 | TImagingGraphicClass = class of TImagingGraphic; |
| 93 | |
| 94 | { Base class for file format specific TGraphic classes that use
|
| 95 | Imaging for saving. Each descendant class can load all file formats |
| 96 | supported by Imaging but save only one format (TImagingBitmap |
| 97 | for *.bmp, TImagingJpeg for *.jpg). Format specific classes also |
| 98 | allow easy access to Imaging options that affect saving of files |
| 99 | (they are properties here).} |
| 100 | TImagingGraphicForSave = class(TImagingGraphic)
|
| 101 | protected
|
| 102 | FDefaultFileExt: string;
|
| 103 | FSavingFormat: TImageFormat; |
| 104 | procedure WriteDataToStream(Stream: TStream); virtual; |
| 105 | public
|
| 106 | constructor Create; override; |
| 107 | { Saves the current image to the stream. It is saved in the
|
| 108 | file format according to the DefaultFileExt property. |
| 109 | So each descendant class can save some other file format.} |
| 110 | procedure SaveToStream(Stream: TStream); override; |
| 111 | { Returns TImageFileFormat descendant for this graphic class.}
|
| 112 | class function GetFileFormat: TImageFileFormat; virtual; abstract; |
| 113 | {$IFDEF COMPONENT_SET_LCL}
|
| 114 | { Returns file extensions of this graphic class.}
|
| 115 | class function GetFileExtensions: string; override; |
| 116 | { Returns default MIME type of this graphic class.}
|
| 117 | function GetDefaultMimeType: string; override; |
| 118 | {$ENDIF}
|
| 119 | { Default (the most common) file extension of this graphic class.}
|
| 120 | property DefaultFileExt: string read FDefaultFileExt; |
| 121 | end;
|
| 122 | |
| 123 | TImagingGraphicForSaveClass = class of TImagingGraphicForSave; |
| 124 | |
| 125 | {$IFDEF LINK_BITMAP}
|
| 126 | { TImagingGraphic descendant for loading/saving Windows bitmaps.
|
| 127 | VCL/CLX/LCL all have native support for bitmaps so you might |
| 128 | want to disable this class (although you can save bitmaps with |
| 129 | RLE compression with this class).} |
| 130 | TImagingBitmap = class(TImagingGraphicForSave)
|
| 131 | protected
|
| 132 | FUseRLE: Boolean; |
| 133 | public
|
| 134 | constructor Create; override; |
| 135 | procedure SaveToStream(Stream: TStream); override; |
| 136 | class function GetFileFormat: TImageFileFormat; override; |
| 137 | { See ImagingBitmapRLE option for details.}
|
| 138 | property UseRLE: Boolean read FUseRLE write FUseRLE; |
| 139 | end;
|
| 140 | {$ENDIF}
|
| 141 | |
| 142 | {$IFDEF LINK_JPEG}
|
| 143 | { TImagingGraphic descendant for loading/saving JPEG images.}
|
| 144 | TImagingJpeg = class(TImagingGraphicForSave)
|
| 145 | protected
|
| 146 | FQuality: LongInt; |
| 147 | FProgressive: Boolean; |
| 148 | public
|
| 149 | constructor Create; override; |
| 150 | procedure SaveToStream(Stream: TStream); override; |
| 151 | class function GetFileFormat: TImageFileFormat; override; |
| 152 | {$IFDEF COMPONENT_SET_LCL}
|
| 153 | function GetDefaultMimeType: string; override; |
| 154 | {$ENDIF}
|
| 155 | { See ImagingJpegQuality option for details.}
|
| 156 | property Quality: LongInt read FQuality write FQuality; |
| 157 | { See ImagingJpegProgressive option for details.}
|
| 158 | property Progressive: Boolean read FProgressive write FProgressive; |
| 159 | end;
|
| 160 | {$ENDIF}
|
| 161 | |
| 162 | {$IFDEF LINK_PNG}
|
| 163 | { TImagingGraphic descendant for loading/saving PNG images.}
|
| 164 | TImagingPNG = class(TImagingGraphicForSave)
|
| 165 | protected
|
| 166 | FPreFilter: LongInt; |
| 167 | FCompressLevel: LongInt; |
| 168 | public
|
| 169 | constructor Create; override; |
| 170 | procedure SaveToStream(Stream: TStream); override; |
| 171 | class function GetFileFormat: TImageFileFormat; override; |
| 172 | { See ImagingPNGPreFilter option for details.}
|
| 173 | property PreFilter: LongInt read FPreFilter write FPreFilter; |
| 174 | { See ImagingPNGCompressLevel option for details.}
|
| 175 | property CompressLevel: LongInt read FCompressLevel write FCompressLevel; |
| 176 | end;
|
| 177 | {$ENDIF}
|
| 178 | |
| 179 | {$IFDEF LINK_GIF}
|
| 180 | { TImagingGraphic descendant for loading/saving GIF images.}
|
| 181 | TImagingGIF = class(TImagingGraphicForSave)
|
| 182 | public
|
| 183 | class function GetFileFormat: TImageFileFormat; override; |
| 184 | end;
|
| 185 | {$ENDIF}
|
| 186 | |
| 187 | {$IFDEF LINK_TARGA}
|
| 188 | { TImagingGraphic descendant for loading/saving Targa images.}
|
| 189 | TImagingTarga = class(TImagingGraphicForSave)
|
| 190 | protected
|
| 191 | FUseRLE: Boolean; |
| 192 | public
|
| 193 | constructor Create; override; |
| 194 | procedure SaveToStream(Stream: TStream); override; |
| 195 | class function GetFileFormat: TImageFileFormat; override; |
| 196 | { See ImagingTargaRLE option for details.}
|
| 197 | property UseRLE: Boolean read FUseRLE write FUseRLE; |
| 198 | end;
|
| 199 | {$ENDIF}
|
| 200 | |
| 201 | {$IFDEF LINK_DDS}
|
| 202 | { Compresssion type used when saving DDS files by TImagingDds.}
|
| 203 | TDDSCompresion = (dcNone, dcDXT1, dcDXT3, dcDXT5); |
| 204 | |
| 205 | { TImagingGraphic descendant for loading/saving DDS images.}
|
| 206 | TImagingDDS = class(TImagingGraphicForSave)
|
| 207 | protected
|
| 208 | FCompression: TDDSCompresion; |
| 209 | public
|
| 210 | constructor Create; override; |
| 211 | procedure SaveToStream(Stream: TStream); override; |
| 212 | class function GetFileFormat: TImageFileFormat; override; |
| 213 | { You can choose compression type used when saving DDS file.
|
| 214 | dcNone means that file will be saved in the current bitmaps pixel format.} |
| 215 | property Compression: TDDSCompresion read FCompression write FCompression; |
| 216 | end;
|
| 217 | {$ENDIF}
|
| 218 | |
| 219 | {$IFDEF LINK_MNG}
|
| 220 | { TImagingGraphic descendant for loading/saving MNG images.}
|
| 221 | TImagingMNG = class(TImagingGraphicForSave)
|
| 222 | protected
|
| 223 | FLossyCompression: Boolean; |
| 224 | FLossyAlpha: Boolean; |
| 225 | FPreFilter: LongInt; |
| 226 | FCompressLevel: LongInt; |
| 227 | FQuality: LongInt; |
| 228 | FProgressive: Boolean; |
| 229 | public
|
| 230 | constructor Create; override; |
| 231 | procedure SaveToStream(Stream: TStream); override; |
| 232 | class function GetFileFormat: TImageFileFormat; override; |
| 233 | {$IFDEF COMPONENT_SET_LCL}
|
| 234 | function GetDefaultMimeType: string; override; |
| 235 | {$ENDIF}
|
| 236 | { See ImagingMNGLossyCompression option for details.}
|
| 237 | property LossyCompression: Boolean read FLossyCompression write FLossyCompression; |
| 238 | { See ImagingMNGLossyAlpha option for details.}
|
| 239 | property LossyAlpha: Boolean read FLossyAlpha write FLossyAlpha; |
| 240 | { See ImagingMNGPreFilter option for details.}
|
| 241 | property PreFilter: LongInt read FPreFilter write FPreFilter; |
| 242 | { See ImagingMNGCompressLevel option for details.}
|
| 243 | property CompressLevel: LongInt read FCompressLevel write FCompressLevel; |
| 244 | { See ImagingMNGQuality option for details.}
|
| 245 | property Quality: LongInt read FQuality write FQuality; |
| 246 | { See ImagingMNGProgressive option for details.}
|
| 247 | property Progressive: Boolean read FProgressive write FProgressive; |
| 248 | end;
|
| 249 | {$ENDIF}
|
| 250 | |
| 251 | {$IFDEF LINK_JNG}
|
| 252 | { TImagingGraphic descendant for loading/saving JNG images.}
|
| 253 | TImagingJNG = class(TImagingGraphicForSave)
|
| 254 | protected
|
| 255 | FLossyAlpha: Boolean; |
| 256 | FAlphaPreFilter: LongInt; |
| 257 | FAlphaCompressLevel: LongInt; |
| 258 | FQuality: LongInt; |
| 259 | FProgressive: Boolean; |
| 260 | public
|
| 261 | constructor Create; override; |
| 262 | procedure SaveToStream(Stream: TStream); override; |
| 263 | class function GetFileFormat: TImageFileFormat; override; |
| 264 | { See ImagingJNGLossyAlpha option for details.}
|
| 265 | property LossyAlpha: Boolean read FLossyAlpha write FLossyAlpha; |
| 266 | { See ImagingJNGPreFilter option for details.}
|
| 267 | property AlphaPreFilter: LongInt read FAlphaPreFilter write FAlphaPreFilter; |
| 268 | { See ImagingJNGCompressLevel option for details.}
|
| 269 | property AlphaCompressLevel: LongInt read FAlphaCompressLevel write FAlphaCompressLevel; |
| 270 | { See ImagingJNGQuality option for details.}
|
| 271 | property Quality: LongInt read FQuality write FQuality; |
| 272 | { See ImagingJNGProgressive option for details.}
|
| 273 | property Progressive: Boolean read FProgressive write FProgressive; |
| 274 | end;
|
| 275 | {$ENDIF}
|
| 276 | |
| 277 | { Returns bitmap pixel format with the closest match with given data format.}
|
| 278 | function DataFormatToPixelFormat(Format: TImageFormat): TPixelFormat;
|
| 279 | { Returns data format with closest match with given bitmap pixel format.}
|
| 280 | function PixelFormatToDataFormat(Format: TPixelFormat): TImageFormat;
|
| 281 | |
| 282 | { Converts TImageData structure to VCL/CLX/LCL bitmap.}
|
| 283 | procedure ConvertDataToBitmap(const Data: TImageData; Bitmap: TBitmap); |
| 284 | { Converts VCL/CLX/LCL bitmap to TImageData structure.}
|
| 285 | procedure ConvertBitmapToData(Bitmap: TBitmap; var Data: TImageData); |
| 286 | { Converts TBaseImage instance to VCL/CLX/LCL bitmap.}
|
| 287 | procedure ConvertImageToBitmap(Image: TBaseImage; Bitmap: TBitmap);
|
| 288 | { Converts VCL/CLX/LCL bitmap to TBaseImage. Image must exist before
|
| 289 | procedure is called. It overwrites its current image data. |
| 290 | When Image is TMultiImage only the current image level is overwritten.} |
| 291 | procedure ConvertBitmapToImage(Bitmap: TBitmap; Image: TBaseImage);
|
| 292 | |
| 293 | { Displays image stored in TImageData structure onto TCanvas. This procedure
|
| 294 | draws image without converting from Imaging format to TBitmap. |
| 295 | Only [ifA8R8G8B8, ifX8R8G8B8] image formats are supported. Use this |
| 296 | when you want displaying images that change frequently (because converting to |
| 297 | TBitmap by ConvertImageDataToBitmap is generally slow). Dest and Src |
| 298 | rectangles represent coordinates in the form (X1, Y1, X2, Y2).} |
| 299 | procedure DisplayImageData(DstCanvas: TCanvas; const DstRect: TRect; const ImageData: TImageData; const SrcRect: TRect); |
| 300 | { Displays image onto TCanvas at position [DstX, DstY]. This procedure
|
| 301 | draws image without converting from Imaging format to TBitmap. |
| 302 | Only [ifA8R8G8B8, ifX8R8G8B8] image formats are supported. Use this |
| 303 | when you want displaying images that change frequently (because converting to |
| 304 | TBitmap by ConvertImageDataToBitmap is generally slow).} |
| 305 | procedure DisplayImage(DstCanvas: TCanvas; DstX, DstY: LongInt; Image: TBaseImage); overload; |
| 306 | { Displays image onto TCanvas to rectangle DstRect. This procedure
|
| 307 | draws image without converting from Imaging format to TBitmap. |
| 308 | Only [ifA8R8G8B8, ifX8R8G8B8] image formats are supported. Use this |
| 309 | when you want displaying images that change frequently (because converting to |
| 310 | TBitmap by ConvertImageDataToBitmap is generally slow).} |
| 311 | procedure DisplayImage(DstCanvas: TCanvas; const DstRect: TRect; Image: TBaseImage); overload; |
| 312 | { Displays part of the image specified by SrcRect onto TCanvas to rectangle DstRect.
|
| 313 | This procedure draws image without converting from Imaging format to TBitmap. |
| 314 | Only [ifA8R8G8B8, ifX8R8G8B8] image formats are supported. Use this |
| 315 | when you want displaying images that change frequently (because converting to |
| 316 | TBitmap by ConvertImageDataToBitmap is generally slow).} |
| 317 | procedure DisplayImage(DstCanvas: TCanvas; const DstRect: TRect; Image: TBaseImage; const SrcRect: TRect); overload; |
| 318 | |
| 319 | {$IFDEF MSWINDOWS}
|
| 320 | { Displays image stored in TImageData structure onto Windows device context.
|
| 321 | Behaviour is the same as of DisplayImageData.} |
| 322 | procedure DisplayImageDataOnDC(DC: HDC; const DstRect: TRect; const ImageData: TImageData; const SrcRect: TRect); |
| 323 | {$ENDIF}
|
| 324 | |
| 325 | implementation
|
| 326 | |
| 327 | uses
|
| 328 | {$IF Defined(UNIX) and Defined(COMPONENT_SET_LCL)}
|
| 329 | {$IFDEF LCLGTK2}
|
| 330 | GLib2, GDK2, GTK2, GTKDef, GTKProc, |
| 331 | {$ELSE}
|
| 332 | GDK, GTK, GTKDef, GTKProc, |
| 333 | {$ENDIF}
|
| 334 | {$IFEND}
|
| 335 | {$IFDEF LINK_BITMAP}
|
| 336 | ImagingBitmap, |
| 337 | {$ENDIF}
|
| 338 | {$IFDEF LINK_JPEG}
|
| 339 | ImagingJpeg, |
| 340 | {$ENDIF}
|
| 341 | {$IFDEF LINK_GIF}
|
| 342 | ImagingGif, |
| 343 | {$ENDIF}
|
| 344 | {$IFDEF LINK_TARGA}
|
| 345 | ImagingTarga, |
| 346 | {$ENDIF}
|
| 347 | {$IFDEF LINK_DDS}
|
| 348 | ImagingDds, |
| 349 | {$ENDIF}
|
| 350 | {$IF Defined(LINK_PNG) or Defined(LINK_MNG) or Defined(LINK_JNG)}
|
| 351 | ImagingNetworkGraphics, |
| 352 | {$IFEND}
|
| 353 | ImagingUtility; |
| 354 | |
| 355 | resourcestring
|
| 356 | SBadFormatDataToBitmap = 'Cannot find compatible bitmap format for image %s';
|
| 357 | SBadFormatBitmapToData = 'Cannot find compatible data format for bitmap %p';
|
| 358 | SBadFormatDisplay = 'Unsupported image format passed';
|
| 359 | SImagingGraphicName = 'Imaging Graphic AllInOne';
|
| 360 | |
| 361 | { Registers types to VCL/CLX/LCL.}
|
| 362 | procedure RegisterTypes;
|
| 363 | var
|
| 364 | I: LongInt; |
| 365 | |
| 366 | procedure RegisterFileFormatAllInOne(Format: TImageFileFormat);
|
| 367 | var
|
| 368 | I: LongInt; |
| 369 | begin
|
| 370 | for I := 0 to Format.Extensions.Count - 1 do |
| 371 | TPicture.RegisterFileFormat(Format.Extensions[I], SImagingGraphicName, |
| 372 | TImagingGraphic); |
| 373 | end;
|
| 374 | |
| 375 | procedure RegisterFileFormat(AClass: TImagingGraphicForSaveClass);
|
| 376 | var
|
| 377 | I: LongInt; |
| 378 | begin
|
| 379 | for I := 0 to AClass.GetFileFormat.Extensions.Count - 1 do |
| 380 | TPicture.RegisterFileFormat(AClass.GetFileFormat.Extensions[I], |
| 381 | AClass.GetFileFormat.Name, AClass); |
| 382 | end;
|
| 383 | |
| 384 | begin
|
| 385 | for I := Imaging.GetFileFormatCount - 1 downto 0 do |
| 386 | RegisterFileFormatAllInOne(Imaging.GetFileFormatAtIndex(I)); |
| 387 | {$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingGraphic);{$ENDIF} |
| 388 | |
| 389 | {$IFDEF LINK_TARGA}
|
| 390 | RegisterFileFormat(TImagingTarga); |
| 391 | {$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingTarga);{$ENDIF} |
| 392 | {$ENDIF}
|
| 393 | {$IFDEF LINK_DDS}
|
| 394 | RegisterFileFormat(TImagingDDS); |
| 395 | {$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingDDS);{$ENDIF} |
| 396 | {$ENDIF}
|
| 397 | {$IFDEF LINK_JNG}
|
| 398 | RegisterFileFormat(TImagingJNG); |
| 399 | {$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingJNG);{$ENDIF} |
| 400 | {$ENDIF}
|
| 401 | {$IFDEF LINK_MNG}
|
| 402 | RegisterFileFormat(TImagingMNG); |
| 403 | {$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingMNG);{$ENDIF} |
| 404 | {$ENDIF}
|
| 405 | {$IFDEF LINK_GIF}
|
| 406 | RegisterFileFormat(TImagingGIF); |
| 407 | {$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingGIF);{$ENDIF} |
| 408 | {$ENDIF}
|
| 409 | {$IFDEF LINK_PNG}
|
| 410 | {$IFDEF COMPONENT_SET_LCL}
|
| 411 | // Unregister Lazarus? default PNG loader which crashes on some PNG files
|
| 412 | TPicture.UnregisterGraphicClass(TPortableNetworkGraphic); |
| 413 | {$ENDIF}
|
| 414 | RegisterFileFormat(TImagingPNG); |
| 415 | {$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingPNG);{$ENDIF} |
| 416 | {$ENDIF}
|
| 417 | {$IFDEF LINK_JPEG}
|
| 418 | RegisterFileFormat(TImagingJpeg); |
| 419 | {$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingJpeg);{$ENDIF} |
| 420 | {$ENDIF}
|
| 421 | {$IFDEF LINK_BITMAP}
|
| 422 | RegisterFileFormat(TImagingBitmap); |
| 423 | {$IFNDEF COMPONENT_SET_CLX}Classes.RegisterClass(TImagingBitmap);{$ENDIF} |
| 424 | {$ENDIF}
|
| 425 | end;
|
| 426 | |
| 427 | { Unregisters types from VCL/CLX/LCL.}
|
| 428 | procedure UnRegisterTypes;
|
| 429 | begin
|
| 430 | {$IFDEF LINK_BITMAP}
|
| 431 | TPicture.UnregisterGraphicClass(TImagingBitmap); |
| 432 | {$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingBitmap);{$ENDIF} |
| 433 | {$ENDIF}
|
| 434 | {$IFDEF LINK_JPEG}
|
| 435 | TPicture.UnregisterGraphicClass(TImagingJpeg); |
| 436 | {$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingJpeg);{$ENDIF} |
| 437 | {$ENDIF}
|
| 438 | {$IFDEF LINK_PNG}
|
| 439 | TPicture.UnregisterGraphicClass(TImagingPNG); |
| 440 | {$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingPNG);{$ENDIF} |
| 441 | {$ENDIF}
|
| 442 | {$IFDEF LINK_GIF}
|
| 443 | TPicture.UnregisterGraphicClass(TImagingGIF); |
| 444 | {$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingGIF);{$ENDIF} |
| 445 | {$ENDIF}
|
| 446 | {$IFDEF LINK_TARGA}
|
| 447 | TPicture.UnregisterGraphicClass(TImagingTarga); |
| 448 | {$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingTarga);{$ENDIF} |
| 449 | {$ENDIF}
|
| 450 | {$IFDEF LINK_DDS}
|
| 451 | TPicture.UnregisterGraphicClass(TImagingDDS); |
| 452 | {$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingDDS);{$ENDIF} |
| 453 | {$ENDIF}
|
| 454 | TPicture.UnregisterGraphicClass(TImagingGraphic); |
| 455 | {$IFNDEF COMPONENT_SET_CLX}Classes.UnRegisterClass(TImagingGraphic);{$ENDIF} |
| 456 | end;
|
| 457 | |
| 458 | function DataFormatToPixelFormat(Format: TImageFormat): TPixelFormat;
|
| 459 | begin
|
| 460 | case Format of |
| 461 | {$IFNDEF COMPONENT_SET_LCL}
|
| 462 | ifIndex8: Result := pf8bit; |
| 463 | {$ENDIF}
|
| 464 | {$IF (not Defined(COMPONENT_SET_CLX)) and (not Defined(COMPONENT_SET_LCL))}
|
| 465 | ifR5G6B5: Result := pf16bit; |
| 466 | ifR8G8B8: Result := pf24bit; |
| 467 | {$IFEND}
|
| 468 | ifA8R8G8B8, |
| 469 | ifX8R8G8B8: Result := pf32bit; |
| 470 | else
|
| 471 | Result := pfCustom; |
| 472 | end;
|
| 473 | end;
|
| 474 | |
| 475 | function PixelFormatToDataFormat(Format: TPixelFormat): TImageFormat;
|
| 476 | begin
|
| 477 | case Format of |
| 478 | pf8bit: Result := ifIndex8; |
| 479 | {$IFNDEF COMPONENT_SET_CLX}
|
| 480 | pf15bit: Result := ifA1R5G5B5; |
| 481 | pf16bit: Result := ifR5G6B5; |
| 482 | pf24bit: Result := ifR8G8B8; |
| 483 | {$ENDIF}
|
| 484 | pf32bit: Result := ifA8R8G8B8; |
| 485 | else
|
| 486 | Result := ifUnknown; |
| 487 | end;
|
| 488 | end;
|
| 489 | |
| 490 | procedure ConvertDataToBitmap(const Data: TImageData; Bitmap: TBitmap); |
| 491 | var
|
| 492 | I, LineBytes: LongInt; |
| 493 | PF: TPixelFormat; |
| 494 | Info: TImageFormatInfo; |
| 495 | WorkData: TImageData; |
| 496 | {$IFDEF COMPONENT_SET_VCL}
|
| 497 | LogPalette: TMaxLogPalette; |
| 498 | {$ENDIF}
|
| 499 | {$IFDEF COMPONENT_SET_CLX}
|
| 500 | ColorTable: PPalette32; |
| 501 | {$ENDIF}
|
| 502 | {$IFDEF COMPONENT_SET_LCL}
|
| 503 | RawImage: TRawImage; |
| 504 | ImgHandle, ImgMaskHandle: HBitmap; |
| 505 | {$ENDIF}
|
| 506 | begin
|
| 507 | PF := DataFormatToPixelFormat(Data.Format); |
| 508 | GetImageFormatInfo(Data.Format, Info); |
| 509 | if PF = pfCustom then |
| 510 | begin
|
| 511 | // Convert from formats not supported by Graphics unit
|
| 512 | Imaging.InitImage(WorkData); |
| 513 | Imaging.CloneImage(Data, WorkData); |
| 514 | if Info.IsFloatingPoint or Info.HasAlphaChannel or Info.IsSpecial then |
| 515 | Imaging.ConvertImage(WorkData, ifA8R8G8B8) |
| 516 | else
|
| 517 | {$IFNDEF COMPONENT_SET_LCL}
|
| 518 | if Info.IsIndexed or Info.HasGrayChannel then |
| 519 | Imaging.ConvertImage(WorkData, ifIndex8) |
| 520 | else
|
| 521 | {$ENDIF}
|
| 522 | {$IF (not Defined(COMPONENT_SET_CLX)) and (not Defined(COMPONENT_SET_LCL))}
|
| 523 | if Info.UsePixelFormat then |
| 524 | Imaging.ConvertImage(WorkData, ifR5G6B5) |
| 525 | else
|
| 526 | Imaging.ConvertImage(WorkData, ifR8G8B8); |
| 527 | {$ELSE}
|
| 528 | Imaging.ConvertImage(WorkData, ifA8R8G8B8); |
| 529 | {$IFEND}
|
| 530 | |
| 531 | PF := DataFormatToPixelFormat(WorkData.Format); |
| 532 | GetImageFormatInfo(WorkData.Format, Info); |
| 533 | end
|
| 534 | else
|
| 535 | WorkData := Data; |
| 536 | |
| 537 | if PF = pfCustom then |
| 538 | RaiseImaging(SBadFormatDataToBitmap, [ImageToStr(WorkData)]); |
| 539 | |
| 540 | LineBytes := WorkData.Width * Info.BytesPerPixel; |
| 541 | |
| 542 | {$IFDEF COMPONENT_SET_VCL}
|
| 543 | Bitmap.Width := WorkData.Width; |
| 544 | Bitmap.Height := WorkData.Height; |
| 545 | Bitmap.PixelFormat := PF; |
| 546 | |
| 547 | if (PF = pf8bit) and (WorkData.Palette <> nil) then |
| 548 | begin
|
| 549 | // Copy palette, this must be done before copying bits
|
| 550 | FillChar(LogPalette, SizeOf(LogPalette), 0);
|
| 551 | LogPalette.palVersion := $300;
|
| 552 | LogPalette.palNumEntries := Info.PaletteEntries; |
| 553 | for I := 0 to Info.PaletteEntries - 1 do |
| 554 | with LogPalette do |
| 555 | begin
|
| 556 | palPalEntry[I].peRed := WorkData.Palette[I].R; |
| 557 | palPalEntry[I].peGreen := WorkData.Palette[I].G; |
| 558 | palPalEntry[I].peBlue := WorkData.Palette[I].B; |
| 559 | end;
|
| 560 | Bitmap.Palette := CreatePalette(PLogPalette(@LogPalette)^); |
| 561 | end;
|
| 562 | // Copy scanlines
|
| 563 | for I := 0 to WorkData.Height - 1 do |
| 564 | Move(PByteArray(WorkData.Bits)[I * LineBytes], Bitmap.Scanline[I]^, LineBytes); |
| 565 | {$ENDIF}
|
| 566 | {$IFDEF COMPONENT_SET_CLX}
|
| 567 | Bitmap.Width := WorkData.Width; |
| 568 | Bitmap.Height := WorkData.Height; |
| 569 | Bitmap.PixelFormat := PF; |
| 570 | |
| 571 | if (PF = pf8bit) and (WorkData.Palette <> nil) then |
| 572 | begin
|
| 573 | // Copy palette
|
| 574 | ColorTable := Bitmap.ColorTable; |
| 575 | for I := 0 to Info.PaletteEntries - 1 do |
| 576 | with ColorTable[I] do |
| 577 | begin
|
| 578 | R := WorkData.Palette[I].R; |
| 579 | G := WorkData.Palette[I].G; |
| 580 | B := WorkData.Palette[I].B; |
| 581 | end;
|
| 582 | end;
|
| 583 | // Copy scanlines
|
| 584 | for I := 0 to WorkData.Height - 1 do |
| 585 | Move(PByteArray(WorkData.Bits)[I * LineBytes], Bitmap.Scanline[I]^, LineBytes); |
| 586 | {$ENDIF}
|
| 587 | {$IFDEF COMPONENT_SET_LCL}
|
| 588 | // Create 32bit raw image from image data
|
| 589 | FillChar(RawImage, SizeOf(RawImage), 0);
|
| 590 | with RawImage.Description do |
| 591 | begin
|
| 592 | Width := WorkData.Width; |
| 593 | Height := WorkData.Height; |
| 594 | BitsPerPixel := Info.BytesPerPixel * 8;
|
| 595 | Format := ricfRGBA; |
| 596 | LineEnd := rileByteBoundary; |
| 597 | BitOrder := riboBitsInOrder; |
| 598 | ByteOrder := riboLSBFirst; |
| 599 | LineOrder := riloTopToBottom; |
| 600 | AlphaPrec := 8;
|
| 601 | RedPrec := 8;
|
| 602 | GreenPrec := 8;
|
| 603 | BluePrec := 8;
|
| 604 | AlphaShift := 24;
|
| 605 | RedShift := 16;
|
| 606 | GreenShift := 8;
|
| 607 | BlueShift := 0;
|
| 608 | Depth := 24;
|
| 609 | end;
|
| 610 | RawImage.Data := WorkData.Bits; |
| 611 | RawImage.DataSize := WorkData.Size; |
| 612 | |
| 613 | // Create bitmap from raw image
|
| 614 | { If you get complitation error here upgrade to Lazarus 0.9.24+ }
|
| 615 | if RawImage_CreateBitmaps(RawImage, ImgHandle, ImgMaskHandle, False) then |
| 616 | begin
|
| 617 | Bitmap.Handle := ImgHandle; |
| 618 | Bitmap.MaskHandle := ImgMaskHandle; |
| 619 | end;
|
| 620 | {$ENDIF}
|
| 621 | if WorkData.Bits <> Data.Bits then |
| 622 | Imaging.FreeImage(WorkData); |
| 623 | end;
|
| 624 | |
| 625 | procedure ConvertBitmapToData(Bitmap: TBitmap; var Data: TImageData); |
| 626 | var
|
| 627 | I, LineBytes: LongInt; |
| 628 | Format: TImageFormat; |
| 629 | Info: TImageFormatInfo; |
| 630 | {$IFDEF COMPONENT_SET_VCL}
|
| 631 | Colors: Word; |
| 632 | LogPalette: TMaxLogPalette; |
| 633 | {$ENDIF}
|
| 634 | {$IFDEF COMPONENT_SET_CLX}
|
| 635 | ColorTable: PPalette32; |
| 636 | {$ENDIF}
|
| 637 | {$IFDEF COMPONENT_SET_LCL}
|
| 638 | RawImage: TRawImage; |
| 639 | LineLazBytes: LongInt; |
| 640 | {$ENDIF}
|
| 641 | begin
|
| 642 | {$IFDEF COMPONENT_SET_LCL}
|
| 643 | // In the current Lazarus 0.9.10 Bitmap.PixelFormat property is useless.
|
| 644 | // We cannot change bitmap's format by changing it (it will just release
|
| 645 | // old image but not convert it to new format) nor we can determine bitmaps's
|
| 646 | // current format (it is usually set to pfDevice). So bitmap's format is obtained
|
| 647 | // trough RawImage api and cannot be changed to mirror some Imaging format
|
| 648 | // (so formats with no coresponding Imaging format cannot be saved now).
|
| 649 | |
| 650 | { If you get complitation error here upgrade to Lazarus 0.9.24+ }
|
| 651 | if RawImage_DescriptionFromBitmap(Bitmap.Handle, RawImage.Description) then |
| 652 | case RawImage.Description.BitsPerPixel of |
| 653 | 8: Format := ifIndex8;
|
| 654 | 16:
|
| 655 | if RawImage.Description.Depth = 15 then |
| 656 | Format := ifA1R5G5B5 |
| 657 | else
|
| 658 | Format := ifR5G6B5; |
| 659 | 24: Format := ifR8G8B8;
|
| 660 | 32: Format := ifA8R8G8B8;
|
| 661 | 48: Format := ifR16G16B16;
|
| 662 | 64: Format := ifA16R16G16B16;
|
| 663 | else
|
| 664 | Format := ifUnknown; |
| 665 | end;
|
| 666 | {$ELSE}
|
| 667 | Format := PixelFormatToDataFormat(Bitmap.PixelFormat); |
| 668 | if Format = ifUnknown then |
| 669 | begin
|
| 670 | // Convert from formats not supported by Imaging (1/4 bit)
|
| 671 | if Bitmap.PixelFormat < pf8bit then |
| 672 | Bitmap.PixelFormat := pf8bit |
| 673 | else
|
| 674 | Bitmap.PixelFormat := pf32bit; |
| 675 | Format := PixelFormatToDataFormat(Bitmap.PixelFormat); |
| 676 | end;
|
| 677 | {$ENDIF}
|
| 678 | |
| 679 | if Format = ifUnknown then |
| 680 | RaiseImaging(SBadFormatBitmapToData, []); |
| 681 | |
| 682 | Imaging.NewImage(Bitmap.Width, Bitmap.Height, Format, Data); |
| 683 | GetImageFormatInfo(Data.Format, Info); |
| 684 | LineBytes := Data.Width * Info.BytesPerPixel; |
| 685 | |
| 686 | {$IFDEF COMPONENT_SET_VCL}
|
| 687 | if (Format = ifIndex8) and (GetObject(Bitmap.Palette, SizeOf(Colors), |
| 688 | @Colors) <> 0) then |
| 689 | begin
|
| 690 | // Copy palette
|
| 691 | GetPaletteEntries(Bitmap.Palette, 0, Colors, LogPalette.palPalEntry);
|
| 692 | if Colors > Info.PaletteEntries then |
| 693 | Colors := Info.PaletteEntries; |
| 694 | for I := 0 to Colors - 1 do |
| 695 | with LogPalette do |
| 696 | begin
|
| 697 | Data.Palette[I].A := $FF;
|
| 698 | Data.Palette[I].R := palPalEntry[I].peRed; |
| 699 | Data.Palette[I].G := palPalEntry[I].peGreen; |
| 700 | Data.Palette[I].B := palPalEntry[I].peBlue; |
| 701 | end;
|
| 702 | end;
|
| 703 | // Copy scanlines
|
| 704 | for I := 0 to Data.Height - 1 do |
| 705 | Move(Bitmap.ScanLine[I]^, PByteArray(Data.Bits)[I * LineBytes], LineBytes); |
| 706 | {$ENDIF}
|
| 707 | {$IFDEF COMPONENT_SET_CLX}
|
| 708 | if Format = ifIndex8 then |
| 709 | begin
|
| 710 | // Copy palette
|
| 711 | ColorTable := Bitmap.ColorTable; |
| 712 | for I := 0 to Info.PaletteEntries - 1 do |
| 713 | with ColorTable[I] do |
| 714 | begin
|
| 715 | Data.Palette[I].A := $FF;
|
| 716 | Data.Palette[I].R := R; |
| 717 | Data.Palette[I].G := G; |
| 718 | Data.Palette[I].B := B; |
| 719 | end;
|
| 720 | end;
|
| 721 | // Copy scanlines
|
| 722 | for I := 0 to Data.Height - 1 do |
| 723 | Move(Bitmap.ScanLine[I]^, PByteArray(Data.Bits)[I * LineBytes], LineBytes); |
| 724 | {$ENDIF}
|
| 725 | {$IFDEF COMPONENT_SET_LCL}
|
| 726 | // Get raw image from bitmap (mask handle must be 0 or expect violations)
|
| 727 | { If you get complitation error here upgrade to Lazarus 0.9.24+ }
|
| 728 | if RawImage_FromBitmap(RawImage, Bitmap.Handle, 0, Classes.Rect(0, 0, Data.Width, Data.Height)) then |
| 729 | begin
|
| 730 | LineLazBytes := GetBytesPerLine(Data.Width, RawImage.Description.BitsPerPixel, |
| 731 | RawImage.Description.LineEnd); |
| 732 | // Copy scanlines
|
| 733 | for I := 0 to Data.Height - 1 do |
| 734 | Move(PByteArray(RawImage.Data)[I * LineLazBytes], |
| 735 | PByteArray(Data.Bits)[I * LineBytes], LineBytes); |
| 736 | { If you get complitation error here upgrade to Lazarus 0.9.24+ }
|
| 737 | RawImage.FreeData; |
| 738 | end;
|
| 739 | {$ENDIF}
|
| 740 | end;
|
| 741 | |
| 742 | procedure ConvertImageToBitmap(Image: TBaseImage; Bitmap: TBitmap);
|
| 743 | begin
|
| 744 | ConvertDataToBitmap(Image.ImageDataPointer^, Bitmap); |
| 745 | end;
|
| 746 | |
| 747 | procedure ConvertBitmapToImage(Bitmap: TBitmap; Image: TBaseImage);
|
| 748 | begin
|
| 749 | ConvertBitmapToData(Bitmap, Image.ImageDataPointer^); |
| 750 | end;
|
| 751 | |
| 752 | {$IFDEF MSWINDOWS}
|
| 753 | procedure DisplayImageDataOnDC(DC: HDC; const DstRect: TRect; const ImageData: TImageData; const SrcRect: TRect); |
| 754 | var
|
| 755 | OldMode: Integer; |
| 756 | BitmapInfo: Windows.TBitmapInfo; |
| 757 | begin
|
| 758 | if TestImage(ImageData) then |
| 759 | begin
|
| 760 | Assert(ImageData.Format in [ifA8R8G8B8, ifX8R8G8B8], SBadFormatDisplay);
|
| 761 | OldMode := Windows.SetStretchBltMode(DC, COLORONCOLOR); |
| 762 | |
| 763 | FillChar(BitmapInfo, SizeOf(BitmapInfo), 0);
|
| 764 | with BitmapInfo.bmiHeader do |
| 765 | begin
|
| 766 | biSize := SizeOf(TBitmapInfoHeader); |
| 767 | biPlanes := 1;
|
| 768 | biBitCount := 32;
|
| 769 | biCompression := BI_RGB; |
| 770 | biWidth := ImageData.Width; |
| 771 | biHeight := -ImageData.Height; |
| 772 | biSizeImage := ImageData.Size; |
| 773 | biXPelsPerMeter := 0;
|
| 774 | biYPelsPerMeter := 0;
|
| 775 | biClrUsed := 0;
|
| 776 | biClrImportant := 0;
|
| 777 | end;
|
| 778 | |
| 779 | try
|
| 780 | with SrcRect, ImageData do |
| 781 | Windows.StretchDIBits(DC, DstRect.Left, DstRect.Top, |
| 782 | DstRect.Right - DstRect.Left, DstRect.Bottom - DstRect.Top, Left, |
| 783 | Top, Right - Left, Bottom - Top, Bits, BitmapInfo, DIB_RGB_COLORS, SRCCOPY); |
| 784 | finally
|
| 785 | Windows.SetStretchBltMode(DC, OldMode); |
| 786 | end;
|
| 787 | end;
|
| 788 | end;
|
| 789 | {$ENDIF}
|
| 790 | |
| 791 | procedure DisplayImageData(DstCanvas: TCanvas; const DstRect: TRect; const ImageData: TImageData; const SrcRect: TRect); |
| 792 | {$IF Defined(MSWINDOWS) and not Defined(COMPONENT_SET_CLX)}
|
| 793 | begin
|
| 794 | DisplayImageDataOnDC(DstCanvas.Handle, DstRect, ImageData, SrcRect); |
| 795 | end;
|
| 796 | {$ELSEIF Defined(COMPONENT_SET_CLX)}
|
| 797 | var
|
| 798 | Bitmap: TBitmap; |
| 799 | //Handle: LongWord;
|
| 800 | begin
|
| 801 | (*
|
| 802 | // It would be nice if this worked: |
| 803 | DstCanvas.Start; |
| 804 | Handle := QPainter_handle(DstCanvas.Handle); |
| 805 | {$IFDEF MSWINDOWS}
|
| 806 | DisplayImageDataOnDC(Handle, DstRect, ImageData, SrcRect); |
| 807 | {$ELSE}
|
| 808 | DisplayImageDataOnX(Handle, DstRect, ImageData, SrcRect); |
| 809 | {$ENDIF}
|
| 810 | DstCanvas.Stop; |
| 811 | *) |
| 812 | Bitmap := TBitmap.Create; |
| 813 | try
|
| 814 | ConvertDataToBitmap(ImageData, Bitmap); |
| 815 | DstCanvas.CopyRect(DstRect, Bitmap.Canvas, SrcRect); |
| 816 | finally
|
| 817 | Bitmap.Free; |
| 818 | end;
|
| 819 | end;
|
| 820 | {$ELSEIF Defined(UNIX) and Defined(COMPONENT_SET_LCL)}
|
| 821 | |
| 822 | procedure GDKDrawBitmap(Dest: HDC; DstX, DstY: Integer; SrcX, SrcY,
|
| 823 | SrcWidth, SrcHeight: Integer; ImageData: TImageData); |
| 824 | var
|
| 825 | P: TPoint; |
| 826 | begin
|
| 827 | P := TGtkDeviceContext(Dest).Offset; |
| 828 | Inc(DstX, P.X); |
| 829 | Inc(DstY, P.Y); |
| 830 | gdk_draw_rgb_32_image(TGtkDeviceContext(Dest).Drawable, TGtkDeviceContext(Dest).GC, |
| 831 | DstX, DstY, SrcWidth, SrcHeight, GDK_RGB_DITHER_NONE, |
| 832 | @PLongWordArray(ImageData.Bits)[SrcY * ImageData.Width + SrcX], ImageData.Width * 4);
|
| 833 | end;
|
| 834 | |
| 835 | var
|
| 836 | DisplayImage: TImageData; |
| 837 | NewWidth, NewHeight: Integer; |
| 838 | SrcBounds, DstBounds, DstClip: TRect; |
| 839 | begin
|
| 840 | if TestImage(ImageData) then |
| 841 | begin
|
| 842 | Assert(ImageData.Format in [ifA8R8G8B8, ifX8R8G8B8], SBadFormatDisplay);
|
| 843 | InitImage(DisplayImage); |
| 844 | |
| 845 | SrcBounds := RectToBounds(SrcRect); |
| 846 | DstBounds := RectToBounds(DstRect); |
| 847 | WidgetSet.GetClipBox(DstCanvas.Handle, @DstClip); |
| 848 | |
| 849 | ClipStretchBounds(SrcBounds.Left, SrcBounds.Top, SrcBounds.Right, SrcBounds.Bottom, |
| 850 | DstBounds.Left, DstBounds.Top, DstBounds.Right, DstBounds.Bottom, ImageData.Width, |
| 851 | ImageData.Height, DstClip); |
| 852 | |
| 853 | NewWidth := DstBounds.Right; |
| 854 | NewHeight := DstBounds.Bottom; |
| 855 | |
| 856 | if (NewWidth > 0) and (NewHeight > 0) then |
| 857 | begin
|
| 858 | if (SrcBounds.Right = NewWidth) and (SrcBounds.Bottom = NewHeight) then |
| 859 | try
|
| 860 | CloneImage(ImageData, DisplayImage); |
| 861 | // Swap R-B channels for GTK display compatability!
|
| 862 | SwapChannels(DisplayImage, ChannelRed, ChannelBlue); |
| 863 | GDKDrawBitmap(DstCanvas.Handle, DstBounds.Left, DstBounds.Top, |
| 864 | SrcBounds.Left, SrcBounds.Top, NewWidth, NewHeight, DisplayImage); |
| 865 | finally
|
| 866 | FreeImage(DisplayImage); |
| 867 | end
|
| 868 | else
|
| 869 | try
|
| 870 | // Create new image with desired dimensions
|
| 871 | NewImage(NewWidth, NewHeight, ImageData.Format, DisplayImage); |
| 872 | // Stretch pixels from old image to new one TResizeFilter = (rfNearest, rfBilinear, rfBicubic);
|
| 873 | StretchRect(ImageData, SrcBounds.Left, SrcBounds.Top, SrcBounds.Right, |
| 874 | SrcBounds.Bottom, DisplayImage, 0, 0, NewWidth, NewHeight, rfNearest); |
| 875 | // Swap R-B channels for GTK display compatability!
|
| 876 | SwapChannels(DisplayImage, ChannelRed, ChannelBlue); |
| 877 | GDKDrawBitmap(DstCanvas.Handle, DstBounds.Left, DstBounds.Top, 0, 0, |
| 878 | NewWidth, NewHeight, DisplayImage); |
| 879 | finally
|
| 880 | FreeImage(DisplayImage); |
| 881 | end
|
| 882 | end;
|
| 883 | end;
|
| 884 | end;
|
| 885 | {$IFEND}
|
| 886 | |
| 887 | procedure DisplayImage(DstCanvas: TCanvas; DstX, DstY: LongInt; Image: TBaseImage);
|
| 888 | begin
|
| 889 | DisplayImageData(DstCanvas, BoundsToRect(DstX, DstY, Image.Width, Image.Height), |
| 890 | Image.ImageDataPointer^, Image.BoundsRect); |
| 891 | end;
|
| 892 | |
| 893 | procedure DisplayImage(DstCanvas: TCanvas; const DstRect: TRect; Image: TBaseImage); |
| 894 | begin
|
| 895 | DisplayImageData(DstCanvas, DstRect, Image.ImageDataPointer^, Image.BoundsRect); |
| 896 | end;
|
| 897 | |
| 898 | procedure DisplayImage(DstCanvas: TCanvas; const DstRect: TRect; Image: TBaseImage; const SrcRect: TRect); |
| 899 | begin
|
| 900 | DisplayImageData(DstCanvas, DstRect, Image.ImageDataPointer^, SrcRect); |
| 901 | end;
|
| 902 | |
| 903 | |
| 904 | { TImagingGraphic class implementation }
|
| 905 | |
| 906 | procedure TImagingGraphic.LoadFromStream(Stream: TStream);
|
| 907 | begin
|
| 908 | ReadDataFromStream(Stream); |
| 909 | end;
|
| 910 | |
| 911 | procedure TImagingGraphic.ReadDataFromStream(Stream: TStream);
|
| 912 | var
|
| 913 | Image: TSingleImage; |
| 914 | begin
|
| 915 | Image := TSingleImage.Create; |
| 916 | try
|
| 917 | Image.LoadFromStream(Stream); |
| 918 | Assign(Image); |
| 919 | finally
|
| 920 | Image.Free; |
| 921 | end;
|
| 922 | end;
|
| 923 | |
| 924 | procedure TImagingGraphic.AssignTo(Dest: TPersistent);
|
| 925 | var
|
| 926 | Arr: TDynImageDataArray; |
| 927 | begin
|
| 928 | if Dest is TSingleImage then |
| 929 | begin
|
| 930 | AssignToImage(TSingleImage(Dest)) |
| 931 | end
|
| 932 | else if Dest is TMultiImage then |
| 933 | begin
|
| 934 | SetLength(Arr, 1);
|
| 935 | AssignToImageData(Arr[0]);
|
| 936 | TMultiImage(Dest).CreateFromArray(Arr); |
| 937 | Imaging.FreeImagesInArray(Arr); |
| 938 | end
|
| 939 | else
|
| 940 | inherited AssignTo(Dest);
|
| 941 | end;
|
| 942 | |
| 943 | procedure TImagingGraphic.Assign(Source: TPersistent);
|
| 944 | begin
|
| 945 | if Source is TBaseImage then |
| 946 | AssignFromImage(TBaseImage(Source)) |
| 947 | else
|
| 948 | inherited Assign(Source);
|
| 949 | end;
|
| 950 | |
| 951 | procedure TImagingGraphic.AssignFromImage(Image: TBaseImage);
|
| 952 | begin
|
| 953 | if (Image <> nil) and Image.Valid then |
| 954 | AssignFromImageData(Image.ImageDataPointer^); |
| 955 | end;
|
| 956 | |
| 957 | procedure TImagingGraphic.AssignToImage(Image: TBaseImage);
|
| 958 | begin
|
| 959 | if (Image <> nil) and (Image.ImageDataPointer <> nil) then |
| 960 | AssignToImageData(Image.ImageDataPointer^); |
| 961 | end;
|
| 962 | |
| 963 | procedure TImagingGraphic.AssignFromImageData(const ImageData: TImageData); |
| 964 | begin
|
| 965 | if Imaging.TestImage(ImageData) then |
| 966 | ConvertDataToBitmap(ImageData, Self); |
| 967 | end;
|
| 968 | |
| 969 | procedure TImagingGraphic.AssignToImageData(var ImageData: TImageData); |
| 970 | begin
|
| 971 | Imaging.FreeImage(ImageData); |
| 972 | ConvertBitmapToData(Self, ImageData); |
| 973 | end;
|
| 974 | |
| 975 | |
| 976 | { TImagingGraphicForSave class implementation }
|
| 977 | |
| 978 | constructor TImagingGraphicForSave.Create;
|
| 979 | begin
|
| 980 | inherited Create;
|
| 981 | FDefaultFileExt := GetFileFormat.Extensions[0];
|
| 982 | FSavingFormat := ifUnknown; |
| 983 | GetFileFormat.CheckOptionsValidity; |
| 984 | end;
|
| 985 | |
| 986 | procedure TImagingGraphicForSave.WriteDataToStream(Stream: TStream);
|
| 987 | var
|
| 988 | Image: TSingleImage; |
| 989 | begin
|
| 990 | if FDefaultFileExt <> '' then |
| 991 | begin
|
| 992 | Image := TSingleImage.Create; |
| 993 | try
|
| 994 | Image.Assign(Self); |
| 995 | if FSavingFormat <> ifUnknown then |
| 996 | Image.Format := FSavingFormat; |
| 997 | Image.SaveToStream(FDefaultFileExt, Stream); |
| 998 | finally
|
| 999 | Image.Free; |
| 1000 | end;
|
| 1001 | end;
|
| 1002 | end;
|
| 1003 | |
| 1004 | procedure TImagingGraphicForSave.SaveToStream(Stream: TStream);
|
| 1005 | begin
|
| 1006 | WriteDataToStream(Stream); |
| 1007 | end;
|
| 1008 | |
| 1009 | {$IFDEF COMPONENT_SET_LCL}
|
| 1010 | class function TImagingGraphicForSave.GetFileExtensions: string; |
| 1011 | begin
|
| 1012 | Result := StringReplace(GetFileFormat.Extensions.CommaText, ',', ';', [rfReplaceAll]); |
| 1013 | end;
|
| 1014 | |
| 1015 | function TImagingGraphicForSave.GetDefaultMimeType: string; |
| 1016 | begin
|
| 1017 | Result := 'image/' + FDefaultFileExt;
|
| 1018 | end;
|
| 1019 | {$ENDIF}
|
| 1020 | |
| 1021 | {$IFDEF LINK_BITMAP}
|
| 1022 | |
| 1023 | { TImagingBitmap class implementation }
|
| 1024 | |
| 1025 | constructor TImagingBitmap.Create;
|
| 1026 | begin
|
| 1027 | inherited Create;
|
| 1028 | FUseRLE := (GetFileFormat as TBitmapFileFormat).UseRLE;
|
| 1029 | end;
|
| 1030 | |
| 1031 | class function TImagingBitmap.GetFileFormat: TImageFileFormat; |
| 1032 | begin
|
| 1033 | Result := FindImageFileFormatByClass(TBitmapFileFormat); |
| 1034 | end;
|
| 1035 | |
| 1036 | procedure TImagingBitmap.SaveToStream(Stream: TStream);
|
| 1037 | begin
|
| 1038 | Imaging.PushOptions; |
| 1039 | Imaging.SetOption(ImagingBitmapRLE, Ord(FUseRLE)); |
| 1040 | inherited SaveToStream(Stream);
|
| 1041 | Imaging.PopOptions; |
| 1042 | end;
|
| 1043 | {$ENDIF}
|
| 1044 | |
| 1045 | {$IFDEF LINK_JPEG}
|
| 1046 | |
| 1047 | { TImagingJpeg class implementation }
|
| 1048 | |
| 1049 | constructor TImagingJpeg.Create;
|
| 1050 | begin
|
| 1051 | inherited Create;
|
| 1052 | FQuality := (GetFileFormat as TJpegFileFormat).Quality;
|
| 1053 | FProgressive := (GetFileFormat as TJpegFileFormat).Progressive;
|
| 1054 | end;
|
| 1055 | |
| 1056 | class function TImagingJpeg.GetFileFormat: TImageFileFormat; |
| 1057 | begin
|
| 1058 | Result := FindImageFileFormatByClass(TJpegFileFormat); |
| 1059 | end;
|
| 1060 | |
| 1061 | {$IFDEF COMPONENT_SET_LCL}
|
| 1062 | function TImagingJpeg.GetDefaultMimeType: string; |
| 1063 | begin
|
| 1064 | Result := 'image/jpeg';
|
| 1065 | end;
|
| 1066 | {$ENDIF}
|
| 1067 | |
| 1068 | procedure TImagingJpeg.SaveToStream(Stream: TStream);
|
| 1069 | begin
|
| 1070 | Imaging.PushOptions; |
| 1071 | Imaging.SetOption(ImagingJpegQuality, FQuality); |
| 1072 | Imaging.SetOption(ImagingJpegProgressive, Ord(FProgressive)); |
| 1073 | inherited SaveToStream(Stream);
|
| 1074 | Imaging.PopOptions; |
| 1075 | end;
|
| 1076 | |
| 1077 | {$ENDIF}
|
| 1078 | |
| 1079 | {$IFDEF LINK_PNG}
|
| 1080 | |
| 1081 | { TImagingPNG class implementation }
|
| 1082 | |
| 1083 | constructor TImagingPNG.Create;
|
| 1084 | begin
|
| 1085 | inherited Create;
|
| 1086 | FPreFilter := (GetFileFormat as TPNGFileFormat).PreFilter;
|
| 1087 | FCompressLevel := (GetFileFormat as TPNGFileFormat).CompressLevel;
|
| 1088 | end;
|
| 1089 | |
| 1090 | class function TImagingPNG.GetFileFormat: TImageFileFormat; |
| 1091 | begin
|
| 1092 | Result := FindImageFileFormatByClass(TPNGFileFormat); |
| 1093 | end;
|
| 1094 | |
| 1095 | procedure TImagingPNG.SaveToStream(Stream: TStream);
|
| 1096 | begin
|
| 1097 | Imaging.PushOptions; |
| 1098 | Imaging.SetOption(ImagingPNGPreFilter, FPreFilter); |
| 1099 | Imaging.SetOption(ImagingPNGCompressLevel, FCompressLevel); |
| 1100 | inherited SaveToStream(Stream);
|
| 1101 | Imaging.PopOptions; |
| 1102 | end;
|
| 1103 | {$ENDIF}
|
| 1104 | |
| 1105 | {$IFDEF LINK_GIF}
|
| 1106 | |
| 1107 | { TImagingGIF class implementation}
|
| 1108 | |
| 1109 | class function TImagingGIF.GetFileFormat: TImageFileFormat; |
| 1110 | begin
|
| 1111 | Result := FindImageFileFormatByClass(TGIFFileFormat); |
| 1112 | end;
|
| 1113 | |
| 1114 | {$ENDIF}
|
| 1115 | |
| 1116 | {$IFDEF LINK_TARGA}
|
| 1117 | |
| 1118 | { TImagingTarga class implementation }
|
| 1119 | |
| 1120 | constructor TImagingTarga.Create;
|
| 1121 | begin
|
| 1122 | inherited Create;
|
| 1123 | FUseRLE := (GetFileFormat as TTargaFileFormat).UseRLE;
|
| 1124 | end;
|
| 1125 | |
| 1126 | class function TImagingTarga.GetFileFormat: TImageFileFormat; |
| 1127 | begin
|
| 1128 | Result := FindImageFileFormatByClass(TTargaFileFormat); |
| 1129 | end;
|
| 1130 | |
| 1131 | procedure TImagingTarga.SaveToStream(Stream: TStream);
|
| 1132 | begin
|
| 1133 | Imaging.PushOptions; |
| 1134 | Imaging.SetOption(ImagingTargaRLE, Ord(FUseRLE)); |
| 1135 | inherited SaveToStream(Stream);
|
| 1136 | Imaging.PopOptions; |
| 1137 | end;
|
| 1138 | {$ENDIF}
|
| 1139 | |
| 1140 | {$IFDEF LINK_DDS}
|
| 1141 | |
| 1142 | { TImagingDDS class implementation }
|
| 1143 | |
| 1144 | constructor TImagingDDS.Create;
|
| 1145 | begin
|
| 1146 | inherited Create;
|
| 1147 | FCompression := dcNone; |
| 1148 | end;
|
| 1149 | |
| 1150 | class function TImagingDDS.GetFileFormat: TImageFileFormat; |
| 1151 | begin
|
| 1152 | Result := FindImageFileFormatByClass(TDDSFileFormat); |
| 1153 | end;
|
| 1154 | |
| 1155 | procedure TImagingDDS.SaveToStream(Stream: TStream);
|
| 1156 | begin
|
| 1157 | case FCompression of |
| 1158 | dcNone: FSavingFormat := ifUnknown; |
| 1159 | dcDXT1: FSavingFormat := ifDXT1; |
| 1160 | dcDXT3: FSavingFormat := ifDXT3; |
| 1161 | dcDXT5: FSavingFormat := ifDXT5; |
| 1162 | end;
|
| 1163 | Imaging.PushOptions; |
| 1164 | Imaging.SetOption(ImagingDDSSaveCubeMap, Ord(False)); |
| 1165 | Imaging.SetOption(ImagingDDSSaveVolume, Ord(False)); |
| 1166 | Imaging.SetOption(ImagingDDSSaveMipMapCount, 1);
|
| 1167 | Imaging.SetOption(ImagingDDSSaveDepth, 1);
|
| 1168 | inherited SaveToStream(Stream);
|
| 1169 | Imaging.PopOptions; |
| 1170 | end;
|
| 1171 | {$ENDIF}
|
| 1172 | |
| 1173 | {$IFDEF LINK_MNG}
|
| 1174 | |
| 1175 | { TImagingMNG class implementation }
|
| 1176 | |
| 1177 | constructor TImagingMNG.Create;
|
| 1178 | begin
|
| 1179 | inherited Create;
|
| 1180 | FLossyCompression := (GetFileFormat as TMNGFileFormat).LossyCompression;
|
| 1181 | FLossyAlpha := (GetFileFormat as TMNGFileFormat).LossyAlpha;
|
| 1182 | FPreFilter := (GetFileFormat as TMNGFileFormat).PreFilter;
|
| 1183 | FCompressLevel := (GetFileFormat as TMNGFileFormat).CompressLevel;
|
| 1184 | FQuality := (GetFileFormat as TMNGFileFormat).Quality;
|
| 1185 | FProgressive := (GetFileFormat as TMNGFileFormat).Progressive;
|
| 1186 | end;
|
| 1187 | |
| 1188 | class function TImagingMNG.GetFileFormat: TImageFileFormat; |
| 1189 | begin
|
| 1190 | Result := FindImageFileFormatByClass(TMNGFileFormat); |
| 1191 | end;
|
| 1192 | |
| 1193 | {$IFDEF COMPONENT_SET_LCL}
|
| 1194 | function TImagingMNG.GetDefaultMimeType: string; |
| 1195 | begin
|
| 1196 | Result := 'video/mng';
|
| 1197 | end;
|
| 1198 | {$ENDIF}
|
| 1199 | |
| 1200 | procedure TImagingMNG.SaveToStream(Stream: TStream);
|
| 1201 | begin
|
| 1202 | Imaging.PushOptions; |
| 1203 | Imaging.SetOption(ImagingMNGLossyCompression, Ord(FLossyCompression)); |
| 1204 | Imaging.SetOption(ImagingMNGLossyAlpha, Ord(FLossyAlpha)); |
| 1205 | Imaging.SetOption(ImagingMNGPreFilter, FPreFilter); |
| 1206 | Imaging.SetOption(ImagingMNGCompressLevel, FCompressLevel); |
| 1207 | Imaging.SetOption(ImagingMNGQuality, FQuality); |
| 1208 | Imaging.SetOption(ImagingMNGProgressive, Ord(FProgressive)); |
| 1209 | inherited SaveToStream(Stream);
|
| 1210 | Imaging.PopOptions; |
| 1211 | end;
|
| 1212 | {$ENDIF}
|
| 1213 | |
| 1214 | {$IFDEF LINK_JNG}
|
| 1215 | |
| 1216 | { TImagingJNG class implementation }
|
| 1217 | |
| 1218 | constructor TImagingJNG.Create;
|
| 1219 | begin
|
| 1220 | inherited Create;
|
| 1221 | FLossyAlpha := (GetFileFormat as TJNGFileFormat).LossyAlpha;
|
| 1222 | FAlphaPreFilter := (GetFileFormat as TJNGFileFormat).PreFilter;
|
| 1223 | FAlphaCompressLevel := (GetFileFormat as TJNGFileFormat).CompressLevel;
|
| 1224 | FQuality := (GetFileFormat as TJNGFileFormat).Quality;
|
| 1225 | FProgressive := (GetFileFormat as TJNGFileFormat).Progressive;
|
| 1226 | end;
|
| 1227 | |
| 1228 | class function TImagingJNG.GetFileFormat: TImageFileFormat; |
| 1229 | begin
|
| 1230 | Result := FindImageFileFormatByClass(TJNGFileFormat); |
| 1231 | end;
|
| 1232 | |
| 1233 | procedure TImagingJNG.SaveToStream(Stream: TStream);
|
| 1234 | begin
|
| 1235 | Imaging.PushOptions; |
| 1236 | Imaging.SetOption(ImagingJNGLossyALpha, Ord(FLossyAlpha)); |
| 1237 | Imaging.SetOption(ImagingJNGAlphaPreFilter, FAlphaPreFilter); |
| 1238 | Imaging.SetOption(ImagingJNGAlphaCompressLevel, FAlphaCompressLevel); |
| 1239 | Imaging.SetOption(ImagingJNGQuality, FQuality); |
| 1240 | Imaging.SetOption(ImagingJNGProgressive, Ord(FProgressive)); |
| 1241 | inherited SaveToStream(Stream);
|
| 1242 | Imaging.PopOptions; |
| 1243 | end;
|
| 1244 | {$ENDIF}
|
| 1245 | |
| 1246 | initialization
|
| 1247 | RegisterTypes; |
| 1248 | finalization
|
| 1249 | UnRegisterTypes; |
| 1250 | |
| 1251 | {
|
| 1252 | File Notes: |
| 1253 | |
| 1254 | -- TODOS ---------------------------------------------------- |
| 1255 | - nothing now |
| 1256 | |
| 1257 | -- 0.24.1 Changes/Bug Fixes --------------------------------- |
| 1258 | - Fixed wrong IFDEF causing that Imaging wouldn't compile in Lazarus |
| 1259 | with GTK2 target. |
| 1260 | - Added commnets with code for Lazarus rev. 11861+ regarding |
| 1261 | RawImage interface. Replace current code with that in comments |
| 1262 | if you use Lazarus from SVN. New RawImage interface will be used by |
| 1263 | default after next Lazarus release. |
| 1264 | |
| 1265 | -- 0.23 Changes/Bug Fixes ----------------------------------- |
| 1266 | - Added TImagingGIF. |
| 1267 | |
| 1268 | -- 0.21 Changes/Bug Fixes ----------------------------------- |
| 1269 | - Uses only high level interface now (except for saving options). |
| 1270 | - Slightly changed class hierarchy. TImagingGraphic is now only for loading |
| 1271 | and base class for savers is new TImagingGraphicForSave. Also |
| 1272 | TImagingGraphic is now registered with all supported file formats |
| 1273 | by TPicture's format support. |
| 1274 | |
| 1275 | -- 0.19 Changes/Bug Fixes ----------------------------------- |
| 1276 | - added DisplayImage procedures (thanks to Paul Michell, modified) |
| 1277 | - removed RegisterTypes and UnRegisterTypes from interface section, |
| 1278 | they are called automatically |
| 1279 | - added procedures: ConvertImageToBitmap and ConvertBitmapToImage |
| 1280 | |
| 1281 | -- 0.17 Changes/Bug Fixes ----------------------------------- |
| 1282 | - LCL data to bitmap conversion didn?t work in Linux, fixed |
| 1283 | - added MNG file format |
| 1284 | - added JNG file format |
| 1285 | |
| 1286 | -- 0.15 Changes/Bug Fixes ----------------------------------- |
| 1287 | - made it LCL compatible |
| 1288 | - made it CLX compatible |
| 1289 | - added all initial stuff |
| 1290 | } |
| 1291 | |
| 1292 | end.
|
| 1293 |