1 { glBitmap by Steffen Xonna aka Lossy eX (2003-2008)
2 http://www.opengl24.de/index.php?cat=header&file=glbitmap
4 modified by Delphi OpenGL Community (http://delphigl.com/) (2013)
6 The contents of this file are used with permission, subject to
7 the Mozilla Public License Version 1.1 (the "License"); you may
8 not use this file except in compliance with the License. You may
9 obtain a copy of the License at
10 http://www.mozilla.org/MPL/MPL-1.1.html
12 The glBitmap is a Delphi/FPC unit that contains several wrapper classes
13 to manage OpenGL texture objects. Below you can find a list of the main
14 functionality of this classes:
15 - load texture data from file (e.g. BMP, TGA, DDS, PNG, JPEG, ...)
16 - load texture data from several other image objects (e.g. TBitmap, TLazIntfImage, SDL Surface)
17 - save texture data to file (e.g. BMP, TGA, DDS, PNG, JPEG, ...)
18 - save texture data to several other image objects (e.g. TBitmap, TLazIntfImage, SDL Surface)
19 - support for many texture formats (e.g. RGB8, BGR8, RGBA8, BGRA8, ...)
20 - manage texture properties (e.g. Filter, Clamp, Mipmap, ...)
21 - upload texture data to video card
22 - download texture data from video card
23 - manipulate texture data (e.g. add alpha, remove alpha, convert to other format, switch RGB, ...) }
44 {$IF DEFINED(WIN32) or DEFINED(WIN64) or DEFINED(WINDOWS)}
46 {$ELSEIF DEFINED(LINUX)}
51 {$IF DEFINED(OPENGL_ES_EXT)} {$DEFINE OPENGL_ES_1_1} {$IFEND}
52 {$IF DEFINED(OPENGL_ES_3_0)} {$DEFINE OPENGL_ES_2_0} {$IFEND}
53 {$IF DEFINED(OPENGL_ES_2_0)} {$DEFINE OPENGL_ES_1_1} {$IFEND}
54 {$IF DEFINED(OPENGL_ES_1_1)} {$DEFINE OPENGL_ES} {$IFEND}
56 // checking define combinations
58 {$IFDEF GLB_SDL_IMAGE}
60 {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
65 {$MESSAGE warn 'The Lazarus TPortableNetworkGraphics will be ignored because you are using SDL_image.'}
70 {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
75 {$MESSAGE warn 'The Lazarus TJPEGImage will be ignored because you are using SDL_image.'}
79 {$IFDEF GLB_DELPHI_JPEG}
80 {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
81 {$undef GLB_DELPHI_JPEG}
85 {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
90 {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
94 {$DEFINE GLB_SUPPORT_PNG_READ}
95 {$DEFINE GLB_SUPPORT_JPEG_READ}
98 // Lazarus TPortableNetworkGraphic
100 {$IFNDEF GLB_LAZARUS}
101 {$MESSAGE warn 'Lazarus TPortableNetworkGraphic won''t work without Lazarus. Lazarus will be activated.'}
102 {$DEFINE GLB_LAZARUS}
105 {$IFDEF GLB_PNGIMAGE}
106 {$MESSAGE warn 'The pngimage will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
107 {$undef GLB_PNGIMAGE}
111 {$MESSAGE warn 'The library libPNG will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
115 {$DEFINE GLB_SUPPORT_PNG_READ}
116 {$DEFINE GLB_SUPPORT_PNG_WRITE}
120 {$IFDEF GLB_PNGIMAGE}
122 {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'}
126 {$DEFINE GLB_SUPPORT_PNG_READ}
127 {$DEFINE GLB_SUPPORT_PNG_WRITE}
132 {$DEFINE GLB_SUPPORT_PNG_READ}
133 {$DEFINE GLB_SUPPORT_PNG_WRITE}
136 // Lazarus TJPEGImage
137 {$IFDEF GLB_LAZ_JPEG}
138 {$IFNDEF GLB_LAZARUS}
139 {$MESSAGE warn 'Lazarus TJPEGImage won''t work without Lazarus. Lazarus will be activated.'}
140 {$DEFINE GLB_LAZARUS}
143 {$IFDEF GLB_DELPHI_JPEG}
144 {$MESSAGE warn 'The Delphi JPEGImage will be ignored if you are using the Lazarus TJPEGImage.'}
145 {$undef GLB_DELPHI_JPEG}
148 {$IFDEF GLB_LIB_JPEG}
149 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the Lazarus TJPEGImage.'}
150 {$undef GLB_LIB_JPEG}
153 {$DEFINE GLB_SUPPORT_JPEG_READ}
154 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
158 {$IFDEF GLB_DELPHI_JPEG}
159 {$IFDEF GLB_LIB_JPEG}
160 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
161 {$undef GLB_LIB_JPEG}
164 {$DEFINE GLB_SUPPORT_JPEG_READ}
165 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
169 {$IFDEF GLB_LIB_JPEG}
170 {$DEFINE GLB_SUPPORT_JPEG_READ}
171 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
185 {$IFDEF OPENGL_ES} dglOpenGLES,
186 {$ELSE} dglOpenGL, {$ENDIF}
188 {$IF DEFINED(GLB_WIN) AND
189 DEFINED(GLB_DELPHI)} windows, {$IFEND}
191 {$IFDEF GLB_SDL} SDL, {$ENDIF}
192 {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, Graphics, {$ENDIF}
193 {$IFDEF GLB_DELPHI} Dialogs, Graphics, Types, {$ENDIF}
195 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
196 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
197 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
198 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
199 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
205 QWord = System.UInt64;
213 { type that describes the format of the data stored in a texture.
214 the name of formats is composed of the following constituents:
216 - channel (e.g. R, G, B, A or Alpha, Luminance or X (reserved))
217 - width of the chanel in bit (4, 8, 16, ...)
218 - data type (e.g. ub, us, ui)
219 - number of elements of data types }
223 tfAlpha4ub1, //< 1 x unsigned byte
224 tfAlpha8ub1, //< 1 x unsigned byte
225 tfAlpha16us1, //< 1 x unsigned short
227 tfLuminance4ub1, //< 1 x unsigned byte
228 tfLuminance8ub1, //< 1 x unsigned byte
229 tfLuminance16us1, //< 1 x unsigned short
231 tfLuminance4Alpha4ub2, //< 1 x unsigned byte (lum), 1 x unsigned byte (alpha)
232 tfLuminance6Alpha2ub2, //< 1 x unsigned byte (lum), 1 x unsigned byte (alpha)
233 tfLuminance8Alpha8ub2, //< 1 x unsigned byte (lum), 1 x unsigned byte (alpha)
234 tfLuminance12Alpha4us2, //< 1 x unsigned short (lum), 1 x unsigned short (alpha)
235 tfLuminance16Alpha16us2, //< 1 x unsigned short (lum), 1 x unsigned short (alpha)
237 tfR3G3B2ub1, //< 1 x unsigned byte (3bit red, 3bit green, 2bit blue)
238 tfRGBX4us1, //< 1 x unsigned short (4bit red, 4bit green, 4bit blue, 4bit reserverd)
239 tfXRGB4us1, //< 1 x unsigned short (4bit reserved, 4bit red, 4bit green, 4bit blue)
240 tfR5G6B5us1, //< 1 x unsigned short (5bit red, 6bit green, 5bit blue)
241 tfRGB5X1us1, //< 1 x unsigned short (5bit red, 5bit green, 5bit blue, 1bit reserved)
242 tfX1RGB5us1, //< 1 x unsigned short (1bit reserved, 5bit red, 5bit green, 5bit blue)
243 tfRGB8ub3, //< 1 x unsigned byte (red), 1 x unsigned byte (green), 1 x unsigned byte (blue)
244 tfRGBX8ui1, //< 1 x unsigned int (8bit red, 8bit green, 8bit blue, 8bit reserved)
245 tfXRGB8ui1, //< 1 x unsigned int (8bit reserved, 8bit red, 8bit green, 8bit blue)
246 tfRGB10X2ui1, //< 1 x unsigned int (10bit red, 10bit green, 10bit blue, 2bit reserved)
247 tfX2RGB10ui1, //< 1 x unsigned int (2bit reserved, 10bit red, 10bit green, 10bit blue)
248 tfRGB16us3, //< 1 x unsigned short (red), 1 x unsigned short (green), 1 x unsigned short (blue)
250 tfRGBA4us1, //< 1 x unsigned short (4bit red, 4bit green, 4bit blue, 4bit alpha)
251 tfARGB4us1, //< 1 x unsigned short (4bit alpha, 4bit red, 4bit green, 4bit blue)
252 tfRGB5A1us1, //< 1 x unsigned short (5bit red, 5bit green, 5bit blue, 1bit alpha)
253 tfA1RGB5us1, //< 1 x unsigned short (1bit alpha, 5bit red, 5bit green, 5bit blue)
254 tfRGBA8ui1, //< 1 x unsigned int (8bit red, 8bit green, 8bit blue, 8 bit alpha)
255 tfARGB8ui1, //< 1 x unsigned int (8 bit alpha, 8bit red, 8bit green, 8bit blue)
256 tfRGBA8ub4, //< 1 x unsigned byte (red), 1 x unsigned byte (green), 1 x unsigned byte (blue), 1 x unsigned byte (alpha)
257 tfRGB10A2ui1, //< 1 x unsigned int (10bit red, 10bit green, 10bit blue, 2bit alpha)
258 tfA2RGB10ui1, //< 1 x unsigned int (2bit alpha, 10bit red, 10bit green, 10bit blue)
259 tfRGBA16us4, //< 1 x unsigned short (red), 1 x unsigned short (green), 1 x unsigned short (blue), 1 x unsigned short (alpha)
261 tfBGRX4us1, //< 1 x unsigned short (4bit blue, 4bit green, 4bit red, 4bit reserved)
262 tfXBGR4us1, //< 1 x unsigned short (4bit reserved, 4bit blue, 4bit green, 4bit red)
263 tfB5G6R5us1, //< 1 x unsigned short (5bit blue, 6bit green, 5bit red)
264 tfBGR5X1us1, //< 1 x unsigned short (5bit blue, 5bit green, 5bit red, 1bit reserved)
265 tfX1BGR5us1, //< 1 x unsigned short (1bit reserved, 5bit blue, 5bit green, 5bit red)
266 tfBGR8ub3, //< 1 x unsigned byte (blue), 1 x unsigned byte (green), 1 x unsigned byte (red)
267 tfBGRX8ui1, //< 1 x unsigned int (8bit blue, 8bit green, 8bit red, 8bit reserved)
268 tfXBGR8ui1, //< 1 x unsigned int (8bit reserved, 8bit blue, 8bit green, 8bit red)
269 tfBGR10X2ui1, //< 1 x unsigned int (10bit blue, 10bit green, 10bit red, 2bit reserved)
270 tfX2BGR10ui1, //< 1 x unsigned int (2bit reserved, 10bit blue, 10bit green, 10bit red)
271 tfBGR16us3, //< 1 x unsigned short (blue), 1 x unsigned short (green), 1 x unsigned short (red)
273 tfBGRA4us1, //< 1 x unsigned short (4bit blue, 4bit green, 4bit red, 4bit alpha)
274 tfABGR4us1, //< 1 x unsigned short (4bit alpha, 4bit blue, 4bit green, 4bit red)
275 tfBGR5A1us1, //< 1 x unsigned short (5bit blue, 5bit green, 5bit red, 1bit alpha)
276 tfA1BGR5us1, //< 1 x unsigned short (1bit alpha, 5bit blue, 5bit green, 5bit red)
277 tfBGRA8ui1, //< 1 x unsigned int (8bit blue, 8bit green, 8bit red, 8bit alpha)
278 tfABGR8ui1, //< 1 x unsigned int (8bit alpha, 8bit blue, 8bit green, 8bit red)
279 tfBGRA8ub4, //< 1 x unsigned byte (blue), 1 x unsigned byte (green), 1 x unsigned byte (red), 1 x unsigned byte (alpha)
280 tfBGR10A2ui1, //< 1 x unsigned int (10bit blue, 10bit green, 10bit red, 2bit alpha)
281 tfA2BGR10ui1, //< 1 x unsigned int (2bit alpha, 10bit blue, 10bit green, 10bit red)
282 tfBGRA16us4, //< 1 x unsigned short (blue), 1 x unsigned short (green), 1 x unsigned short (red), 1 x unsigned short (alpha)
284 tfDepth16us1, //< 1 x unsigned short (depth)
285 tfDepth24ui1, //< 1 x unsigned int (depth)
286 tfDepth32ui1, //< 1 x unsigned int (depth)
293 { type to define suitable file formats }
294 TglBitmapFileType = (
295 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF} //< Portable Network Graphic file (PNG)
296 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF} //< JPEG file
297 ftDDS, //< Direct Draw Surface file (DDS)
298 ftTGA, //< Targa Image File (TGA)
299 ftBMP, //< Windows Bitmap File (BMP)
300 ftRAW); //< glBitmap RAW file format
301 TglBitmapFileTypes = set of TglBitmapFileType;
303 { possible mipmap types }
305 mmNone, //< no mipmaps
306 mmMipmap, //< normal mipmaps
307 mmMipmapGlu); //< mipmaps generated with glu functions
309 { possible normal map functions }
310 TglBitmapNormalMapFunc = (
316 ////////////////////////////////////////////////////////////////////////////////////////////////////
317 EglBitmap = class(Exception); //< glBitmap exception
318 EglBitmapNotSupported = class(Exception); //< exception for not supported functions
319 EglBitmapSizeToLarge = class(EglBitmap); //< exception for to large textures
320 EglBitmapNonPowerOfTwo = class(EglBitmap); //< exception for non power of two textures
321 EglBitmapUnsupportedFormat = class(EglBitmap) //< exception for unsupporetd formats
323 constructor Create(const aFormat: TglBitmapFormat); overload;
324 constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload;
327 ////////////////////////////////////////////////////////////////////////////////////////////////////
328 { record that stores 4 unsigned integer values }
329 TglBitmapRec4ui = packed record
331 0: (r, g, b, a: Cardinal);
332 1: (arr: array[0..3] of Cardinal);
335 { record that stores 4 unsigned byte values }
336 TglBitmapRec4ub = packed record
338 0: (r, g, b, a: Byte);
339 1: (arr: array[0..3] of Byte);
342 { record that stores 4 unsigned long integer values }
343 TglBitmapRec4ul = packed record
345 0: (r, g, b, a: QWord);
346 1: (arr: array[0..3] of QWord);
349 { structure to store pixel data in }
350 TglBitmapPixelData = packed record
351 Data: TglBitmapRec4ui; //< color data for each color channel
352 Range: TglBitmapRec4ui; //< maximal color value for each channel
353 Format: TglBitmapFormat; //< format of the pixel
355 PglBitmapPixelData = ^TglBitmapPixelData;
357 TglBitmapSizeFields = set of (ffX, ffY);
358 TglBitmapSize = packed record
359 Fields: TglBitmapSizeFields;
363 TglBitmapPixelPosition = TglBitmapSize;
365 { describes the properties of a given texture data format }
366 TglBitmapFormatDescriptor = class(TObject)
369 fBytesPerPixel: Single; //< number of bytes for each pixel
370 fChannelCount: Integer; //< number of color channels
371 fMask: TglBitmapRec4ul; //< bitmask for each color channel
372 fRange: TglBitmapRec4ui; //< maximal value of each color channel
374 { @return @true if the format has a red color channel, @false otherwise }
375 function GetHasRed: Boolean;
377 { @return @true if the format has a green color channel, @false otherwise }
378 function GetHasGreen: Boolean;
380 { @return @true if the format has a blue color channel, @false otherwise }
381 function GetHasBlue: Boolean;
383 { @return @true if the format has a alpha color channel, @false otherwise }
384 function GetHasAlpha: Boolean;
386 { @return @true if the format has any color color channel, @false otherwise }
387 function GetHasColor: Boolean;
389 { @return @true if the format is a grayscale format, @false otherwise }
390 function GetIsGrayscale: Boolean;
392 { @return @true if the format is supported by OpenGL, @false otherwise }
393 function GetHasOpenGLSupport: Boolean;
396 fFormat: TglBitmapFormat; //< format this descriptor belongs to
397 fWithAlpha: TglBitmapFormat; //< suitable format with alpha channel
398 fWithoutAlpha: TglBitmapFormat; //< suitable format without alpha channel
399 fOpenGLFormat: TglBitmapFormat; //< suitable format that is supported by OpenGL
400 fRGBInverted: TglBitmapFormat; //< suitable format with inverted RGB channels
401 fUncompressed: TglBitmapFormat; //< suitable format with uncompressed data
403 fBitsPerPixel: Integer; //< number of bits per pixel
404 fIsCompressed: Boolean; //< @true if the format is compressed, @false otherwise
406 fPrecision: TglBitmapRec4ub; //< number of bits for each color channel
407 fShift: TglBitmapRec4ub; //< bit offset for each color channel
409 fglFormat: GLenum; //< OpenGL format enum (e.g. GL_RGB)
410 fglInternalFormat: GLenum; //< OpenGL internal format enum (e.g. GL_RGB8)
411 fglDataFormat: GLenum; //< OpenGL data format enum (e.g. GL_UNSIGNED_BYTE)
413 { set values for this format descriptor }
414 procedure SetValues; virtual;
416 { calculate cached values }
417 procedure CalcValues;
419 property Format: TglBitmapFormat read fFormat; //< format this descriptor belongs to
420 property ChannelCount: Integer read fChannelCount; //< number of color channels
421 property IsCompressed: Boolean read fIsCompressed; //< @true if the format is compressed, @false otherwise
422 property BitsPerPixel: Integer read fBitsPerPixel; //< number of bytes per pixel
423 property BytesPerPixel: Single read fBytesPerPixel; //< number of bits per pixel
425 property Precision: TglBitmapRec4ub read fPrecision; //< number of bits for each color channel
426 property Shift: TglBitmapRec4ub read fShift; //< bit offset for each color channel
427 property Range: TglBitmapRec4ui read fRange; //< maximal value of each color channel
428 property Mask: TglBitmapRec4ul read fMask; //< bitmask for each color channel
430 property RGBInverted: TglBitmapFormat read fRGBInverted; //< suitable format with inverted RGB channels
431 property WithAlpha: TglBitmapFormat read fWithAlpha; //< suitable format with alpha channel
432 property WithoutAlpha: TglBitmapFormat read fWithAlpha; //< suitable format without alpha channel
433 property OpenGLFormat: TglBitmapFormat read fOpenGLFormat; //< suitable format that is supported by OpenGL
434 property Uncompressed: TglBitmapFormat read fUncompressed; //< suitable format with uncompressed data
436 property glFormat: GLenum read fglFormat; //< OpenGL format enum (e.g. GL_RGB)
437 property glInternalFormat: GLenum read fglInternalFormat; //< OpenGL internal format enum (e.g. GL_RGB8)
438 property glDataFormat: GLenum read fglDataFormat; //< OpenGL data format enum (e.g. GL_UNSIGNED_BYTE)
440 property HasRed: Boolean read GetHasRed; //< @true if the format has a red color channel, @false otherwise
441 property HasGreen: Boolean read GetHasGreen; //< @true if the format has a green color channel, @false otherwise
442 property HasBlue: Boolean read GetHasBlue; //< @true if the format has a blue color channel, @false otherwise
443 property HasAlpha: Boolean read GetHasAlpha; //< @true if the format has a alpha color channel, @false otherwise
444 property HasColor: Boolean read GetHasColor; //< @true if the format has any color color channel, @false otherwise
445 property IsGrayscale: Boolean read GetIsGrayscale; //< @true if the format is a grayscale format, @false otherwise
447 property HasOpenGLSupport: Boolean read GetHasOpenGLSupport; //< @true if the format is supported by OpenGL, @false otherwise
449 function GetSize(const aSize: TglBitmapSize): Integer; overload; virtual;
450 function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
455 { get the format descriptor by a given OpenGL internal format
456 @param aInternalFormat OpenGL internal format to get format descriptor for
457 @returns suitable format descriptor or tfEmpty-Descriptor }
458 class function GetByFormat(const aInternalFormat: GLenum): TglBitmapFormatDescriptor;
461 ////////////////////////////////////////////////////////////////////////////////////////////////////
462 TglBitmapData = class;
464 { structure to store data for converting in }
465 TglBitmapFunctionRec = record
466 Sender: TglBitmapData; //< texture object that stores the data to convert
467 Size: TglBitmapSize; //< size of the texture
468 Position: TglBitmapPixelPosition; //< position of the currently pixel
469 Source: TglBitmapPixelData; //< pixel data of the current pixel
470 Dest: TglBitmapPixelData; //< new data of the pixel (must be filled in)
471 Args: Pointer; //< user defined args that was passed to the convert function
474 { callback to use for converting texture data }
475 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
477 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
478 { class to store texture data in. used to load, save and
479 manipulate data before assigned to texture object
480 all operations on a data object can be done from a background thread }
481 TglBitmapData = class
484 fData: PByte; //< texture data
485 fDimension: TglBitmapSize; //< pixel size of the data
486 fFormat: TglBitmapFormat; //< format the texture data is stored in
487 fFilename: String; //< file the data was load from
489 fScanlines: array of PByte; //< pointer to begin of each line
490 fHasScanlines: Boolean; //< @true if scanlines are initialized, @false otherwise
492 private { getter / setter }
494 { @returns the format descriptor suitable to the texture data format }
495 function GetFormatDescriptor: TglBitmapFormatDescriptor;
497 { @returns the width of the texture data (in pixel) or -1 if no data is set }
498 function GetWidth: Integer;
500 { @returns the height of the texture data (in pixel) or -1 if no data is set }
501 function GetHeight: Integer;
503 { get scanline at index aIndex
504 @returns Pointer to start of line or @nil }
505 function GetScanlines(const aIndex: Integer): PByte;
507 { set new value for the data format. only possible if new format has the same pixel size.
508 if you want to convert the texture data, see ConvertTo function }
509 procedure SetFormat(const aValue: TglBitmapFormat);
511 private { internal misc }
513 { splits a resource identifier into the resource and it's type
514 @param aResource resource identifier to split and store name in
515 @param aResType type of the resource }
516 procedure PrepareResType(var aResource: String; var aResType: PChar);
518 { updates scanlines array }
519 procedure UpdateScanlines;
521 private { internal load and save }
522 {$IFDEF GLB_SUPPORT_PNG_READ}
523 { try to load a PNG from a stream
524 @param aStream stream to load PNG from
525 @returns @true on success, @false otherwise }
526 function LoadPNG(const aStream: TStream): Boolean; virtual;
529 {$ifdef GLB_SUPPORT_PNG_WRITE}
530 { save texture data as PNG to stream
531 @param aStream stream to save data to}
532 procedure SavePNG(const aStream: TStream); virtual;
535 {$IFDEF GLB_SUPPORT_JPEG_READ}
536 { try to load a JPEG from a stream
537 @param aStream stream to load JPEG from
538 @returns @true on success, @false otherwise }
539 function LoadJPEG(const aStream: TStream): Boolean; virtual;
542 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
543 { save texture data as JPEG to stream
544 @param aStream stream to save data to}
545 procedure SaveJPEG(const aStream: TStream); virtual;
548 { try to load a RAW image from a stream
549 @param aStream stream to load RAW image from
550 @returns @true on success, @false otherwise }
551 function LoadRAW(const aStream: TStream): Boolean;
553 { save texture data as RAW image to stream
554 @param aStream stream to save data to}
555 procedure SaveRAW(const aStream: TStream);
557 { try to load a BMP from a stream
558 @param aStream stream to load BMP from
559 @returns @true on success, @false otherwise }
560 function LoadBMP(const aStream: TStream): Boolean;
562 { save texture data as BMP to stream
563 @param aStream stream to save data to}
564 procedure SaveBMP(const aStream: TStream);
566 { try to load a TGA from a stream
567 @param aStream stream to load TGA from
568 @returns @true on success, @false otherwise }
569 function LoadTGA(const aStream: TStream): Boolean;
571 { save texture data as TGA to stream
572 @param aStream stream to save data to}
573 procedure SaveTGA(const aStream: TStream);
575 { try to load a DDS from a stream
576 @param aStream stream to load DDS from
577 @returns @true on success, @false otherwise }
578 function LoadDDS(const aStream: TStream): Boolean;
580 { save texture data as DDS to stream
581 @param aStream stream to save data to}
582 procedure SaveDDS(const aStream: TStream);
584 public { properties }
585 property Data: PByte read fData; //< texture data (be carefull with this!)
586 property Dimension: TglBitmapSize read fDimension; //< size of the texture data (in pixel)
587 property Filename: String read fFilename; //< file the data was loaded from
588 property Width: Integer read GetWidth; //< width of the texture data (in pixel)
589 property Height: Integer read GetHeight; //< height of the texture data (in pixel)
590 property Format: TglBitmapFormat read fFormat write SetFormat; //< format the texture data is stored in
591 property Scanlines[const aIndex: Integer]: PByte read GetScanlines; //< pointer to begin of line at given index or @nil
593 property FormatDescriptor: TglBitmapFormatDescriptor read GetFormatDescriptor; //< descriptor object that describes the format of the stored data
597 { flip texture horizontal
598 @returns @true in success, @false otherwise }
599 function FlipHorz: Boolean; virtual;
601 { flip texture vertical
602 @returns @true in success, @false otherwise }
603 function FlipVert: Boolean; virtual;
607 { load a texture from a file
608 @param aFilename file to load texuture from }
609 procedure LoadFromFile(const aFilename: String);
611 { load a texture from a stream
612 @param aStream stream to load texture from }
613 procedure LoadFromStream(const aStream: TStream); virtual;
615 { use a function to generate texture data
616 @param aSize size of the texture
617 @param aFormat format of the texture data
618 @param aFunc callback to use for generation
619 @param aArgs user defined paramaters (use at will) }
620 procedure LoadFromFunc(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil);
622 { load a texture from a resource
623 @param aInstance resource handle
624 @param aResource resource indentifier
625 @param aResType resource type (if known) }
626 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil);
628 { load a texture from a resource id
629 @param aInstance resource handle
630 @param aResource resource ID
631 @param aResType resource type }
632 procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
636 { save texture data to a file
637 @param aFilename filename to store texture in
638 @param aFileType file type to store data into }
639 procedure SaveToFile(const aFilename: String; const aFileType: TglBitmapFileType);
641 { save texture data to a stream
642 @param aFilename filename to store texture in
643 @param aFileType file type to store data into }
644 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
648 { convert texture data using a user defined callback
649 @param aFunc callback to use for converting
650 @param aCreateTemp create a temporary buffer to use for converting
651 @param aArgs user defined paramters (use at will)
652 @returns @true if converting was successful, @false otherwise }
653 function Convert(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
655 { convert texture data using a user defined callback
656 @param aSource glBitmap to read data from
657 @param aFunc callback to use for converting
658 @param aCreateTemp create a temporary buffer to use for converting
659 @param aFormat format of the new data
660 @param aArgs user defined paramters (use at will)
661 @returns @true if converting was successful, @false otherwise }
662 function Convert(const aSource: TglBitmapData; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
663 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
665 { convert texture data using a specific format
666 @param aFormat new format of texture data
667 @returns @true if converting was successful, @false otherwise }
668 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
673 { assign texture data to SDL surface
674 @param aSurface SDL surface to write data to
675 @returns @true on success, @false otherwise }
676 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
678 { assign texture data from SDL surface
679 @param aSurface SDL surface to read data from
680 @returns @true on success, @false otherwise }
681 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
683 { assign alpha channel data to SDL surface
684 @param aSurface SDL surface to write alpha channel data to
685 @returns @true on success, @false otherwise }
686 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
688 { assign alpha channel data from SDL surface
689 @param aSurface SDL surface to read data from
690 @param aFunc callback to use for converting
691 @param aArgs user defined parameters (use at will)
692 @returns @true on success, @false otherwise }
693 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
699 { assign texture data to TBitmap object
700 @param aBitmap TBitmap to write data to
701 @returns @true on success, @false otherwise }
702 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
704 { assign texture data from TBitmap object
705 @param aBitmap TBitmap to read data from
706 @returns @true on success, @false otherwise }
707 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
709 { assign alpha channel data to TBitmap object
710 @param aBitmap TBitmap to write data to
711 @returns @true on success, @false otherwise }
712 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
714 { assign alpha channel data from TBitmap object
715 @param aBitmap TBitmap to read data from
716 @param aFunc callback to use for converting
717 @param aArgs user defined parameters (use at will)
718 @returns @true on success, @false otherwise }
719 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
725 { assign texture data to TLazIntfImage object
726 @param aImage TLazIntfImage to write data to
727 @returns @true on success, @false otherwise }
728 function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
730 { assign texture data from TLazIntfImage object
731 @param aImage TLazIntfImage to read data from
732 @returns @true on success, @false otherwise }
733 function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
735 { assign alpha channel data to TLazIntfImage object
736 @param aImage TLazIntfImage to write data to
737 @returns @true on success, @false otherwise }
738 function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
740 { assign alpha channel data from TLazIntfImage object
741 @param aImage TLazIntfImage to read data from
742 @param aFunc callback to use for converting
743 @param aArgs user defined parameters (use at will)
744 @returns @true on success, @false otherwise }
745 function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
749 { load alpha channel data from resource
750 @param aInstance resource handle
751 @param aResource resource ID
752 @param aResType resource type
753 @param aFunc callback to use for converting
754 @param aArgs user defined parameters (use at will)
755 @returns @true on success, @false otherwise }
756 function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
758 { load alpha channel data from resource ID
759 @param aInstance resource handle
760 @param aResourceID resource ID
761 @param aResType resource type
762 @param aFunc callback to use for converting
763 @param aArgs user defined parameters (use at will)
764 @returns @true on success, @false otherwise }
765 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
767 { add alpha channel data from function
768 @param aFunc callback to get data from
769 @param aArgs user defined parameters (use at will)
770 @returns @true on success, @false otherwise }
771 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
773 { add alpha channel data from file (macro for: new glBitmap, LoadFromFile, AddAlphaFromGlBitmap)
774 @param aFilename file to load alpha channel data from
775 @param aFunc callback to use for converting
776 @param aArgs SetFormat user defined parameters (use at will)
777 @returns @true on success, @false otherwise }
778 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
780 { add alpha channel data from stream (macro for: new glBitmap, LoadFromStream, AddAlphaFromGlBitmap)
781 @param aStream stream to load alpha channel data from
782 @param aFunc callback to use for converting
783 @param aArgs user defined parameters (use at will)
784 @returns @true on success, @false otherwise }
785 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
787 { add alpha channel data from existing glBitmap object
788 @param aBitmap TglBitmap to copy alpha channel data from
789 @param aFunc callback to use for converting
790 @param aArgs user defined parameters (use at will)
791 @returns @true on success, @false otherwise }
792 function AddAlphaFromDataObj(const aDataObj: TglBitmapData; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
794 { add alpha to pixel if the pixels color is greter than the given color value
795 @param aRed red threshold (0-255)
796 @param aGreen green threshold (0-255)
797 @param aBlue blue threshold (0-255)
798 @param aDeviatation accepted deviatation (0-255)
799 @returns @true on success, @false otherwise }
800 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
802 { add alpha to pixel if the pixels color is greter than the given color value
803 @param aRed red threshold (0-Range.r)
804 @param aGreen green threshold (0-Range.g)
805 @param aBlue blue threshold (0-Range.b)
806 @param aDeviatation accepted deviatation (0-max(Range.rgb))
807 @returns @true on success, @false otherwise }
808 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
810 { add alpha to pixel if the pixels color is greter than the given color value
811 @param aRed red threshold (0.0-1.0)
812 @param aGreen green threshold (0.0-1.0)
813 @param aBlue blue threshold (0.0-1.0)
814 @param aDeviatation accepted deviatation (0.0-1.0)
815 @returns @true on success, @false otherwise }
816 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
818 { add a constand alpha value to all pixels
819 @param aAlpha alpha value to add (0-255)
820 @returns @true on success, @false otherwise }
821 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
823 { add a constand alpha value to all pixels
824 @param aAlpha alpha value to add (0-max(Range.rgb))
825 @returns @true on success, @false otherwise }
826 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
828 { add a constand alpha value to all pixels
829 @param aAlpha alpha value to add (0.0-1.0)
830 @returns @true on success, @false otherwise }
831 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
833 { remove alpha channel
834 @returns @true on success, @false otherwise }
835 function RemoveAlpha: Boolean; virtual;
838 { fill complete texture with one color
839 @param aRed red color for border (0-255)
840 @param aGreen green color for border (0-255)
841 @param aBlue blue color for border (0-255)
842 @param aAlpha alpha color for border (0-255) }
843 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
845 { fill complete texture with one color
846 @param aRed red color for border (0-Range.r)
847 @param aGreen green color for border (0-Range.g)
848 @param aBlue blue color for border (0-Range.b)
849 @param aAlpha alpha color for border (0-Range.a) }
850 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
852 { fill complete texture with one color
853 @param aRed red color for border (0.0-1.0)
854 @param aGreen green color for border (0.0-1.0)
855 @param aBlue blue color for border (0.0-1.0)
856 @param aAlpha alpha color for border (0.0-1.0) }
857 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single = 1.0);
861 { set data pointer of texture data
862 @param aData pointer to new texture data
863 @param aFormat format of the data stored at aData
864 @param aWidth width of the texture data
865 @param aHeight height of the texture data }
866 procedure SetData(const aData: PByte; const aFormat: TglBitmapFormat;
867 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual;
869 { create a clone of the current object
870 @returns clone of this object}
871 function Clone: TglBitmapData;
873 { invert color data (bitwise not)
874 @param aRed invert red channel
875 @param aGreen invert green channel
876 @param aBlue invert blue channel
877 @param aAlpha invert alpha channel }
878 procedure Invert(const aRed, aGreen, aBlue, aAlpha: Boolean);
880 { create normal map from texture data
881 @param aFunc normal map function to generate normalmap with
882 @param aScale scale of the normale stored in the normal map
883 @param aUseAlpha generate normalmap from alpha channel data (if present) }
884 procedure GenerateNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
885 const aScale: Single = 2; const aUseAlpha: Boolean = false);
887 public { constructor }
889 { constructor - creates a texutre data object }
890 constructor Create; overload;
892 { constructor - creates a texture data object and loads it from a file
893 @param aFilename file to load texture from }
894 constructor Create(const aFileName: String); overload;
896 { constructor - creates a texture data object and loads it from a stream
897 @param aStream stream to load texture from }
898 constructor Create(const aStream: TStream); overload;
900 { constructor - creates a texture data object with the given size, format and data
901 @param aSize size of the texture
902 @param aFormat format of the given data
903 @param aData texture data - be carefull: the data will now be managed by the texture data object }
904 constructor Create(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat; aData: PByte = nil); overload;
906 { constructor - creates a texture data object with the given size and format and uses the given callback to create the data
907 @param aSize size of the texture
908 @param aFormat format of the given data
909 @param aFunc callback to use for generating the data
910 @param aArgs user defined parameters (use at will) }
911 constructor Create(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
913 { constructor - creates a texture data object and loads it from a resource
914 @param aInstance resource handle
915 @param aResource resource indentifier
916 @param aResType resource type (if known) }
917 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
919 { constructor - creates a texture data object and loads it from a resource
920 @param aInstance resource handle
921 @param aResourceID resource ID
922 @param aResType resource type (if known) }
923 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
926 destructor Destroy; override;
930 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
931 { base class for all glBitmap classes. used to manage OpenGL texture objects
932 all operations on a bitmap object must be done from the render thread }
935 fID: GLuint; //< name of the OpenGL texture object
936 fTarget: GLuint; //< texture target (e.g. GL_TEXTURE_2D)
937 fDeleteTextureOnFree: Boolean; //< delete OpenGL texture object when this object is destroyed
939 // texture properties
940 fFilterMin: GLenum; //< min filter to apply to the texture
941 fFilterMag: GLenum; //< mag filter to apply to the texture
942 fWrapS: GLenum; //< texture wrapping for x axis
943 fWrapT: GLenum; //< texture wrapping for y axis
944 fWrapR: GLenum; //< texture wrapping for z axis
945 fAnisotropic: Integer; //< anisotropic level
946 fBorderColor: array[0..3] of Single; //< color of the texture border
948 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
950 fSwizzle: array[0..3] of GLenum; //< color channel swizzle
953 fIsResident: GLboolean; //< @true if OpenGL texture object has data, @false otherwise
956 fDimension: TglBitmapSize; //< size of this texture
957 fMipMap: TglBitmapMipMap; //< mipmap type
960 fCustomData: Pointer; //< user defined data
961 fCustomName: String; //< user defined name
962 fCustomNameW: WideString; //< user defined name
964 { @returns the actual width of the texture }
965 function GetWidth: Integer; virtual;
967 { @returns the actual height of the texture }
968 function GetHeight: Integer; virtual;
971 { set a new value for fCustomData }
972 procedure SetCustomData(const aValue: Pointer);
974 { set a new value for fCustomName }
975 procedure SetCustomName(const aValue: String);
977 { set a new value for fCustomNameW }
978 procedure SetCustomNameW(const aValue: WideString);
980 { set new value for fDeleteTextureOnFree }
981 procedure SetDeleteTextureOnFree(const aValue: Boolean);
983 { set name of OpenGL texture object }
984 procedure SetID(const aValue: Cardinal);
986 { set new value for fMipMap }
987 procedure SetMipMap(const aValue: TglBitmapMipMap);
989 { set new value for target }
990 procedure SetTarget(const aValue: Cardinal);
992 { set new value for fAnisotrophic }
993 procedure SetAnisotropic(const aValue: Integer);
996 { create OpenGL texture object (delete exisiting object if exists) }
999 { setup texture parameters }
1000 procedure SetupParameters({$IFNDEF OPENGL_ES}out aBuildWithGlu: Boolean{$ENDIF});
1003 property Width: Integer read GetWidth; //< the actual width of the texture
1004 property Height: Integer read GetHeight; //< the actual height of the texture
1007 property ID: Cardinal read fID write SetID; //< name of the OpenGL texture object
1008 property Target: Cardinal read fTarget write SetTarget; //< texture target (e.g. GL_TEXTURE_2D)
1009 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree; //< delete texture object when this object is destroyed
1011 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap; //< mipmap type
1012 property Anisotropic: Integer read fAnisotropic write SetAnisotropic; //< anisotropic level
1014 property CustomData: Pointer read fCustomData write SetCustomData; //< user defined data (use at will)
1015 property CustomName: String read fCustomName write SetCustomName; //< user defined name (use at will)
1016 property CustomNameW: WideString read fCustomNameW write SetCustomNameW; //< user defined name (as WideString; use at will)
1018 property Dimension: TglBitmapSize read fDimension; //< size of the texture
1020 property IsResident: GLboolean read fIsResident; //< @true if OpenGL texture object has data, @false otherwise
1023 { this method is called after the constructor and sets the default values of this object }
1024 procedure AfterConstruction; override;
1026 { this method is called before the destructor and does some cleanup }
1027 procedure BeforeDestruction; override;
1031 { set the new value for texture border color
1032 @param aRed red color for border (0.0-1.0)
1033 @param aGreen green color for border (0.0-1.0)
1034 @param aBlue blue color for border (0.0-1.0)
1035 @param aAlpha alpha color for border (0.0-1.0) }
1036 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
1040 { set new texture filer
1041 @param aMin min filter
1042 @param aMag mag filter }
1043 procedure SetFilter(const aMin, aMag: GLenum);
1045 { set new texture wrapping
1046 @param S texture wrapping for x axis
1047 @param T texture wrapping for y axis
1048 @param R texture wrapping for z axis }
1050 const S: GLenum = GL_CLAMP_TO_EDGE;
1051 const T: GLenum = GL_CLAMP_TO_EDGE;
1052 const R: GLenum = GL_CLAMP_TO_EDGE);
1054 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
1056 @param r swizzle for red channel
1057 @param g swizzle for green channel
1058 @param b swizzle for blue channel
1059 @param a swizzle for alpha channel }
1060 procedure SetSwizzle(const r, g, b, a: GLenum);
1065 @param aEnableTextureUnit enable texture unit for this texture (e.g. glEnable(GL_TEXTURE_2D)) }
1066 procedure Bind({$IFNDEF OPENGL_ES}const aEnableTextureUnit: Boolean = true{$ENDIF}); virtual;
1069 @param aDisableTextureUnit disable texture unit for this texture (e.g. glEnable(GL_TEXTURE_2D)) }
1070 procedure Unbind({$IFNDEF OPENGL_ES}const aDisableTextureUnit: Boolean = true{$ENDIF}); virtual;
1072 { upload texture data from given data object to video card
1073 @param aData texture data object that contains the actual data
1074 @param aCheckSize check size before upload and throw exception if something is wrong }
1075 procedure UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean = true); virtual;
1078 { download texture data from video card and store it into given data object
1079 @returns @true when download was successfull, @false otherwise }
1080 function DownloadData(const aDataObj: TglBitmapData): Boolean; virtual;
1083 { constructor - creates an empty texture }
1084 constructor Create; overload;
1086 { constructor - creates an texture object and uploads the given data }
1087 constructor Create(const aData: TglBitmapData); overload;
1091 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1092 {$IF NOT DEFINED(OPENGL_ES)}
1093 { wrapper class for 1-dimensional textures (OpenGL target = GL_TEXTURE_1D
1094 all operations on a bitmap object must be done from the render thread }
1095 TglBitmap1D = class(TglBitmap)
1098 { upload the texture data to video card
1099 @param aDataObj texture data object that contains the actual data
1100 @param aBuildWithGlu use glu functions to build mipmaps }
1101 procedure UploadDataIntern(const aDataObj: TglBitmapData; const aBuildWithGlu: Boolean);
1104 property Width; //< actual with of the texture
1106 { this method is called after constructor and initializes the object }
1107 procedure AfterConstruction; override;
1109 { upload texture data from given data object to video card
1110 @param aData texture data object that contains the actual data
1111 @param aCheckSize check size before upload and throw exception if something is wrong }
1112 procedure UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean = true); override;
1117 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1118 { wrapper class for 2-dimensional textures (OpenGL target = GL_TEXTURE_2D)
1119 all operations on a bitmap object must be done from the render thread }
1120 TglBitmap2D = class(TglBitmap)
1123 { upload the texture data to video card
1124 @param aDataObj texture data object that contains the actual data
1125 @param aTarget target o upload data to (e.g. GL_TEXTURE_2D)
1126 @param aBuildWithGlu use glu functions to build mipmaps }
1127 procedure UploadDataIntern(const aDataObj: TglBitmapData; const aTarget: GLenum
1128 {$IFNDEF OPENGL_ES}; const aBuildWithGlu: Boolean{$ENDIF});
1131 property Width; //< actual width of the texture
1132 property Height; //< actual height of the texture
1134 { this method is called after constructor and initializes the object }
1135 procedure AfterConstruction; override;
1137 { upload texture data from given data object to video card
1138 @param aData texture data object that contains the actual data
1139 @param aCheckSize check size before upload and throw exception if something is wrong }
1140 procedure UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean = true); override;
1144 { copy a part of the frame buffer to the texture
1145 @param aTop topmost pixel to copy
1146 @param aLeft leftmost pixel to copy
1147 @param aRight rightmost pixel to copy
1148 @param aBottom bottommost pixel to copy
1149 @param aFormat format to store data in
1150 @param aDataObj texture data object to store the data in }
1151 class procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat; const aDataObj: TglBitmapData);
1155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1156 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
1157 { wrapper class for cube maps (OpenGL target = GL_TEXTURE_CUBE_MAP)
1158 all operations on a bitmap object must be done from the render thread }
1159 TglBitmapCubeMap = class(TglBitmap2D)
1162 fGenMode: Integer; //< generation mode for the cube map (e.g. GL_REFLECTION_MAP)
1166 { this method is called after constructor and initializes the object }
1167 procedure AfterConstruction; override;
1169 { upload texture data from given data object to video card
1170 @param aData texture data object that contains the actual data
1171 @param aCheckSize check size before upload and throw exception if something is wrong }
1172 procedure UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean = true); override;
1174 { upload texture data from given data object to video card
1175 @param aData texture data object that contains the actual data
1176 @param aCubeTarget cube map target to upload data to (e.g. GL_TEXTURE_CUBE_MAP_POSITIVE_X)
1177 @param aCheckSize check size before upload and throw exception if something is wrong }
1178 procedure UploadCubeMap(const aDataObj: TglBitmapData; const aCubeTarget: Cardinal; const aCheckSize: Boolean);
1181 @param aEnableTexCoordsGen enable cube map generator
1182 @param aEnableTextureUnit enable texture unit }
1183 procedure Bind({$IFNDEF OPENGL_ES}const aEnableTexCoordsGen: Boolean = true; const aEnableTextureUnit: Boolean = true{$ENDIF}); reintroduce; virtual;
1186 @param aDisableTexCoordsGen disable cube map generator
1187 @param aDisableTextureUnit disable texture unit }
1188 procedure Unbind({$IFNDEF OPENGL_ES}const aDisableTexCoordsGen: Boolean = true; const aDisableTextureUnit: Boolean = true{$ENDIF}); reintroduce; virtual;
1192 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
1193 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1194 { wrapper class for cube normal maps
1195 all operations on a bitmap object must be done from the render thread }
1196 TglBitmapNormalMap = class(TglBitmapCubeMap)
1198 { this method is called after constructor and initializes the object }
1199 procedure AfterConstruction; override;
1201 { create cube normal map from texture data and upload it to video card
1202 @param aSize size of each cube map texture
1203 @param aCheckSize check size before upload and throw exception if something is wrong }
1204 procedure GenerateNormalMap(const aSize: Integer = 32; const aCheckSize: Boolean = true);
1209 NULL_SIZE: TglBitmapSize = (Fields: []; X: 0; Y: 0);
1211 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1212 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1213 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1214 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1215 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1216 procedure glBitmapSetDefaultWrap(
1217 const S: Cardinal = GL_CLAMP_TO_EDGE;
1218 const T: Cardinal = GL_CLAMP_TO_EDGE;
1219 const R: Cardinal = GL_CLAMP_TO_EDGE);
1221 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
1222 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
1225 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1226 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1227 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1228 function glBitmapGetDefaultFormat: TglBitmapFormat;
1229 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1230 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1231 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
1232 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
1235 function glBitmapSize(X: Integer = -1; Y: Integer = -1): TglBitmapSize;
1236 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1237 function glBitmapRec4ub(const r, g, b, a: Byte): TglBitmapRec4ub;
1238 function glBitmapRec4ui(const r, g, b, a: Cardinal): TglBitmapRec4ui;
1239 function glBitmapRec4ul(const r, g, b, a: QWord): TglBitmapRec4ul;
1240 function glBitmapRec4ubCompare(const r1, r2: TglBitmapRec4ub): Boolean;
1241 function glBitmapRec4uiCompare(const r1, r2: TglBitmapRec4ui): Boolean;
1243 function glBitmapCreateTestData(const aFormat: TglBitmapFormat): TglBitmapData;
1246 function CreateGrayPalette: HPALETTE;
1252 Math, syncobjs, typinfo
1253 {$IF DEFINED(GLB_SUPPORT_JPEG_READ) AND DEFINED(GLB_LAZ_JPEG)}, FPReadJPEG{$IFEND};
1257 glBitmapDefaultDeleteTextureOnFree: Boolean;
1258 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1259 glBitmapDefaultFormat: TglBitmapFormat;
1260 glBitmapDefaultMipmap: TglBitmapMipMap;
1261 glBitmapDefaultFilterMin: Cardinal;
1262 glBitmapDefaultFilterMag: Cardinal;
1263 glBitmapDefaultWrapS: Cardinal;
1264 glBitmapDefaultWrapT: Cardinal;
1265 glBitmapDefaultWrapR: Cardinal;
1266 glDefaultSwizzle: array[0..3] of GLenum;
1268 ////////////////////////////////////////////////////////////////////////////////////////////////////
1270 TFormatDescriptor = class(TglBitmapFormatDescriptor)
1272 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1273 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1275 function CreateMappingData: Pointer; virtual;
1276 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1278 function IsEmpty: Boolean; virtual;
1279 function MaskMatch(const aMask: TglBitmapRec4ul): Boolean; virtual;
1281 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1283 constructor Create; virtual;
1285 class procedure Init;
1286 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1287 class function GetAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1288 class function GetFromMask(const aMask: TglBitmapRec4ul; const aBitCount: Integer = 0): TFormatDescriptor;
1289 class function GetFromPrecShift(const aPrec, aShift: TglBitmapRec4ub; const aBitCount: Integer): TFormatDescriptor;
1290 class procedure Clear;
1291 class procedure Finalize;
1293 TFormatDescriptorClass = class of TFormatDescriptor;
1295 TfdEmpty = class(TFormatDescriptor);
1297 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1298 TfdAlphaUB1 = class(TFormatDescriptor) //1* unsigned byte
1299 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1300 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1303 TfdLuminanceUB1 = class(TFormatDescriptor) //1* unsigned byte
1304 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1305 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1308 TfdUniversalUB1 = class(TFormatDescriptor) //1* unsigned byte
1309 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1310 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1313 TfdLuminanceAlphaUB2 = class(TfdLuminanceUB1) //2* unsigned byte
1314 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1315 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1318 TfdRGBub3 = class(TFormatDescriptor) //3* unsigned byte
1319 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1320 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1323 TfdBGRub3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1324 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1325 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1328 TfdRGBAub4 = class(TfdRGBub3) //3* unsigned byte
1329 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1330 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1333 TfdBGRAub4 = class(TfdBGRub3) //3* unsigned byte (inverse)
1334 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1335 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1338 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1339 TfdAlphaUS1 = class(TFormatDescriptor) //1* unsigned short
1340 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1341 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1344 TfdLuminanceUS1 = class(TFormatDescriptor) //1* unsigned short
1345 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1346 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1349 TfdUniversalUS1 = class(TFormatDescriptor) //1* unsigned short
1350 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1351 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1354 TfdDepthUS1 = class(TFormatDescriptor) //1* unsigned short
1355 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1356 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1359 TfdLuminanceAlphaUS2 = class(TfdLuminanceUS1) //2* unsigned short
1360 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1361 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1364 TfdRGBus3 = class(TFormatDescriptor) //3* unsigned short
1365 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1366 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1369 TfdBGRus3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1370 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1371 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1374 TfdRGBAus4 = class(TfdRGBus3) //4* unsigned short
1375 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1376 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1379 TfdARGBus4 = class(TfdRGBus3) //4* unsigned short
1380 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1381 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1384 TfdBGRAus4 = class(TfdBGRus3) //4* unsigned short (inverse)
1385 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1386 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1389 TfdABGRus4 = class(TfdBGRus3) //4* unsigned short (inverse)
1390 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1391 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1394 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1395 TfdUniversalUI1 = class(TFormatDescriptor) //1* unsigned int
1396 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1397 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1400 TfdDepthUI1 = class(TFormatDescriptor) //1* unsigned int
1401 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1402 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1405 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1406 TfdAlpha4ub1 = class(TfdAlphaUB1)
1407 procedure SetValues; override;
1410 TfdAlpha8ub1 = class(TfdAlphaUB1)
1411 procedure SetValues; override;
1414 TfdAlpha16us1 = class(TfdAlphaUS1)
1415 procedure SetValues; override;
1418 TfdLuminance4ub1 = class(TfdLuminanceUB1)
1419 procedure SetValues; override;
1422 TfdLuminance8ub1 = class(TfdLuminanceUB1)
1423 procedure SetValues; override;
1426 TfdLuminance16us1 = class(TfdLuminanceUS1)
1427 procedure SetValues; override;
1430 TfdLuminance4Alpha4ub2 = class(TfdLuminanceAlphaUB2)
1431 procedure SetValues; override;
1434 TfdLuminance6Alpha2ub2 = class(TfdLuminanceAlphaUB2)
1435 procedure SetValues; override;
1438 TfdLuminance8Alpha8ub2 = class(TfdLuminanceAlphaUB2)
1439 procedure SetValues; override;
1442 TfdLuminance12Alpha4us2 = class(TfdLuminanceAlphaUS2)
1443 procedure SetValues; override;
1446 TfdLuminance16Alpha16us2 = class(TfdLuminanceAlphaUS2)
1447 procedure SetValues; override;
1450 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1451 TfdR3G3B2ub1 = class(TfdUniversalUB1)
1452 procedure SetValues; override;
1455 TfdRGBX4us1 = class(TfdUniversalUS1)
1456 procedure SetValues; override;
1459 TfdXRGB4us1 = class(TfdUniversalUS1)
1460 procedure SetValues; override;
1463 TfdR5G6B5us1 = class(TfdUniversalUS1)
1464 procedure SetValues; override;
1467 TfdRGB5X1us1 = class(TfdUniversalUS1)
1468 procedure SetValues; override;
1471 TfdX1RGB5us1 = class(TfdUniversalUS1)
1472 procedure SetValues; override;
1475 TfdRGB8ub3 = class(TfdRGBub3)
1476 procedure SetValues; override;
1479 TfdRGBX8ui1 = class(TfdUniversalUI1)
1480 procedure SetValues; override;
1483 TfdXRGB8ui1 = class(TfdUniversalUI1)
1484 procedure SetValues; override;
1487 TfdRGB10X2ui1 = class(TfdUniversalUI1)
1488 procedure SetValues; override;
1491 TfdX2RGB10ui1 = class(TfdUniversalUI1)
1492 procedure SetValues; override;
1495 TfdRGB16us3 = class(TfdRGBus3)
1496 procedure SetValues; override;
1499 TfdRGBA4us1 = class(TfdUniversalUS1)
1500 procedure SetValues; override;
1503 TfdARGB4us1 = class(TfdUniversalUS1)
1504 procedure SetValues; override;
1507 TfdRGB5A1us1 = class(TfdUniversalUS1)
1508 procedure SetValues; override;
1511 TfdA1RGB5us1 = class(TfdUniversalUS1)
1512 procedure SetValues; override;
1515 TfdRGBA8ui1 = class(TfdUniversalUI1)
1516 procedure SetValues; override;
1519 TfdARGB8ui1 = class(TfdUniversalUI1)
1520 procedure SetValues; override;
1523 TfdRGBA8ub4 = class(TfdRGBAub4)
1524 procedure SetValues; override;
1527 TfdRGB10A2ui1 = class(TfdUniversalUI1)
1528 procedure SetValues; override;
1531 TfdA2RGB10ui1 = class(TfdUniversalUI1)
1532 procedure SetValues; override;
1535 TfdRGBA16us4 = class(TfdRGBAus4)
1536 procedure SetValues; override;
1539 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1540 TfdBGRX4us1 = class(TfdUniversalUS1)
1541 procedure SetValues; override;
1544 TfdXBGR4us1 = class(TfdUniversalUS1)
1545 procedure SetValues; override;
1548 TfdB5G6R5us1 = class(TfdUniversalUS1)
1549 procedure SetValues; override;
1552 TfdBGR5X1us1 = class(TfdUniversalUS1)
1553 procedure SetValues; override;
1556 TfdX1BGR5us1 = class(TfdUniversalUS1)
1557 procedure SetValues; override;
1560 TfdBGR8ub3 = class(TfdBGRub3)
1561 procedure SetValues; override;
1564 TfdBGRX8ui1 = class(TfdUniversalUI1)
1565 procedure SetValues; override;
1568 TfdXBGR8ui1 = class(TfdUniversalUI1)
1569 procedure SetValues; override;
1572 TfdBGR10X2ui1 = class(TfdUniversalUI1)
1573 procedure SetValues; override;
1576 TfdX2BGR10ui1 = class(TfdUniversalUI1)
1577 procedure SetValues; override;
1580 TfdBGR16us3 = class(TfdBGRus3)
1581 procedure SetValues; override;
1584 TfdBGRA4us1 = class(TfdUniversalUS1)
1585 procedure SetValues; override;
1588 TfdABGR4us1 = class(TfdUniversalUS1)
1589 procedure SetValues; override;
1592 TfdBGR5A1us1 = class(TfdUniversalUS1)
1593 procedure SetValues; override;
1596 TfdA1BGR5us1 = class(TfdUniversalUS1)
1597 procedure SetValues; override;
1600 TfdBGRA8ui1 = class(TfdUniversalUI1)
1601 procedure SetValues; override;
1604 TfdABGR8ui1 = class(TfdUniversalUI1)
1605 procedure SetValues; override;
1608 TfdBGRA8ub4 = class(TfdBGRAub4)
1609 procedure SetValues; override;
1612 TfdBGR10A2ui1 = class(TfdUniversalUI1)
1613 procedure SetValues; override;
1616 TfdA2BGR10ui1 = class(TfdUniversalUI1)
1617 procedure SetValues; override;
1620 TfdBGRA16us4 = class(TfdBGRAus4)
1621 procedure SetValues; override;
1624 TfdDepth16us1 = class(TfdDepthUS1)
1625 procedure SetValues; override;
1628 TfdDepth24ui1 = class(TfdDepthUI1)
1629 procedure SetValues; override;
1632 TfdDepth32ui1 = class(TfdDepthUI1)
1633 procedure SetValues; override;
1636 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1637 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1638 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1639 procedure SetValues; override;
1642 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1643 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1644 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1645 procedure SetValues; override;
1648 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1649 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1650 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1651 procedure SetValues; override;
1654 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1655 TbmpBitfieldFormat = class(TFormatDescriptor)
1657 procedure SetCustomValues(const aBPP: Integer; aMask: TglBitmapRec4ul); overload;
1658 procedure SetCustomValues(const aBBP: Integer; const aPrec, aShift: TglBitmapRec4ub); overload;
1659 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1660 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1663 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1664 TbmpColorTableEnty = packed record
1667 TbmpColorTable = array of TbmpColorTableEnty;
1668 TbmpColorTableFormat = class(TFormatDescriptor)
1670 fColorTable: TbmpColorTable;
1672 procedure SetValues; override;
1674 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1676 procedure SetCustomValues(const aFormat: TglBitmapFormat; const aBPP: Integer; const aPrec, aShift: TglBitmapRec4ub); overload;
1677 procedure CalcValues;
1678 procedure CreateColorTable;
1680 function CreateMappingData: Pointer; override;
1681 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1682 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1683 destructor Destroy; override;
1687 LUMINANCE_WEIGHT_R = 0.30;
1688 LUMINANCE_WEIGHT_G = 0.59;
1689 LUMINANCE_WEIGHT_B = 0.11;
1691 ALPHA_WEIGHT_R = 0.30;
1692 ALPHA_WEIGHT_G = 0.59;
1693 ALPHA_WEIGHT_B = 0.11;
1695 DEPTH_WEIGHT_R = 0.333333333;
1696 DEPTH_WEIGHT_G = 0.333333333;
1697 DEPTH_WEIGHT_B = 0.333333333;
1699 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1710 TfdLuminance4Alpha4ub2,
1711 TfdLuminance6Alpha2ub2,
1712 TfdLuminance8Alpha8ub2,
1713 TfdLuminance12Alpha4us2,
1714 TfdLuminance16Alpha16us2,
1773 FormatDescriptorCS: TCriticalSection;
1774 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1776 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1777 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1779 inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1782 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1783 constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat);
1785 inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1788 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1789 function glBitmapSize(X: Integer; Y: Integer): TglBitmapSize;
1791 result.Fields := [];
1793 result.Fields := result.Fields + [ffX];
1795 result.Fields := result.Fields + [ffY];
1796 result.X := Max(0, X);
1797 result.Y := Max(0, Y);
1800 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1801 function glBitmapPosition(X: Integer; Y: Integer): TglBitmapPixelPosition;
1803 result := glBitmapSize(X, Y);
1806 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1807 function glBitmapRec4ub(const r, g, b, a: Byte): TglBitmapRec4ub;
1815 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1816 function glBitmapRec4ui(const r, g, b, a: Cardinal): TglBitmapRec4ui;
1824 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1825 function glBitmapRec4ul(const r, g, b, a: QWord): TglBitmapRec4ul;
1833 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1834 function glBitmapRec4ubCompare(const r1, r2: TglBitmapRec4ub): Boolean;
1839 for i := 0 to high(r1.arr) do
1840 if (r1.arr[i] <> r2.arr[i]) then
1845 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1846 function glBitmapRec4uiCompare(const r1, r2: TglBitmapRec4ui): Boolean;
1851 for i := 0 to high(r1.arr) do
1852 if (r1.arr[i] <> r2.arr[i]) then
1857 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1858 function glBitmapCreateTestData(const aFormat: TglBitmapFormat): TglBitmapData;
1860 desc: TFormatDescriptor;
1864 px: TglBitmapPixelData;
1867 desc := TFormatDescriptor.Get(aFormat);
1868 if (desc.IsCompressed) or (desc.glFormat = 0) then
1871 p := GetMemory(ceil(25 * desc.BytesPerPixel)); // 5 x 5 pixel
1872 md := desc.CreateMappingData;
1875 desc.PreparePixel(px);
1877 for x := 0 to 4 do begin
1878 px.Data := glBitmapRec4ui(0, 0, 0, 0);
1879 for i := 0 to 3 do begin
1880 if ((y < 3) and (y = i)) or
1881 ((y = 3) and (i < 3)) or
1882 ((y = 4) and (i = 3))
1884 px.Data.arr[i] := Trunc(px.Range.arr[i] / 4 * x)
1885 else if ((y < 4) and (i = 3)) or
1886 ((y = 4) and (i < 3))
1888 px.Data.arr[i] := px.Range.arr[i]
1890 px.Data.arr[i] := 0; //px.Range.arr[i];
1892 desc.Map(px, tmp, md);
1895 desc.FreeMappingData(md);
1898 result := TglBitmapData.Create(glBitmapPosition(5, 5), aFormat, p);
1901 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1902 function glBitmapShiftRec(const r, g, b, a: Byte): TglBitmapRec4ub;
1910 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1911 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1917 tfAlpha4ub1, tfAlpha8ub1,
1918 tfLuminance4ub1, tfLuminance8ub1, tfR3G3B2ub1,
1921 tfLuminance4Alpha4ub2, tfLuminance6Alpha2ub2, tfLuminance8Alpha8ub2,
1922 tfRGBX4us1, tfXRGB4us1, tfRGB5X1us1, tfX1RGB5us1, tfR5G6B5us1, tfRGB5A1us1, tfA1RGB5us1, tfRGBA4us1, tfARGB4us1,
1923 tfBGRX4us1, tfXBGR4us1, tfBGR5X1us1, tfX1BGR5us1, tfB5G6R5us1, tfBGR5A1us1, tfA1BGR5us1, tfBGRA4us1, tfABGR4us1,
1926 tfBGR8ub3, tfRGB8ub3,
1929 tfRGBX8ui1, tfXRGB8ui1, tfRGB10X2ui1, tfX2RGB10ui1, tfRGBA8ui1, tfARGB8ui1, tfRGBA8ub4, tfRGB10A2ui1, tfA2RGB10ui1,
1930 tfBGRX8ui1, tfXBGR8ui1, tfBGR10X2ui1, tfX2BGR10ui1, tfBGRA8ui1, tfABGR8ui1, tfBGRA8ub4, tfBGR10A2ui1, tfA2BGR10ui1])
1932 result := result + [ ftBMP ];
1936 tfAlpha4ub1, tfAlpha8ub1, tfLuminance4ub1, tfLuminance8ub1,
1939 tfAlpha16us1, tfLuminance16us1,
1940 tfLuminance4Alpha4ub2, tfLuminance6Alpha2ub2, tfLuminance8Alpha8ub2,
1941 tfX1RGB5us1, tfARGB4us1, tfA1RGB5us1, tfDepth16us1,
1947 tfX2RGB10ui1, tfARGB8ui1, tfBGRA8ub4, tfA2RGB10ui1,
1948 tfDepth24ui1, tfDepth32ui1])
1950 result := result + [ftTGA];
1952 if not (aFormat in [tfEmpty, tfRGB16us3, tfBGR16us3]) then
1953 result := result + [ftDDS];
1955 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1957 tfAlpha8ub1, tfLuminance8ub1, tfLuminance8Alpha8ub2,
1958 tfRGB8ub3, tfRGBA8ui1,
1959 tfBGR8ub3, tfBGRA8ui1] then
1960 result := result + [ftPNG];
1963 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1964 if aFormat in [tfAlpha8ub1, tfLuminance8ub1, tfRGB8ub3, tfBGR8ub3] then
1965 result := result + [ftJPEG];
1969 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1970 function IsPowerOfTwo(aNumber: Integer): Boolean;
1972 while (aNumber and 1) = 0 do
1973 aNumber := aNumber shr 1;
1974 result := aNumber = 1;
1977 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1978 function GetTopMostBit(aBitSet: QWord): Integer;
1981 while aBitSet > 0 do begin
1983 aBitSet := aBitSet shr 1;
1987 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1988 function CountSetBits(aBitSet: QWord): Integer;
1991 while aBitSet > 0 do begin
1992 if (aBitSet and 1) = 1 then
1994 aBitSet := aBitSet shr 1;
1998 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1999 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
2002 LUMINANCE_WEIGHT_R * aPixel.Data.r +
2003 LUMINANCE_WEIGHT_G * aPixel.Data.g +
2004 LUMINANCE_WEIGHT_B * aPixel.Data.b);
2007 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2008 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
2011 DEPTH_WEIGHT_R * aPixel.Data.r +
2012 DEPTH_WEIGHT_G * aPixel.Data.g +
2013 DEPTH_WEIGHT_B * aPixel.Data.b);
2016 {$IFDEF GLB_SDL_IMAGE}
2017 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2018 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2019 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2020 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2022 result := TStream(context^.unknown.data1).Seek(offset, whence);
2025 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2027 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2030 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2032 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2035 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2040 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2042 result := SDL_AllocRW;
2044 if result = nil then
2045 raise EglBitmap.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2047 result^.seek := glBitmapRWseek;
2048 result^.read := glBitmapRWread;
2049 result^.write := glBitmapRWwrite;
2050 result^.close := glBitmapRWclose;
2051 result^.unknown.data1 := Stream;
2055 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2056 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2058 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2061 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2062 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2064 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2067 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2068 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2070 glBitmapDefaultMipmap := aValue;
2073 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2074 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2076 glBitmapDefaultFormat := aFormat;
2079 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2080 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2082 glBitmapDefaultFilterMin := aMin;
2083 glBitmapDefaultFilterMag := aMag;
2086 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2087 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2089 glBitmapDefaultWrapS := S;
2090 glBitmapDefaultWrapT := T;
2091 glBitmapDefaultWrapR := R;
2094 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2095 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
2096 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
2098 glDefaultSwizzle[0] := r;
2099 glDefaultSwizzle[1] := g;
2100 glDefaultSwizzle[2] := b;
2101 glDefaultSwizzle[3] := a;
2105 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2106 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2108 result := glBitmapDefaultDeleteTextureOnFree;
2111 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2112 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2114 result := glBitmapDefaultFreeDataAfterGenTextures;
2117 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2118 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2120 result := glBitmapDefaultMipmap;
2123 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2124 function glBitmapGetDefaultFormat: TglBitmapFormat;
2126 result := glBitmapDefaultFormat;
2129 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2130 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
2132 aMin := glBitmapDefaultFilterMin;
2133 aMag := glBitmapDefaultFilterMag;
2136 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2137 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
2139 S := glBitmapDefaultWrapS;
2140 T := glBitmapDefaultWrapT;
2141 R := glBitmapDefaultWrapR;
2144 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
2145 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2146 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
2148 r := glDefaultSwizzle[0];
2149 g := glDefaultSwizzle[1];
2150 b := glDefaultSwizzle[2];
2151 a := glDefaultSwizzle[3];
2155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2156 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2157 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2158 function TFormatDescriptor.CreateMappingData: Pointer;
2163 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2164 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2169 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2170 function TFormatDescriptor.IsEmpty: Boolean;
2172 result := (fFormat = tfEmpty);
2175 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2176 function TFormatDescriptor.MaskMatch(const aMask: TglBitmapRec4ul): Boolean;
2182 if (aMask.r = 0) and (aMask.g = 0) and (aMask.b = 0) and (aMask.a = 0) then
2183 raise EglBitmap.Create('FormatCheckFormat - All Masks are 0');
2186 if (aMask.arr[i] <> m.arr[i]) then
2191 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2192 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2194 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2195 aPixel.Data := Range;
2196 aPixel.Format := fFormat;
2197 aPixel.Range := Range;
2200 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2201 constructor TFormatDescriptor.Create;
2206 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2207 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2208 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2209 procedure TfdAlphaUB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2211 aData^ := aPixel.Data.a;
2215 procedure TfdAlphaUB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2220 aPixel.Data.a := aData^;
2224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2225 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2227 procedure TfdLuminanceUB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2229 aData^ := LuminanceWeight(aPixel);
2233 procedure TfdLuminanceUB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2235 aPixel.Data.r := aData^;
2236 aPixel.Data.g := aData^;
2237 aPixel.Data.b := aData^;
2242 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2243 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2244 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2245 procedure TfdUniversalUB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2251 if (Range.arr[i] > 0) then
2252 aData^ := aData^ or ((aPixel.Data.arr[i] and Range.arr[i]) shl fShift.arr[i]);
2256 procedure TfdUniversalUB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2261 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and Range.arr[i];
2265 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2266 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2267 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2268 procedure TfdLuminanceAlphaUB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2270 inherited Map(aPixel, aData, aMapData);
2271 aData^ := aPixel.Data.a;
2275 procedure TfdLuminanceAlphaUB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2277 inherited Unmap(aData, aPixel, aMapData);
2278 aPixel.Data.a := aData^;
2282 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2283 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2284 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2285 procedure TfdRGBub3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2287 aData^ := aPixel.Data.r;
2289 aData^ := aPixel.Data.g;
2291 aData^ := aPixel.Data.b;
2295 procedure TfdRGBub3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2297 aPixel.Data.r := aData^;
2299 aPixel.Data.g := aData^;
2301 aPixel.Data.b := aData^;
2306 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2307 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2308 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2309 procedure TfdBGRub3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2311 aData^ := aPixel.Data.b;
2313 aData^ := aPixel.Data.g;
2315 aData^ := aPixel.Data.r;
2319 procedure TfdBGRub3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2321 aPixel.Data.b := aData^;
2323 aPixel.Data.g := aData^;
2325 aPixel.Data.r := aData^;
2330 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2331 //TfdRGBA_UB4//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2332 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2333 procedure TfdRGBAub4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2335 inherited Map(aPixel, aData, aMapData);
2336 aData^ := aPixel.Data.a;
2340 procedure TfdRGBAub4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2342 inherited Unmap(aData, aPixel, aMapData);
2343 aPixel.Data.a := aData^;
2347 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2348 //TfdBGRA_UB4//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2349 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2350 procedure TfdBGRAub4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2352 inherited Map(aPixel, aData, aMapData);
2353 aData^ := aPixel.Data.a;
2357 procedure TfdBGRAub4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2359 inherited Unmap(aData, aPixel, aMapData);
2360 aPixel.Data.a := aData^;
2364 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2365 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2366 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2367 procedure TfdAlphaUS1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2369 PWord(aData)^ := aPixel.Data.a;
2373 procedure TfdAlphaUS1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2378 aPixel.Data.a := PWord(aData)^;
2382 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2383 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2384 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2385 procedure TfdLuminanceUS1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2387 PWord(aData)^ := LuminanceWeight(aPixel);
2391 procedure TfdLuminanceUS1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2393 aPixel.Data.r := PWord(aData)^;
2394 aPixel.Data.g := PWord(aData)^;
2395 aPixel.Data.b := PWord(aData)^;
2400 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2401 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2402 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2403 procedure TfdUniversalUS1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2409 if (Range.arr[i] > 0) then
2410 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and Range.arr[i]) shl fShift.arr[i]);
2414 procedure TfdUniversalUS1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2419 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and Range.arr[i];
2423 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2424 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2426 procedure TfdDepthUS1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2428 PWord(aData)^ := DepthWeight(aPixel);
2432 procedure TfdDepthUS1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2434 aPixel.Data.r := PWord(aData)^;
2435 aPixel.Data.g := PWord(aData)^;
2436 aPixel.Data.b := PWord(aData)^;
2437 aPixel.Data.a := PWord(aData)^;;
2441 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2442 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2443 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2444 procedure TfdLuminanceAlphaUS2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2446 inherited Map(aPixel, aData, aMapData);
2447 PWord(aData)^ := aPixel.Data.a;
2451 procedure TfdLuminanceAlphaUS2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2453 inherited Unmap(aData, aPixel, aMapData);
2454 aPixel.Data.a := PWord(aData)^;
2458 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2459 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2460 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2461 procedure TfdRGBus3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2463 PWord(aData)^ := aPixel.Data.r;
2465 PWord(aData)^ := aPixel.Data.g;
2467 PWord(aData)^ := aPixel.Data.b;
2471 procedure TfdRGBus3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2473 aPixel.Data.r := PWord(aData)^;
2475 aPixel.Data.g := PWord(aData)^;
2477 aPixel.Data.b := PWord(aData)^;
2482 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2483 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2485 procedure TfdBGRus3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2487 PWord(aData)^ := aPixel.Data.b;
2489 PWord(aData)^ := aPixel.Data.g;
2491 PWord(aData)^ := aPixel.Data.r;
2495 procedure TfdBGRus3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2497 aPixel.Data.b := PWord(aData)^;
2499 aPixel.Data.g := PWord(aData)^;
2501 aPixel.Data.r := PWord(aData)^;
2506 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2507 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2508 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2509 procedure TfdRGBAus4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2511 inherited Map(aPixel, aData, aMapData);
2512 PWord(aData)^ := aPixel.Data.a;
2516 procedure TfdRGBAus4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2518 inherited Unmap(aData, aPixel, aMapData);
2519 aPixel.Data.a := PWord(aData)^;
2523 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2524 //TfdARGB_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2525 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2526 procedure TfdARGBus4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2528 PWord(aData)^ := aPixel.Data.a;
2530 inherited Map(aPixel, aData, aMapData);
2533 procedure TfdARGBus4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2535 aPixel.Data.a := PWord(aData)^;
2537 inherited Unmap(aData, aPixel, aMapData);
2540 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2541 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2542 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2543 procedure TfdBGRAus4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2545 inherited Map(aPixel, aData, aMapData);
2546 PWord(aData)^ := aPixel.Data.a;
2550 procedure TfdBGRAus4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2552 inherited Unmap(aData, aPixel, aMapData);
2553 aPixel.Data.a := PWord(aData)^;
2557 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2558 //TfdABGR_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2559 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2560 procedure TfdABGRus4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2562 PWord(aData)^ := aPixel.Data.a;
2564 inherited Map(aPixel, aData, aMapData);
2567 procedure TfdABGRus4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2569 aPixel.Data.a := PWord(aData)^;
2571 inherited Unmap(aData, aPixel, aMapData);
2574 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2575 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2576 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2577 procedure TfdUniversalUI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2581 PCardinal(aData)^ := 0;
2583 if (Range.arr[i] > 0) then
2584 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and Range.arr[i]) shl fShift.arr[i]);
2588 procedure TfdUniversalUI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2593 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and Range.arr[i];
2597 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2598 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2599 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2600 procedure TfdDepthUI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2602 PCardinal(aData)^ := DepthWeight(aPixel);
2606 procedure TfdDepthUI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2608 aPixel.Data.r := PCardinal(aData)^;
2609 aPixel.Data.g := PCardinal(aData)^;
2610 aPixel.Data.b := PCardinal(aData)^;
2611 aPixel.Data.a := PCardinal(aData)^;
2615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2616 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2617 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2618 procedure TfdAlpha4ub1.SetValues;
2620 inherited SetValues;
2622 fFormat := tfAlpha4ub1;
2623 fWithAlpha := tfAlpha4ub1;
2624 fPrecision := glBitmapRec4ub(0, 0, 0, 8);
2625 fShift := glBitmapRec4ub(0, 0, 0, 0);
2627 fOpenGLFormat := tfAlpha4ub1;
2628 fglFormat := GL_ALPHA;
2629 fglInternalFormat := GL_ALPHA4;
2630 fglDataFormat := GL_UNSIGNED_BYTE;
2632 fOpenGLFormat := tfAlpha8ub1;
2636 procedure TfdAlpha8ub1.SetValues;
2638 inherited SetValues;
2640 fFormat := tfAlpha8ub1;
2641 fWithAlpha := tfAlpha8ub1;
2642 fPrecision := glBitmapRec4ub(0, 0, 0, 8);
2643 fShift := glBitmapRec4ub(0, 0, 0, 0);
2644 fOpenGLFormat := tfAlpha8ub1;
2645 fglFormat := GL_ALPHA;
2646 fglInternalFormat := {$IFNDEF OPENGL_ES}GL_ALPHA8{$ELSE}GL_ALPHA{$ENDIF};
2647 fglDataFormat := GL_UNSIGNED_BYTE;
2650 procedure TfdAlpha16us1.SetValues;
2652 inherited SetValues;
2653 fBitsPerPixel := 16;
2654 fFormat := tfAlpha16us1;
2655 fWithAlpha := tfAlpha16us1;
2656 fPrecision := glBitmapRec4ub(0, 0, 0, 16);
2657 fShift := glBitmapRec4ub(0, 0, 0, 0);
2659 fOpenGLFormat := tfAlpha16us1;
2660 fglFormat := GL_ALPHA;
2661 fglInternalFormat := GL_ALPHA16;
2662 fglDataFormat := GL_UNSIGNED_SHORT;
2664 fOpenGLFormat := tfAlpha8ub1;
2668 procedure TfdLuminance4ub1.SetValues;
2670 inherited SetValues;
2672 fFormat := tfLuminance4ub1;
2673 fWithAlpha := tfLuminance4Alpha4ub2;
2674 fWithoutAlpha := tfLuminance4ub1;
2675 fPrecision := glBitmapRec4ub(8, 8, 8, 0);
2676 fShift := glBitmapRec4ub(0, 0, 0, 0);
2678 fOpenGLFormat := tfLuminance4ub1;
2679 fglFormat := GL_LUMINANCE;
2680 fglInternalFormat := GL_LUMINANCE4;
2681 fglDataFormat := GL_UNSIGNED_BYTE;
2683 fOpenGLFormat := tfLuminance8ub1;
2687 procedure TfdLuminance8ub1.SetValues;
2689 inherited SetValues;
2691 fFormat := tfLuminance8ub1;
2692 fWithAlpha := tfLuminance8Alpha8ub2;
2693 fWithoutAlpha := tfLuminance8ub1;
2694 fOpenGLFormat := tfLuminance8ub1;
2695 fPrecision := glBitmapRec4ub(8, 8, 8, 0);
2696 fShift := glBitmapRec4ub(0, 0, 0, 0);
2697 fglFormat := GL_LUMINANCE;
2698 fglInternalFormat := {$IFNDEF OPENGL_ES}GL_LUMINANCE8{$ELSE}GL_LUMINANCE{$ENDIF};
2699 fglDataFormat := GL_UNSIGNED_BYTE;
2702 procedure TfdLuminance16us1.SetValues;
2704 inherited SetValues;
2705 fBitsPerPixel := 16;
2706 fFormat := tfLuminance16us1;
2707 fWithAlpha := tfLuminance16Alpha16us2;
2708 fWithoutAlpha := tfLuminance16us1;
2709 fPrecision := glBitmapRec4ub(16, 16, 16, 0);
2710 fShift := glBitmapRec4ub( 0, 0, 0, 0);
2712 fOpenGLFormat := tfLuminance16us1;
2713 fglFormat := GL_LUMINANCE;
2714 fglInternalFormat := GL_LUMINANCE16;
2715 fglDataFormat := GL_UNSIGNED_SHORT;
2717 fOpenGLFormat := tfLuminance8ub1;
2721 procedure TfdLuminance4Alpha4ub2.SetValues;
2723 inherited SetValues;
2724 fBitsPerPixel := 16;
2725 fFormat := tfLuminance4Alpha4ub2;
2726 fWithAlpha := tfLuminance4Alpha4ub2;
2727 fWithoutAlpha := tfLuminance4ub1;
2728 fPrecision := glBitmapRec4ub(8, 8, 8, 8);
2729 fShift := glBitmapRec4ub(0, 0, 0, 8);
2731 fOpenGLFormat := tfLuminance4Alpha4ub2;
2732 fglFormat := GL_LUMINANCE_ALPHA;
2733 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
2734 fglDataFormat := GL_UNSIGNED_BYTE;
2736 fOpenGLFormat := tfLuminance8Alpha8ub2;
2740 procedure TfdLuminance6Alpha2ub2.SetValues;
2742 inherited SetValues;
2743 fBitsPerPixel := 16;
2744 fFormat := tfLuminance6Alpha2ub2;
2745 fWithAlpha := tfLuminance6Alpha2ub2;
2746 fWithoutAlpha := tfLuminance8ub1;
2747 fPrecision := glBitmapRec4ub(8, 8, 8, 8);
2748 fShift := glBitmapRec4ub(0, 0, 0, 8);
2750 fOpenGLFormat := tfLuminance6Alpha2ub2;
2751 fglFormat := GL_LUMINANCE_ALPHA;
2752 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
2753 fglDataFormat := GL_UNSIGNED_BYTE;
2755 fOpenGLFormat := tfLuminance8Alpha8ub2;
2759 procedure TfdLuminance8Alpha8ub2.SetValues;
2761 inherited SetValues;
2762 fBitsPerPixel := 16;
2763 fFormat := tfLuminance8Alpha8ub2;
2764 fWithAlpha := tfLuminance8Alpha8ub2;
2765 fWithoutAlpha := tfLuminance8ub1;
2766 fOpenGLFormat := tfLuminance8Alpha8ub2;
2767 fPrecision := glBitmapRec4ub(8, 8, 8, 8);
2768 fShift := glBitmapRec4ub(0, 0, 0, 8);
2769 fglFormat := GL_LUMINANCE_ALPHA;
2770 fglInternalFormat := {$IFNDEF OPENGL_ES}GL_LUMINANCE8_ALPHA8{$ELSE}GL_LUMINANCE_ALPHA{$ENDIF};
2771 fglDataFormat := GL_UNSIGNED_BYTE;
2774 procedure TfdLuminance12Alpha4us2.SetValues;
2776 inherited SetValues;
2777 fBitsPerPixel := 32;
2778 fFormat := tfLuminance12Alpha4us2;
2779 fWithAlpha := tfLuminance12Alpha4us2;
2780 fWithoutAlpha := tfLuminance16us1;
2781 fPrecision := glBitmapRec4ub(16, 16, 16, 16);
2782 fShift := glBitmapRec4ub( 0, 0, 0, 16);
2784 fOpenGLFormat := tfLuminance12Alpha4us2;
2785 fglFormat := GL_LUMINANCE_ALPHA;
2786 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
2787 fglDataFormat := GL_UNSIGNED_SHORT;
2789 fOpenGLFormat := tfLuminance8Alpha8ub2;
2793 procedure TfdLuminance16Alpha16us2.SetValues;
2795 inherited SetValues;
2796 fBitsPerPixel := 32;
2797 fFormat := tfLuminance16Alpha16us2;
2798 fWithAlpha := tfLuminance16Alpha16us2;
2799 fWithoutAlpha := tfLuminance16us1;
2800 fPrecision := glBitmapRec4ub(16, 16, 16, 16);
2801 fShift := glBitmapRec4ub( 0, 0, 0, 16);
2803 fOpenGLFormat := tfLuminance16Alpha16us2;
2804 fglFormat := GL_LUMINANCE_ALPHA;
2805 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
2806 fglDataFormat := GL_UNSIGNED_SHORT;
2808 fOpenGLFormat := tfLuminance8Alpha8ub2;
2812 procedure TfdR3G3B2ub1.SetValues;
2814 inherited SetValues;
2816 fFormat := tfR3G3B2ub1;
2817 fWithAlpha := tfRGBA4us1;
2818 fWithoutAlpha := tfR3G3B2ub1;
2819 fRGBInverted := tfEmpty;
2820 fPrecision := glBitmapRec4ub(3, 3, 2, 0);
2821 fShift := glBitmapRec4ub(5, 2, 0, 0);
2823 fOpenGLFormat := tfR3G3B2ub1;
2824 fglFormat := GL_RGB;
2825 fglInternalFormat := GL_R3_G3_B2;
2826 fglDataFormat := GL_UNSIGNED_BYTE_3_3_2;
2828 fOpenGLFormat := tfR5G6B5us1;
2832 procedure TfdRGBX4us1.SetValues;
2834 inherited SetValues;
2835 fBitsPerPixel := 16;
2836 fFormat := tfRGBX4us1;
2837 fWithAlpha := tfRGBA4us1;
2838 fWithoutAlpha := tfRGBX4us1;
2839 fRGBInverted := tfBGRX4us1;
2840 fPrecision := glBitmapRec4ub( 4, 4, 4, 0);
2841 fShift := glBitmapRec4ub(12, 8, 4, 0);
2843 fOpenGLFormat := tfRGBX4us1;
2844 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
2845 fglInternalFormat := GL_RGB4;
2846 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4;
2848 fOpenGLFormat := tfR5G6B5us1;
2852 procedure TfdXRGB4us1.SetValues;
2854 inherited SetValues;
2855 fBitsPerPixel := 16;
2856 fFormat := tfXRGB4us1;
2857 fWithAlpha := tfARGB4us1;
2858 fWithoutAlpha := tfXRGB4us1;
2859 fRGBInverted := tfXBGR4us1;
2860 fPrecision := glBitmapRec4ub(4, 4, 4, 0);
2861 fShift := glBitmapRec4ub(8, 4, 0, 0);
2863 fOpenGLFormat := tfXRGB4us1;
2864 fglFormat := GL_BGRA;
2865 fglInternalFormat := GL_RGB4;
2866 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
2868 fOpenGLFormat := tfR5G6B5us1;
2872 procedure TfdR5G6B5us1.SetValues;
2874 inherited SetValues;
2875 fBitsPerPixel := 16;
2876 fFormat := tfR5G6B5us1;
2877 fWithAlpha := tfRGB5A1us1;
2878 fWithoutAlpha := tfR5G6B5us1;
2879 fRGBInverted := tfB5G6R5us1;
2880 fPrecision := glBitmapRec4ub( 5, 6, 5, 0);
2881 fShift := glBitmapRec4ub(11, 5, 0, 0);
2882 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
2883 fOpenGLFormat := tfR5G6B5us1;
2884 fglFormat := GL_RGB;
2885 fglInternalFormat := GL_RGB565;
2886 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
2888 fOpenGLFormat := tfRGB8ub3;
2892 procedure TfdRGB5X1us1.SetValues;
2894 inherited SetValues;
2895 fBitsPerPixel := 16;
2896 fFormat := tfRGB5X1us1;
2897 fWithAlpha := tfRGB5A1us1;
2898 fWithoutAlpha := tfRGB5X1us1;
2899 fRGBInverted := tfBGR5X1us1;
2900 fPrecision := glBitmapRec4ub( 5, 5, 5, 0);
2901 fShift := glBitmapRec4ub(11, 6, 1, 0);
2903 fOpenGLFormat := tfRGB5X1us1;
2904 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
2905 fglInternalFormat := GL_RGB5;
2906 fglDataFormat := GL_UNSIGNED_SHORT_5_5_5_1;
2908 fOpenGLFormat := tfR5G6B5us1;
2912 procedure TfdX1RGB5us1.SetValues;
2914 inherited SetValues;
2915 fBitsPerPixel := 16;
2916 fFormat := tfX1RGB5us1;
2917 fWithAlpha := tfA1RGB5us1;
2918 fWithoutAlpha := tfX1RGB5us1;
2919 fRGBInverted := tfX1BGR5us1;
2920 fPrecision := glBitmapRec4ub( 5, 5, 5, 0);
2921 fShift := glBitmapRec4ub(10, 5, 0, 0);
2923 fOpenGLFormat := tfX1RGB5us1;
2924 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
2925 fglInternalFormat := GL_RGB5;
2926 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
2928 fOpenGLFormat := tfR5G6B5us1;
2932 procedure TfdRGB8ub3.SetValues;
2934 inherited SetValues;
2935 fBitsPerPixel := 24;
2936 fFormat := tfRGB8ub3;
2937 fWithAlpha := tfRGBA8ub4;
2938 fWithoutAlpha := tfRGB8ub3;
2939 fRGBInverted := tfBGR8ub3;
2940 fPrecision := glBitmapRec4ub(8, 8, 8, 0);
2941 fShift := glBitmapRec4ub(0, 8, 16, 0);
2942 fOpenGLFormat := tfRGB8ub3;
2943 fglFormat := GL_RGB;
2944 fglInternalFormat := {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}GL_RGB8{$ELSE}GL_RGB{$IFEND};
2945 fglDataFormat := GL_UNSIGNED_BYTE;
2948 procedure TfdRGBX8ui1.SetValues;
2950 inherited SetValues;
2951 fBitsPerPixel := 32;
2952 fFormat := tfRGBX8ui1;
2953 fWithAlpha := tfRGBA8ui1;
2954 fWithoutAlpha := tfRGBX8ui1;
2955 fRGBInverted := tfBGRX8ui1;
2956 fPrecision := glBitmapRec4ub( 8, 8, 8, 0);
2957 fShift := glBitmapRec4ub(24, 16, 8, 0);
2959 fOpenGLFormat := tfRGBX8ui1;
2960 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
2961 fglInternalFormat := GL_RGB8;
2962 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8;
2964 fOpenGLFormat := tfRGB8ub3;
2968 procedure TfdXRGB8ui1.SetValues;
2970 inherited SetValues;
2971 fBitsPerPixel := 32;
2972 fFormat := tfXRGB8ui1;
2973 fWithAlpha := tfXRGB8ui1;
2974 fWithoutAlpha := tfXRGB8ui1;
2975 fOpenGLFormat := tfXRGB8ui1;
2976 fRGBInverted := tfXBGR8ui1;
2977 fPrecision := glBitmapRec4ub( 8, 8, 8, 0);
2978 fShift := glBitmapRec4ub(16, 8, 0, 0);
2980 fOpenGLFormat := tfXRGB8ui1;
2981 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
2982 fglInternalFormat := GL_RGB8;
2983 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8_REV;
2985 fOpenGLFormat := tfRGB8ub3;
2989 procedure TfdRGB10X2ui1.SetValues;
2991 inherited SetValues;
2992 fBitsPerPixel := 32;
2993 fFormat := tfRGB10X2ui1;
2994 fWithAlpha := tfRGB10A2ui1;
2995 fWithoutAlpha := tfRGB10X2ui1;
2996 fRGBInverted := tfBGR10X2ui1;
2997 fPrecision := glBitmapRec4ub(10, 10, 10, 0);
2998 fShift := glBitmapRec4ub(22, 12, 2, 0);
3000 fOpenGLFormat := tfRGB10X2ui1;
3001 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3002 fglInternalFormat := GL_RGB10;
3003 fglDataFormat := GL_UNSIGNED_INT_10_10_10_2;
3005 fOpenGLFormat := tfRGB16us3;
3009 procedure TfdX2RGB10ui1.SetValues;
3011 inherited SetValues;
3012 fBitsPerPixel := 32;
3013 fFormat := tfX2RGB10ui1;
3014 fWithAlpha := tfA2RGB10ui1;
3015 fWithoutAlpha := tfX2RGB10ui1;
3016 fRGBInverted := tfX2BGR10ui1;
3017 fPrecision := glBitmapRec4ub(10, 10, 10, 0);
3018 fShift := glBitmapRec4ub(20, 10, 0, 0);
3020 fOpenGLFormat := tfX2RGB10ui1;
3021 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3022 fglInternalFormat := GL_RGB10;
3023 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3025 fOpenGLFormat := tfRGB16us3;
3029 procedure TfdRGB16us3.SetValues;
3031 inherited SetValues;
3032 fBitsPerPixel := 48;
3033 fFormat := tfRGB16us3;
3034 fWithAlpha := tfRGBA16us4;
3035 fWithoutAlpha := tfRGB16us3;
3036 fRGBInverted := tfBGR16us3;
3037 fPrecision := glBitmapRec4ub(16, 16, 16, 0);
3038 fShift := glBitmapRec4ub( 0, 16, 32, 0);
3039 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
3040 fOpenGLFormat := tfRGB16us3;
3041 fglFormat := GL_RGB;
3042 fglInternalFormat := {$IFNDEF OPENGL_ES}GL_RGB16{$ELSE}GL_RGB16UI{$ENDIF};
3043 fglDataFormat := GL_UNSIGNED_SHORT;
3045 fOpenGLFormat := tfRGB8ub3;
3049 procedure TfdRGBA4us1.SetValues;
3051 inherited SetValues;
3052 fBitsPerPixel := 16;
3053 fFormat := tfRGBA4us1;
3054 fWithAlpha := tfRGBA4us1;
3055 fWithoutAlpha := tfRGBX4us1;
3056 fOpenGLFormat := tfRGBA4us1;
3057 fRGBInverted := tfBGRA4us1;
3058 fPrecision := glBitmapRec4ub( 4, 4, 4, 4);
3059 fShift := glBitmapRec4ub(12, 8, 4, 0);
3060 fglFormat := GL_RGBA;
3061 fglInternalFormat := {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}GL_RGBA8{$ELSE}GL_RGBA{$IFEND};
3062 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4;
3065 procedure TfdARGB4us1.SetValues;
3067 inherited SetValues;
3068 fBitsPerPixel := 16;
3069 fFormat := tfARGB4us1;
3070 fWithAlpha := tfARGB4us1;
3071 fWithoutAlpha := tfXRGB4us1;
3072 fRGBInverted := tfABGR4us1;
3073 fPrecision := glBitmapRec4ub( 4, 4, 4, 4);
3074 fShift := glBitmapRec4ub( 8, 4, 0, 12);
3076 fOpenGLFormat := tfARGB4us1;
3077 fglFormat := GL_BGRA;
3078 fglInternalFormat := GL_RGBA4;
3079 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3081 fOpenGLFormat := tfRGBA4us1;
3085 procedure TfdRGB5A1us1.SetValues;
3087 inherited SetValues;
3088 fBitsPerPixel := 16;
3089 fFormat := tfRGB5A1us1;
3090 fWithAlpha := tfRGB5A1us1;
3091 fWithoutAlpha := tfRGB5X1us1;
3092 fOpenGLFormat := tfRGB5A1us1;
3093 fRGBInverted := tfBGR5A1us1;
3094 fPrecision := glBitmapRec4ub( 5, 5, 5, 1);
3095 fShift := glBitmapRec4ub(11, 6, 1, 0);
3096 fglFormat := GL_RGBA;
3097 fglInternalFormat := {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}GL_RGB5_A1{$ELSE}GL_RGBA{$IFEND};
3098 fglDataFormat := GL_UNSIGNED_SHORT_5_5_5_1;
3101 procedure TfdA1RGB5us1.SetValues;
3103 inherited SetValues;
3104 fBitsPerPixel := 16;
3105 fFormat := tfA1RGB5us1;
3106 fWithAlpha := tfA1RGB5us1;
3107 fWithoutAlpha := tfX1RGB5us1;
3108 fRGBInverted := tfA1BGR5us1;
3109 fPrecision := glBitmapRec4ub( 5, 5, 5, 1);
3110 fShift := glBitmapRec4ub(10, 5, 0, 15);
3112 fOpenGLFormat := tfA1RGB5us1;
3113 fglFormat := GL_BGRA;
3114 fglInternalFormat := GL_RGB5_A1;
3115 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3117 fOpenGLFormat := tfRGB5A1us1;
3121 procedure TfdRGBA8ui1.SetValues;
3123 inherited SetValues;
3124 fBitsPerPixel := 32;
3125 fFormat := tfRGBA8ui1;
3126 fWithAlpha := tfRGBA8ui1;
3127 fWithoutAlpha := tfRGBX8ui1;
3128 fRGBInverted := tfBGRA8ui1;
3129 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3130 fShift := glBitmapRec4ub(24, 16, 8, 0);
3132 fOpenGLFormat := tfRGBA8ui1;
3133 fglFormat := GL_RGBA;
3134 fglInternalFormat := GL_RGBA8;
3135 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8;
3137 fOpenGLFormat := tfRGBA8ub4;
3141 procedure TfdARGB8ui1.SetValues;
3143 inherited SetValues;
3144 fBitsPerPixel := 32;
3145 fFormat := tfARGB8ui1;
3146 fWithAlpha := tfARGB8ui1;
3147 fWithoutAlpha := tfXRGB8ui1;
3148 fRGBInverted := tfABGR8ui1;
3149 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3150 fShift := glBitmapRec4ub(16, 8, 0, 24);
3152 fOpenGLFormat := tfARGB8ui1;
3153 fglFormat := GL_BGRA;
3154 fglInternalFormat := GL_RGBA8;
3155 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8_REV;
3157 fOpenGLFormat := tfRGBA8ub4;
3161 procedure TfdRGBA8ub4.SetValues;
3163 inherited SetValues;
3164 fBitsPerPixel := 32;
3165 fFormat := tfRGBA8ub4;
3166 fWithAlpha := tfRGBA8ub4;
3167 fWithoutAlpha := tfRGB8ub3;
3168 fOpenGLFormat := tfRGBA8ub4;
3169 fRGBInverted := tfBGRA8ub4;
3170 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3171 fShift := glBitmapRec4ub( 0, 8, 16, 24);
3172 fglFormat := GL_RGBA;
3173 fglInternalFormat := {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}GL_RGBA8{$ELSE}GL_RGBA{$IFEND};
3174 fglDataFormat := GL_UNSIGNED_BYTE;
3177 procedure TfdRGB10A2ui1.SetValues;
3179 inherited SetValues;
3180 fBitsPerPixel := 32;
3181 fFormat := tfRGB10A2ui1;
3182 fWithAlpha := tfRGB10A2ui1;
3183 fWithoutAlpha := tfRGB10X2ui1;
3184 fRGBInverted := tfBGR10A2ui1;
3185 fPrecision := glBitmapRec4ub(10, 10, 10, 2);
3186 fShift := glBitmapRec4ub(22, 12, 2, 0);
3188 fOpenGLFormat := tfRGB10A2ui1;
3189 fglFormat := GL_RGBA;
3190 fglInternalFormat := GL_RGB10_A2;
3191 fglDataFormat := GL_UNSIGNED_INT_10_10_10_2;
3193 fOpenGLFormat := tfA2RGB10ui1;
3197 procedure TfdA2RGB10ui1.SetValues;
3199 inherited SetValues;
3200 fBitsPerPixel := 32;
3201 fFormat := tfA2RGB10ui1;
3202 fWithAlpha := tfA2RGB10ui1;
3203 fWithoutAlpha := tfX2RGB10ui1;
3204 fRGBInverted := tfA2BGR10ui1;
3205 fPrecision := glBitmapRec4ub(10, 10, 10, 2);
3206 fShift := glBitmapRec4ub(20, 10, 0, 30);
3207 {$IF NOT DEFINED(OPENGL_ES)}
3208 fOpenGLFormat := tfA2RGB10ui1;
3209 fglFormat := GL_BGRA;
3210 fglInternalFormat := GL_RGB10_A2;
3211 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3212 {$ELSEIF DEFINED(OPENGL_ES_3_0)}
3213 fOpenGLFormat := tfA2RGB10ui1;
3214 fglFormat := GL_RGBA;
3215 fglInternalFormat := GL_RGB10_A2;
3216 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3218 fOpenGLFormat := tfRGBA8ui1;
3222 procedure TfdRGBA16us4.SetValues;
3224 inherited SetValues;
3225 fBitsPerPixel := 64;
3226 fFormat := tfRGBA16us4;
3227 fWithAlpha := tfRGBA16us4;
3228 fWithoutAlpha := tfRGB16us3;
3229 fRGBInverted := tfBGRA16us4;
3230 fPrecision := glBitmapRec4ub(16, 16, 16, 16);
3231 fShift := glBitmapRec4ub( 0, 16, 32, 48);
3232 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
3233 fOpenGLFormat := tfRGBA16us4;
3234 fglFormat := GL_RGBA;
3235 fglInternalFormat := {$IFNDEF OPENGL_ES}GL_RGBA16{$ELSE}GL_RGBA16UI{$ENDIF};
3236 fglDataFormat := GL_UNSIGNED_SHORT;
3238 fOpenGLFormat := tfRGBA8ub4;
3242 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3243 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3244 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3245 procedure TfdBGRX4us1.SetValues;
3247 inherited SetValues;
3248 fBitsPerPixel := 16;
3249 fFormat := tfBGRX4us1;
3250 fWithAlpha := tfBGRA4us1;
3251 fWithoutAlpha := tfBGRX4us1;
3252 fRGBInverted := tfRGBX4us1;
3253 fPrecision := glBitmapRec4ub( 4, 4, 4, 0);
3254 fShift := glBitmapRec4ub( 4, 8, 12, 0);
3256 fOpenGLFormat := tfBGRX4us1;
3257 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3258 fglInternalFormat := GL_RGB4;
3259 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4;
3261 fOpenGLFormat := tfR5G6B5us1;
3265 procedure TfdXBGR4us1.SetValues;
3267 inherited SetValues;
3268 fBitsPerPixel := 16;
3269 fFormat := tfXBGR4us1;
3270 fWithAlpha := tfABGR4us1;
3271 fWithoutAlpha := tfXBGR4us1;
3272 fRGBInverted := tfXRGB4us1;
3273 fPrecision := glBitmapRec4ub( 4, 4, 4, 0);
3274 fShift := glBitmapRec4ub( 0, 4, 8, 0);
3276 fOpenGLFormat := tfXBGR4us1;
3277 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3278 fglInternalFormat := GL_RGB4;
3279 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3281 fOpenGLFormat := tfR5G6B5us1;
3285 procedure TfdB5G6R5us1.SetValues;
3287 inherited SetValues;
3288 fBitsPerPixel := 16;
3289 fFormat := tfB5G6R5us1;
3290 fWithAlpha := tfBGR5A1us1;
3291 fWithoutAlpha := tfB5G6R5us1;
3292 fRGBInverted := tfR5G6B5us1;
3293 fPrecision := glBitmapRec4ub( 5, 6, 5, 0);
3294 fShift := glBitmapRec4ub( 0, 5, 11, 0);
3296 fOpenGLFormat := tfB5G6R5us1;
3297 fglFormat := GL_RGB;
3298 fglInternalFormat := GL_RGB565;
3299 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3301 fOpenGLFormat := tfR5G6B5us1;
3305 procedure TfdBGR5X1us1.SetValues;
3307 inherited SetValues;
3308 fBitsPerPixel := 16;
3309 fFormat := tfBGR5X1us1;
3310 fWithAlpha := tfBGR5A1us1;
3311 fWithoutAlpha := tfBGR5X1us1;
3312 fRGBInverted := tfRGB5X1us1;
3313 fPrecision := glBitmapRec4ub( 5, 5, 5, 0);
3314 fShift := glBitmapRec4ub( 1, 6, 11, 0);
3316 fOpenGLFormat := tfBGR5X1us1;
3317 fglFormat := GL_BGRA;
3318 fglInternalFormat := GL_RGB5;
3319 fglDataFormat := GL_UNSIGNED_SHORT_5_5_5_1;
3321 fOpenGLFormat := tfR5G6B5us1;
3325 procedure TfdX1BGR5us1.SetValues;
3327 inherited SetValues;
3328 fBitsPerPixel := 16;
3329 fFormat := tfX1BGR5us1;
3330 fWithAlpha := tfA1BGR5us1;
3331 fWithoutAlpha := tfX1BGR5us1;
3332 fRGBInverted := tfX1RGB5us1;
3333 fPrecision := glBitmapRec4ub( 5, 5, 5, 0);
3334 fShift := glBitmapRec4ub( 0, 5, 10, 0);
3336 fOpenGLFormat := tfX1BGR5us1;
3337 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3338 fglInternalFormat := GL_RGB5;
3339 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3341 fOpenGLFormat := tfR5G6B5us1;
3345 procedure TfdBGR8ub3.SetValues;
3347 inherited SetValues;
3348 fBitsPerPixel := 24;
3349 fFormat := tfBGR8ub3;
3350 fWithAlpha := tfBGRA8ub4;
3351 fWithoutAlpha := tfBGR8ub3;
3352 fRGBInverted := tfRGB8ub3;
3353 fPrecision := glBitmapRec4ub( 8, 8, 8, 0);
3354 fShift := glBitmapRec4ub(16, 8, 0, 0);
3356 fOpenGLFormat := tfBGR8ub3;
3357 fglFormat := GL_BGR;
3358 fglInternalFormat := GL_RGB8;
3359 fglDataFormat := GL_UNSIGNED_BYTE;
3361 fOpenGLFormat := tfRGB8ub3;
3365 procedure TfdBGRX8ui1.SetValues;
3367 inherited SetValues;
3368 fBitsPerPixel := 32;
3369 fFormat := tfBGRX8ui1;
3370 fWithAlpha := tfBGRA8ui1;
3371 fWithoutAlpha := tfBGRX8ui1;
3372 fRGBInverted := tfRGBX8ui1;
3373 fPrecision := glBitmapRec4ub( 8, 8, 8, 0);
3374 fShift := glBitmapRec4ub( 8, 16, 24, 0);
3376 fOpenGLFormat := tfBGRX8ui1;
3377 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3378 fglInternalFormat := GL_RGB8;
3379 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8;
3381 fOpenGLFormat := tfRGB8ub3;
3385 procedure TfdXBGR8ui1.SetValues;
3387 inherited SetValues;
3388 fBitsPerPixel := 32;
3389 fFormat := tfXBGR8ui1;
3390 fWithAlpha := tfABGR8ui1;
3391 fWithoutAlpha := tfXBGR8ui1;
3392 fRGBInverted := tfXRGB8ui1;
3393 fPrecision := glBitmapRec4ub( 8, 8, 8, 0);
3394 fShift := glBitmapRec4ub( 0, 8, 16, 0);
3396 fOpenGLFormat := tfXBGR8ui1;
3397 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3398 fglInternalFormat := GL_RGB8;
3399 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8_REV;
3401 fOpenGLFormat := tfRGB8ub3;
3405 procedure TfdBGR10X2ui1.SetValues;
3407 inherited SetValues;
3408 fBitsPerPixel := 32;
3409 fFormat := tfBGR10X2ui1;
3410 fWithAlpha := tfBGR10A2ui1;
3411 fWithoutAlpha := tfBGR10X2ui1;
3412 fRGBInverted := tfRGB10X2ui1;
3413 fPrecision := glBitmapRec4ub(10, 10, 10, 0);
3414 fShift := glBitmapRec4ub( 2, 12, 22, 0);
3416 fOpenGLFormat := tfBGR10X2ui1;
3417 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3418 fglInternalFormat := GL_RGB10;
3419 fglDataFormat := GL_UNSIGNED_INT_10_10_10_2;
3421 fOpenGLFormat := tfRGB16us3;
3425 procedure TfdX2BGR10ui1.SetValues;
3427 inherited SetValues;
3428 fBitsPerPixel := 32;
3429 fFormat := tfX2BGR10ui1;
3430 fWithAlpha := tfA2BGR10ui1;
3431 fWithoutAlpha := tfX2BGR10ui1;
3432 fRGBInverted := tfX2RGB10ui1;
3433 fPrecision := glBitmapRec4ub(10, 10, 10, 0);
3434 fShift := glBitmapRec4ub( 0, 10, 20, 0);
3436 fOpenGLFormat := tfX2BGR10ui1;
3437 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3438 fglInternalFormat := GL_RGB10;
3439 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3441 fOpenGLFormat := tfRGB16us3;
3445 procedure TfdBGR16us3.SetValues;
3447 inherited SetValues;
3448 fBitsPerPixel := 48;
3449 fFormat := tfBGR16us3;
3450 fWithAlpha := tfBGRA16us4;
3451 fWithoutAlpha := tfBGR16us3;
3452 fRGBInverted := tfRGB16us3;
3453 fPrecision := glBitmapRec4ub(16, 16, 16, 0);
3454 fShift := glBitmapRec4ub(32, 16, 0, 0);
3456 fOpenGLFormat := tfBGR16us3;
3457 fglFormat := GL_BGR;
3458 fglInternalFormat := GL_RGB16;
3459 fglDataFormat := GL_UNSIGNED_SHORT;
3461 fOpenGLFormat := tfRGB16us3;
3465 procedure TfdBGRA4us1.SetValues;
3467 inherited SetValues;
3468 fBitsPerPixel := 16;
3469 fFormat := tfBGRA4us1;
3470 fWithAlpha := tfBGRA4us1;
3471 fWithoutAlpha := tfBGRX4us1;
3472 fRGBInverted := tfRGBA4us1;
3473 fPrecision := glBitmapRec4ub( 4, 4, 4, 4);
3474 fShift := glBitmapRec4ub( 4, 8, 12, 0);
3476 fOpenGLFormat := tfBGRA4us1;
3477 fglFormat := GL_BGRA;
3478 fglInternalFormat := GL_RGBA4;
3479 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4;
3481 fOpenGLFormat := tfRGBA4us1;
3485 procedure TfdABGR4us1.SetValues;
3487 inherited SetValues;
3488 fBitsPerPixel := 16;
3489 fFormat := tfABGR4us1;
3490 fWithAlpha := tfABGR4us1;
3491 fWithoutAlpha := tfXBGR4us1;
3492 fRGBInverted := tfARGB4us1;
3493 fPrecision := glBitmapRec4ub( 4, 4, 4, 4);
3494 fShift := glBitmapRec4ub( 0, 4, 8, 12);
3496 fOpenGLFormat := tfABGR4us1;
3497 fglFormat := GL_RGBA;
3498 fglInternalFormat := GL_RGBA4;
3499 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3501 fOpenGLFormat := tfRGBA4us1;
3505 procedure TfdBGR5A1us1.SetValues;
3507 inherited SetValues;
3508 fBitsPerPixel := 16;
3509 fFormat := tfBGR5A1us1;
3510 fWithAlpha := tfBGR5A1us1;
3511 fWithoutAlpha := tfBGR5X1us1;
3512 fRGBInverted := tfRGB5A1us1;
3513 fPrecision := glBitmapRec4ub( 5, 5, 5, 1);
3514 fShift := glBitmapRec4ub( 1, 6, 11, 0);
3516 fOpenGLFormat := tfBGR5A1us1;
3517 fglFormat := GL_BGRA;
3518 fglInternalFormat := GL_RGB5_A1;
3519 fglDataFormat := GL_UNSIGNED_SHORT_5_5_5_1;
3521 fOpenGLFormat := tfRGB5A1us1;
3525 procedure TfdA1BGR5us1.SetValues;
3527 inherited SetValues;
3528 fBitsPerPixel := 16;
3529 fFormat := tfA1BGR5us1;
3530 fWithAlpha := tfA1BGR5us1;
3531 fWithoutAlpha := tfX1BGR5us1;
3532 fRGBInverted := tfA1RGB5us1;
3533 fPrecision := glBitmapRec4ub( 5, 5, 5, 1);
3534 fShift := glBitmapRec4ub( 0, 5, 10, 15);
3536 fOpenGLFormat := tfA1BGR5us1;
3537 fglFormat := GL_RGBA;
3538 fglInternalFormat := GL_RGB5_A1;
3539 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3541 fOpenGLFormat := tfRGB5A1us1;
3545 procedure TfdBGRA8ui1.SetValues;
3547 inherited SetValues;
3548 fBitsPerPixel := 32;
3549 fFormat := tfBGRA8ui1;
3550 fWithAlpha := tfBGRA8ui1;
3551 fWithoutAlpha := tfBGRX8ui1;
3552 fRGBInverted := tfRGBA8ui1;
3553 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3554 fShift := glBitmapRec4ub( 8, 16, 24, 0);
3556 fOpenGLFormat := tfBGRA8ui1;
3557 fglFormat := GL_BGRA;
3558 fglInternalFormat := GL_RGBA8;
3559 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8;
3561 fOpenGLFormat := tfRGBA8ub4;
3565 procedure TfdABGR8ui1.SetValues;
3567 inherited SetValues;
3568 fBitsPerPixel := 32;
3569 fFormat := tfABGR8ui1;
3570 fWithAlpha := tfABGR8ui1;
3571 fWithoutAlpha := tfXBGR8ui1;
3572 fRGBInverted := tfARGB8ui1;
3573 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3574 fShift := glBitmapRec4ub( 0, 8, 16, 24);
3576 fOpenGLFormat := tfABGR8ui1;
3577 fglFormat := GL_RGBA;
3578 fglInternalFormat := GL_RGBA8;
3579 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8_REV;
3581 fOpenGLFormat := tfRGBA8ub4
3585 procedure TfdBGRA8ub4.SetValues;
3587 inherited SetValues;
3588 fBitsPerPixel := 32;
3589 fFormat := tfBGRA8ub4;
3590 fWithAlpha := tfBGRA8ub4;
3591 fWithoutAlpha := tfBGR8ub3;
3592 fRGBInverted := tfRGBA8ub4;
3593 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3594 fShift := glBitmapRec4ub(16, 8, 0, 24);
3596 fOpenGLFormat := tfBGRA8ub4;
3597 fglFormat := GL_BGRA;
3598 fglInternalFormat := GL_RGBA8;
3599 fglDataFormat := GL_UNSIGNED_BYTE;
3601 fOpenGLFormat := tfRGBA8ub4;
3605 procedure TfdBGR10A2ui1.SetValues;
3607 inherited SetValues;
3608 fBitsPerPixel := 32;
3609 fFormat := tfBGR10A2ui1;
3610 fWithAlpha := tfBGR10A2ui1;
3611 fWithoutAlpha := tfBGR10X2ui1;
3612 fRGBInverted := tfRGB10A2ui1;
3613 fPrecision := glBitmapRec4ub(10, 10, 10, 2);
3614 fShift := glBitmapRec4ub( 2, 12, 22, 0);
3616 fOpenGLFormat := tfBGR10A2ui1;
3617 fglFormat := GL_BGRA;
3618 fglInternalFormat := GL_RGB10_A2;
3619 fglDataFormat := GL_UNSIGNED_INT_10_10_10_2;
3621 fOpenGLFormat := tfA2RGB10ui1;
3625 procedure TfdA2BGR10ui1.SetValues;
3627 inherited SetValues;
3628 fBitsPerPixel := 32;
3629 fFormat := tfA2BGR10ui1;
3630 fWithAlpha := tfA2BGR10ui1;
3631 fWithoutAlpha := tfX2BGR10ui1;
3632 fRGBInverted := tfA2RGB10ui1;
3633 fPrecision := glBitmapRec4ub(10, 10, 10, 2);
3634 fShift := glBitmapRec4ub( 0, 10, 20, 30);
3636 fOpenGLFormat := tfA2BGR10ui1;
3637 fglFormat := GL_RGBA;
3638 fglInternalFormat := GL_RGB10_A2;
3639 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3641 fOpenGLFormat := tfA2RGB10ui1;
3645 procedure TfdBGRA16us4.SetValues;
3647 inherited SetValues;
3648 fBitsPerPixel := 64;
3649 fFormat := tfBGRA16us4;
3650 fWithAlpha := tfBGRA16us4;
3651 fWithoutAlpha := tfBGR16us3;
3652 fRGBInverted := tfRGBA16us4;
3653 fPrecision := glBitmapRec4ub(16, 16, 16, 16);
3654 fShift := glBitmapRec4ub(32, 16, 0, 48);
3656 fOpenGLFormat := tfBGRA16us4;
3657 fglFormat := GL_BGRA;
3658 fglInternalFormat := GL_RGBA16;
3659 fglDataFormat := GL_UNSIGNED_SHORT;
3661 fOpenGLFormat := tfRGBA16us4;
3665 procedure TfdDepth16us1.SetValues;
3667 inherited SetValues;
3668 fBitsPerPixel := 16;
3669 fFormat := tfDepth16us1;
3670 fWithoutAlpha := tfDepth16us1;
3671 fPrecision := glBitmapRec4ub(16, 16, 16, 16);
3672 fShift := glBitmapRec4ub( 0, 0, 0, 0);
3673 {$IF NOT DEFINED (OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
3674 fOpenGLFormat := tfDepth16us1;
3675 fglFormat := GL_DEPTH_COMPONENT;
3676 fglInternalFormat := GL_DEPTH_COMPONENT16;
3677 fglDataFormat := GL_UNSIGNED_SHORT;
3681 procedure TfdDepth24ui1.SetValues;
3683 inherited SetValues;
3684 fBitsPerPixel := 32;
3685 fFormat := tfDepth24ui1;
3686 fWithoutAlpha := tfDepth24ui1;
3687 fOpenGLFormat := tfDepth24ui1;
3688 fPrecision := glBitmapRec4ub(32, 32, 32, 32);
3689 fShift := glBitmapRec4ub( 0, 0, 0, 0);
3690 {$IF NOT DEFINED (OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
3691 fOpenGLFormat := tfDepth24ui1;
3692 fglFormat := GL_DEPTH_COMPONENT;
3693 fglInternalFormat := GL_DEPTH_COMPONENT24;
3694 fglDataFormat := GL_UNSIGNED_INT;
3698 procedure TfdDepth32ui1.SetValues;
3700 inherited SetValues;
3701 fBitsPerPixel := 32;
3702 fFormat := tfDepth32ui1;
3703 fWithoutAlpha := tfDepth32ui1;
3704 fPrecision := glBitmapRec4ub(32, 32, 32, 32);
3705 fShift := glBitmapRec4ub( 0, 0, 0, 0);
3706 {$IF NOT DEFINED(OPENGL_ES)}
3707 fOpenGLFormat := tfDepth32ui1;
3708 fglFormat := GL_DEPTH_COMPONENT;
3709 fglInternalFormat := GL_DEPTH_COMPONENT32;
3710 fglDataFormat := GL_UNSIGNED_INT;
3711 {$ELSEIF DEFINED(OPENGL_ES_3_0)}
3712 fOpenGLFormat := tfDepth24ui1;
3713 {$ELSEIF DEFINED(OPENGL_ES_2_0)}
3714 fOpenGLFormat := tfDepth16us1;
3718 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3719 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3720 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3721 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3723 raise EglBitmap.Create('mapping for compressed formats is not supported');
3726 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3728 raise EglBitmap.Create('mapping for compressed formats is not supported');
3731 procedure TfdS3tcDtx1RGBA.SetValues;
3733 inherited SetValues;
3734 fFormat := tfS3tcDtx1RGBA;
3735 fWithAlpha := tfS3tcDtx1RGBA;
3736 fUncompressed := tfRGB5A1us1;
3738 fIsCompressed := true;
3740 fOpenGLFormat := tfS3tcDtx1RGBA;
3741 fglFormat := GL_COMPRESSED_RGBA;
3742 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3743 fglDataFormat := GL_UNSIGNED_BYTE;
3745 fOpenGLFormat := fUncompressed;
3749 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3750 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3752 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3754 raise EglBitmap.Create('mapping for compressed formats is not supported');
3757 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3759 raise EglBitmap.Create('mapping for compressed formats is not supported');
3762 procedure TfdS3tcDtx3RGBA.SetValues;
3764 inherited SetValues;
3765 fFormat := tfS3tcDtx3RGBA;
3766 fWithAlpha := tfS3tcDtx3RGBA;
3767 fUncompressed := tfRGBA8ub4;
3769 fIsCompressed := true;
3771 fOpenGLFormat := tfS3tcDtx3RGBA;
3772 fglFormat := GL_COMPRESSED_RGBA;
3773 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3774 fglDataFormat := GL_UNSIGNED_BYTE;
3776 fOpenGLFormat := fUncompressed;
3780 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3781 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3782 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3783 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3785 raise EglBitmap.Create('mapping for compressed formats is not supported');
3788 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3790 raise EglBitmap.Create('mapping for compressed formats is not supported');
3793 procedure TfdS3tcDtx5RGBA.SetValues;
3795 inherited SetValues;
3796 fFormat := tfS3tcDtx3RGBA;
3797 fWithAlpha := tfS3tcDtx3RGBA;
3798 fUncompressed := tfRGBA8ub4;
3800 fIsCompressed := true;
3802 fOpenGLFormat := tfS3tcDtx3RGBA;
3803 fglFormat := GL_COMPRESSED_RGBA;
3804 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3805 fglDataFormat := GL_UNSIGNED_BYTE;
3807 fOpenGLFormat := fUncompressed;
3811 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3812 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3813 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3814 function TglBitmapFormatDescriptor.GetHasRed: Boolean;
3816 result := (fPrecision.r > 0);
3819 function TglBitmapFormatDescriptor.GetHasGreen: Boolean;
3821 result := (fPrecision.g > 0);
3824 function TglBitmapFormatDescriptor.GetHasBlue: Boolean;
3826 result := (fPrecision.b > 0);
3829 function TglBitmapFormatDescriptor.GetHasAlpha: Boolean;
3831 result := (fPrecision.a > 0);
3834 function TglBitmapFormatDescriptor.GetHasColor: Boolean;
3836 result := HasRed or HasGreen or HasBlue;
3839 function TglBitmapFormatDescriptor.GetIsGrayscale: Boolean;
3841 result := (Mask.r = Mask.g) and (Mask.g = Mask.b) and (Mask.r > 0);
3844 function TglBitmapFormatDescriptor.GetHasOpenGLSupport: Boolean;
3846 result := (OpenGLFormat = Format);
3849 procedure TglBitmapFormatDescriptor.SetValues;
3852 fWithAlpha := tfEmpty;
3853 fWithoutAlpha := tfEmpty;
3854 fOpenGLFormat := tfEmpty;
3855 fRGBInverted := tfEmpty;
3856 fUncompressed := tfEmpty;
3859 fIsCompressed := false;
3862 fglInternalFormat := 0;
3865 FillChar(fPrecision, 0, SizeOf(fPrecision));
3866 FillChar(fShift, 0, SizeOf(fShift));
3869 procedure TglBitmapFormatDescriptor.CalcValues;
3873 fBytesPerPixel := fBitsPerPixel / 8;
3875 for i := 0 to 3 do begin
3876 if (fPrecision.arr[i] > 0) then
3878 fRange.arr[i] := (1 shl fPrecision.arr[i]) - 1;
3879 fMask.arr[i] := fRange.arr[i] shl fShift.arr[i];
3883 function TglBitmapFormatDescriptor.GetSize(const aSize: TglBitmapSize): Integer;
3887 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
3888 w := Max(1, aSize.X);
3889 h := Max(1, aSize.Y);
3890 result := GetSize(w, h);
3895 function TglBitmapFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
3898 if (aWidth <= 0) or (aHeight <= 0) then
3900 result := Ceil(aWidth * aHeight * BytesPerPixel);
3903 constructor TglBitmapFormatDescriptor.Create;
3910 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3911 class function TglBitmapFormatDescriptor.GetByFormat(const aInternalFormat: GLenum): TglBitmapFormatDescriptor;
3915 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
3916 result := TFormatDescriptor.Get(f);
3917 if (result.glInternalFormat = aInternalFormat) then
3920 result := TFormatDescriptor.Get(tfEmpty);
3923 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3924 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3925 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3926 class procedure TFormatDescriptor.Init;
3928 if not Assigned(FormatDescriptorCS) then
3929 FormatDescriptorCS := TCriticalSection.Create;
3932 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3933 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3935 FormatDescriptorCS.Enter;
3937 result := FormatDescriptors[aFormat];
3938 if not Assigned(result) then begin
3939 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3940 FormatDescriptors[aFormat] := result;
3943 FormatDescriptorCS.Leave;
3947 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3948 class function TFormatDescriptor.GetAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3950 result := Get(Get(aFormat).WithAlpha);
3953 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3954 class function TFormatDescriptor.GetFromMask(const aMask: TglBitmapRec4ul; const aBitCount: Integer): TFormatDescriptor;
3956 ft: TglBitmapFormat;
3958 // find matching format with OpenGL support
3959 for ft := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
3961 if (result.MaskMatch(aMask)) and
3962 (result.glFormat <> 0) and
3963 (result.glInternalFormat <> 0) and
3964 ((aBitCount = 0) or (aBitCount = result.BitsPerPixel))
3969 // find matching format without OpenGL Support
3970 for ft := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
3972 if result.MaskMatch(aMask) and ((aBitCount = 0) or (aBitCount = result.BitsPerPixel)) then
3976 result := TFormatDescriptor.Get(tfEmpty);
3979 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3980 class function TFormatDescriptor.GetFromPrecShift(const aPrec, aShift: TglBitmapRec4ub; const aBitCount: Integer): TFormatDescriptor;
3982 ft: TglBitmapFormat;
3984 // find matching format with OpenGL support
3985 for ft := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
3987 if glBitmapRec4ubCompare(result.Shift, aShift) and
3988 glBitmapRec4ubCompare(result.Precision, aPrec) and
3989 (result.glFormat <> 0) and
3990 (result.glInternalFormat <> 0) and
3991 ((aBitCount = 0) or (aBitCount = result.BitsPerPixel))
3996 // find matching format without OpenGL Support
3997 for ft := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
3999 if glBitmapRec4ubCompare(result.Shift, aShift) and
4000 glBitmapRec4ubCompare(result.Precision, aPrec) and
4001 ((aBitCount = 0) or (aBitCount = result.BitsPerPixel)) then
4005 result := TFormatDescriptor.Get(tfEmpty);
4008 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4009 class procedure TFormatDescriptor.Clear;
4013 FormatDescriptorCS.Enter;
4015 for f := low(FormatDescriptors) to high(FormatDescriptors) do
4016 FreeAndNil(FormatDescriptors[f]);
4018 FormatDescriptorCS.Leave;
4022 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4023 class procedure TFormatDescriptor.Finalize;
4026 FreeAndNil(FormatDescriptorCS);
4029 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4030 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4031 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4032 procedure TbmpBitfieldFormat.SetCustomValues(const aBPP: Integer; aMask: TglBitmapRec4ul);
4036 for i := 0 to 3 do begin
4038 while (aMask.arr[i] > 0) and ((aMask.arr[i] and 1) = 0) do begin
4039 aMask.arr[i] := aMask.arr[i] shr 1;
4042 fPrecision.arr[i] := CountSetBits(aMask.arr[i]);
4044 fBitsPerPixel := aBPP;
4048 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4049 procedure TbmpBitfieldFormat.SetCustomValues(const aBBP: Integer; const aPrec, aShift: TglBitmapRec4ub);
4051 fBitsPerPixel := aBBP;
4052 fPrecision := aPrec;
4057 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4058 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
4063 ((aPixel.Data.r and Range.r) shl Shift.r) or
4064 ((aPixel.Data.g and Range.g) shl Shift.g) or
4065 ((aPixel.Data.b and Range.b) shl Shift.b) or
4066 ((aPixel.Data.a and Range.a) shl Shift.a);
4067 case BitsPerPixel of
4069 16: PWord(aData)^ := data;
4070 32: PCardinal(aData)^ := data;
4071 64: PQWord(aData)^ := data;
4073 raise EglBitmap.CreateFmt('invalid pixel size: %d', [BitsPerPixel]);
4075 inc(aData, Round(BytesPerPixel));
4078 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4079 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
4084 case BitsPerPixel of
4086 16: data := PWord(aData)^;
4087 32: data := PCardinal(aData)^;
4088 64: data := PQWord(aData)^;
4090 raise EglBitmap.CreateFmt('invalid pixel size: %d', [BitsPerPixel]);
4093 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and Range.arr[i];
4094 inc(aData, Round(BytesPerPixel));
4097 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4098 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4099 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4100 procedure TbmpColorTableFormat.SetValues;
4102 inherited SetValues;
4103 fShift := glBitmapRec4ub(8, 8, 8, 0);
4106 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4107 procedure TbmpColorTableFormat.SetCustomValues(const aFormat: TglBitmapFormat; const aBPP: Integer; const aPrec, aShift: TglBitmapRec4ub);
4110 fBitsPerPixel := aBPP;
4111 fPrecision := aPrec;
4116 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4117 procedure TbmpColorTableFormat.CalcValues;
4119 inherited CalcValues;
4122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4123 procedure TbmpColorTableFormat.CreateColorTable;
4127 SetLength(fColorTable, 256);
4128 if not HasColor then begin
4130 for i := 0 to High(fColorTable) do begin
4131 fColorTable[i].r := Round(((i shr Shift.a) and Range.a) / Range.a * 255);
4132 fColorTable[i].g := Round(((i shr Shift.a) and Range.a) / Range.a * 255);
4133 fColorTable[i].b := Round(((i shr Shift.a) and Range.a) / Range.a * 255);
4134 fColorTable[i].a := 0;
4138 for i := 0 to High(fColorTable) do begin
4139 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
4140 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
4141 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
4142 fColorTable[i].a := 0;
4147 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4148 function TbmpColorTableFormat.CreateMappingData: Pointer;
4150 result := Pointer(0);
4153 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4154 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
4156 if (BitsPerPixel <> 8) then
4157 raise EglBitmapUnsupportedFormat.Create('color table are only supported for 8bit formats');
4158 if not HasColor then
4160 aData^ := aPixel.Data.a
4164 ((aPixel.Data.r shr Shift.r) and Range.r) * LUMINANCE_WEIGHT_R +
4165 ((aPixel.Data.g shr Shift.g) and Range.g) * LUMINANCE_WEIGHT_G +
4166 ((aPixel.Data.b shr Shift.b) and Range.b) * LUMINANCE_WEIGHT_B);
4170 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4171 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
4173 function ReadValue: Byte;
4177 if (BitsPerPixel = 8) then begin
4181 i := {%H-}PtrUInt(aMapData);
4182 if (BitsPerPixel > 1) then
4183 result := (aData^ shr i) and ((1 shl BitsPerPixel) - 1)
4185 result := (aData^ shr (7-i)) and ((1 shl BitsPerPixel) - 1);
4186 inc(i, BitsPerPixel);
4187 while (i >= 8) do begin
4191 aMapData := {%H-}Pointer(i);
4196 if (BitsPerPixel > 8) then
4197 raise EglBitmapUnsupportedFormat.Create('color table are only supported for 8bit formats');
4198 with fColorTable[ReadValue] do begin
4206 destructor TbmpColorTableFormat.Destroy;
4208 SetLength(fColorTable, 0);
4212 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4213 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4214 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4215 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
4219 for i := 0 to 3 do begin
4220 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
4221 if (aSourceFD.Range.arr[i] > 0) then
4222 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
4224 aPixel.Data.arr[i] := 0;
4229 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4230 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
4232 with aFuncRec do begin
4233 if (Source.Range.r > 0) then
4234 Dest.Data.r := Source.Data.r;
4235 if (Source.Range.g > 0) then
4236 Dest.Data.g := Source.Data.g;
4237 if (Source.Range.b > 0) then
4238 Dest.Data.b := Source.Data.b;
4239 if (Source.Range.a > 0) then
4240 Dest.Data.a := Source.Data.a;
4244 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4245 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4249 with aFuncRec do begin
4251 if (Source.Range.arr[i] > 0) then
4252 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4257 TShiftData = packed record
4259 0: (r, g, b, a: SmallInt);
4260 1: (arr: array[0..3] of SmallInt);
4262 PShiftData = ^TShiftData;
4264 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4265 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4271 if (Source.Range.arr[i] > 0) then
4272 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4275 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4276 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4280 with aFuncRec do begin
4281 Dest.Data := Source.Data;
4283 if ({%H-}PtrUInt(Args) and (1 shl i) > 0) then
4284 Dest.Data.arr[i] := Dest.Data.arr[i] xor Dest.Range.arr[i];
4288 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4289 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4293 with aFuncRec do begin
4295 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4299 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4300 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4304 with FuncRec do begin
4305 if (FuncRec.Args = nil) then begin //source has no alpha
4307 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4308 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4309 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4310 Dest.Data.a := Round(Dest.Range.a * Temp);
4312 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4316 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4317 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4319 PglBitmapPixelData = ^TglBitmapPixelData;
4321 with FuncRec do begin
4322 Dest.Data.r := Source.Data.r;
4323 Dest.Data.g := Source.Data.g;
4324 Dest.Data.b := Source.Data.b;
4326 with PglBitmapPixelData(Args)^ do
4327 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4328 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4329 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4332 Dest.Data.a := Dest.Range.a;
4336 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4337 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4339 with FuncRec do begin
4340 Dest.Data.r := Source.Data.r;
4341 Dest.Data.g := Source.Data.g;
4342 Dest.Data.b := Source.Data.b;
4343 Dest.Data.a := PCardinal(Args)^;
4347 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4348 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4351 TRGBPix = array [0..2] of byte;
4355 while aWidth > 0 do begin
4356 Temp := PRGBPix(aData)^[0];
4357 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4358 PRGBPix(aData)^[2] := Temp;
4368 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4369 //TglBitmapData///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4370 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4371 function TglBitmapData.GetFormatDescriptor: TglBitmapFormatDescriptor;
4373 result := TFormatDescriptor.Get(fFormat);
4376 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4377 function TglBitmapData.GetWidth: Integer;
4379 if (ffX in fDimension.Fields) then
4380 result := fDimension.X
4385 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4386 function TglBitmapData.GetHeight: Integer;
4388 if (ffY in fDimension.Fields) then
4389 result := fDimension.Y
4394 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4395 function TglBitmapData.GetScanlines(const aIndex: Integer): PByte;
4397 if fHasScanlines and (aIndex >= Low(fScanlines)) and (aIndex <= High(fScanlines)) then
4398 result := fScanlines[aIndex]
4403 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4404 procedure TglBitmapData.SetFormat(const aValue: TglBitmapFormat);
4406 if fFormat = aValue then
4408 if TFormatDescriptor.Get(Format).BitsPerPixel <> TFormatDescriptor.Get(aValue).BitsPerPixel then
4409 raise EglBitmapUnsupportedFormat.Create(Format);
4410 SetData(fData, aValue, Width, Height);
4413 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4414 procedure TglBitmapData.PrepareResType(var aResource: String; var aResType: PChar);
4418 if not Assigned(aResType) then begin
4419 TempPos := Pos('.', aResource);
4420 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4421 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4426 procedure TglBitmapData.UpdateScanlines;
4428 w, h, i, LineWidth: Integer;
4432 fHasScanlines := Assigned(fData) and (w > 0) and (h > 0);
4433 if fHasScanlines then begin
4434 SetLength(fScanlines, h);
4435 LineWidth := Trunc(w * FormatDescriptor.BytesPerPixel);
4436 for i := 0 to h-1 do begin
4437 fScanlines[i] := fData;
4438 Inc(fScanlines[i], i * LineWidth);
4441 SetLength(fScanlines, 0);
4444 {$IFDEF GLB_SUPPORT_PNG_READ}
4445 {$IF DEFINED(GLB_LAZ_PNG)}
4446 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4447 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4448 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4449 function TglBitmapData.LoadPNG(const aStream: TStream): Boolean;
4452 PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A;
4454 reader: TLazReaderPNG;
4455 intf: TLazIntfImage;
4457 magic: String[MAGIC_LEN];
4460 StreamPos := aStream.Position;
4462 SetLength(magic, MAGIC_LEN);
4463 aStream.Read(magic[1], MAGIC_LEN);
4464 aStream.Position := StreamPos;
4465 if (magic <> PNG_MAGIC) then begin
4470 intf := TLazIntfImage.Create(0, 0);
4471 reader := TLazReaderPNG.Create;
4473 reader.UpdateDescription := true;
4474 reader.ImageRead(aStream, intf);
4475 AssignFromLazIntfImage(intf);
4478 aStream.Position := StreamPos;
4487 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
4488 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4489 function TglBitmapData.LoadPNG(const aStream: TStream): Boolean;
4491 Surface: PSDL_Surface;
4495 RWops := glBitmapCreateRWops(aStream);
4497 if IMG_isPNG(RWops) > 0 then begin
4498 Surface := IMG_LoadPNG_RW(RWops);
4500 AssignFromSurface(Surface);
4503 SDL_FreeSurface(Surface);
4511 {$ELSEIF DEFINED(GLB_LIB_PNG)}
4512 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4513 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
4515 TStream(png_get_io_ptr(png)).Read(buffer^, size);
4518 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4519 function TglBitmapData.LoadPNG(const aStream: TStream): Boolean;
4522 signature: array [0..7] of byte;
4524 png_info: png_infop;
4526 TempHeight, TempWidth: Integer;
4527 Format: TglBitmapFormat;
4530 png_rows: array of pByte;
4531 Row, LineSize: Integer;
4535 if not init_libPNG then
4536 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
4540 StreamPos := aStream.Position;
4541 aStream.Read(signature{%H-}, 8);
4542 aStream.Position := StreamPos;
4544 if png_check_sig(@signature, 8) <> 0 then begin
4546 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
4548 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
4551 png_info := png_create_info_struct(png);
4552 if png_info = nil then begin
4553 png_destroy_read_struct(@png, nil, nil);
4554 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
4557 // set read callback
4558 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
4560 // read informations
4561 png_read_info(png, png_info);
4564 TempHeight := png_get_image_height(png, png_info);
4565 TempWidth := png_get_image_width(png, png_info);
4568 case png_get_color_type(png, png_info) of
4569 PNG_COLOR_TYPE_GRAY:
4570 Format := tfLuminance8ub1;
4571 PNG_COLOR_TYPE_GRAY_ALPHA:
4572 Format := tfLuminance8Alpha8us1;
4574 Format := tfRGB8ub3;
4575 PNG_COLOR_TYPE_RGB_ALPHA:
4576 Format := tfRGBA8ub4;
4578 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
4581 // cut upper 8 bit from 16 bit formats
4582 if png_get_bit_depth(png, png_info) > 8 then
4583 png_set_strip_16(png);
4585 // expand bitdepth smaller than 8
4586 if png_get_bit_depth(png, png_info) < 8 then
4587 png_set_expand(png);
4589 // allocating mem for scanlines
4590 LineSize := png_get_rowbytes(png, png_info);
4591 GetMem(png_data, TempHeight * LineSize);
4593 SetLength(png_rows, TempHeight);
4594 for Row := Low(png_rows) to High(png_rows) do begin
4595 png_rows[Row] := png_data;
4596 Inc(png_rows[Row], Row * LineSize);
4599 // read complete image into scanlines
4600 png_read_image(png, @png_rows[0]);
4603 png_read_end(png, png_info);
4605 // destroy read struct
4606 png_destroy_read_struct(@png, @png_info, nil);
4608 SetLength(png_rows, 0);
4611 SetData(png_data, Format, TempWidth, TempHeight);
4615 if Assigned(png_data) then
4625 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
4626 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4627 function TglBitmapData.LoadPNG(const aStream: TStream): Boolean;
4632 Row, Col, PixSize, LineSize: Integer;
4633 NewImage, pSource, pDest, pAlpha: pByte;
4634 PngFormat: TglBitmapFormat;
4635 FormatDesc: TFormatDescriptor;
4638 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
4643 StreamPos := aStream.Position;
4644 aStream.Read(Header[0], SizeOf(Header));
4645 aStream.Position := StreamPos;
4647 {Test if the header matches}
4648 if Header = PngHeader then begin
4649 Png := TPNGObject.Create;
4651 Png.LoadFromStream(aStream);
4653 case Png.Header.ColorType of
4655 PngFormat := tfLuminance8ub1;
4656 COLOR_GRAYSCALEALPHA:
4657 PngFormat := tfLuminance8Alpha8us1;
4659 PngFormat := tfBGR8ub3;
4661 PngFormat := tfBGRA8ub4;
4663 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
4666 FormatDesc := TFormatDescriptor.Get(PngFormat);
4667 PixSize := Round(FormatDesc.PixelSize);
4668 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
4670 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
4674 case Png.Header.ColorType of
4675 COLOR_RGB, COLOR_GRAYSCALE:
4677 for Row := 0 to Png.Height -1 do begin
4678 Move (Png.Scanline[Row]^, pDest^, LineSize);
4679 Inc(pDest, LineSize);
4682 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
4684 PixSize := PixSize -1;
4686 for Row := 0 to Png.Height -1 do begin
4687 pSource := Png.Scanline[Row];
4688 pAlpha := pByte(Png.AlphaScanline[Row]);
4690 for Col := 0 to Png.Width -1 do begin
4691 Move (pSource^, pDest^, PixSize);
4692 Inc(pSource, PixSize);
4693 Inc(pDest, PixSize);
4702 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
4705 SetData(NewImage, PngFormat, Png.Header.Width, Png.Header.Height);
4709 if Assigned(NewImage) then
4721 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4722 {$IFDEF GLB_LIB_PNG}
4723 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4724 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
4726 TStream(png_get_io_ptr(png)).Write(buffer^, size);
4730 {$IF DEFINED(GLB_LAZ_PNG)}
4731 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4732 procedure TglBitmapData.SavePNG(const aStream: TStream);
4734 png: TPortableNetworkGraphic;
4735 intf: TLazIntfImage;
4738 png := TPortableNetworkGraphic.Create;
4739 intf := TLazIntfImage.Create(0, 0);
4741 if not AssignToLazIntfImage(intf) then
4742 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
4743 intf.GetRawImage(raw);
4744 png.LoadFromRawImage(raw, false);
4745 png.SaveToStream(aStream);
4752 {$ELSEIF DEFINED(GLB_LIB_PNG)}
4753 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4754 procedure TglBitmapData.SavePNG(const aStream: TStream);
4757 png_info: png_infop;
4758 png_rows: array of pByte;
4762 FormatDesc: TFormatDescriptor;
4764 if not (ftPNG in FormatGetSupportedFiles(Format)) then
4765 raise EglBitmapUnsupportedFormat.Create(Format);
4767 if not init_libPNG then
4768 raise Exception.Create('unable to initialize libPNG.');
4772 tfAlpha8ub1, tfLuminance8ub1:
4773 ColorType := PNG_COLOR_TYPE_GRAY;
4774 tfLuminance8Alpha8us1:
4775 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
4776 tfBGR8ub3, tfRGB8ub3:
4777 ColorType := PNG_COLOR_TYPE_RGB;
4778 tfBGRA8ub4, tfRGBA8ub4:
4779 ColorType := PNG_COLOR_TYPE_RGBA;
4781 raise EglBitmapUnsupportedFormat.Create(Format);
4784 FormatDesc := TFormatDescriptor.Get(Format);
4785 LineSize := FormatDesc.GetSize(Width, 1);
4787 // creating array for scanline
4788 SetLength(png_rows, Height);
4790 for Row := 0 to Height - 1 do begin
4791 png_rows[Row] := Data;
4792 Inc(png_rows[Row], Row * LineSize)
4796 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
4798 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
4801 png_info := png_create_info_struct(png);
4802 if png_info = nil then begin
4803 png_destroy_write_struct(@png, nil);
4804 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
4807 // set read callback
4808 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
4811 png_set_compression_level(png, 6);
4813 if Format in [tfBGR8ub3, tfBGRA8ub4] then
4816 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
4817 png_write_info(png, png_info);
4818 png_write_image(png, @png_rows[0]);
4819 png_write_end(png, png_info);
4820 png_destroy_write_struct(@png, @png_info);
4822 SetLength(png_rows, 0);
4829 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
4830 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4831 procedure TglBitmapData.SavePNG(const aStream: TStream);
4835 pSource, pDest: pByte;
4836 X, Y, PixSize: Integer;
4837 ColorType: Cardinal;
4843 if not (ftPNG in FormatGetSupportedFiles (Format)) then
4844 raise EglBitmapUnsupportedFormat.Create(Format);
4847 tfAlpha8ub1, tfLuminance8ub1: begin
4848 ColorType := COLOR_GRAYSCALE;
4852 tfLuminance8Alpha8us1: begin
4853 ColorType := COLOR_GRAYSCALEALPHA;
4857 tfBGR8ub3, tfRGB8ub3: begin
4858 ColorType := COLOR_RGB;
4862 tfBGRA8ub4, tfRGBA8ub4: begin
4863 ColorType := COLOR_RGBALPHA;
4868 raise EglBitmapUnsupportedFormat.Create(Format);
4871 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
4875 for Y := 0 to Height -1 do begin
4876 pDest := png.ScanLine[Y];
4877 for X := 0 to Width -1 do begin
4878 Move(pSource^, pDest^, PixSize);
4879 Inc(pDest, PixSize);
4880 Inc(pSource, PixSize);
4882 png.AlphaScanline[Y]^[X] := pSource^;
4887 // convert RGB line to BGR
4888 if Format in [tfRGB8ub3, tfRGBA8ub4] then begin
4889 pTemp := png.ScanLine[Y];
4890 for X := 0 to Width -1 do begin
4891 Temp := pByteArray(pTemp)^[0];
4892 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
4893 pByteArray(pTemp)^[2] := Temp;
4900 Png.CompressionLevel := 6;
4901 Png.SaveToStream(aStream);
4909 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4910 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4911 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4912 {$IFDEF GLB_LIB_JPEG}
4914 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
4915 glBitmap_libJPEG_source_mgr = record
4916 pub: jpeg_source_mgr;
4919 SrcBuffer: array [1..4096] of byte;
4922 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
4923 glBitmap_libJPEG_dest_mgr = record
4924 pub: jpeg_destination_mgr;
4926 DestStream: TStream;
4927 DestBuffer: array [1..4096] of byte;
4930 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
4936 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
4942 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
4947 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
4953 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
4959 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4960 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
4962 src: glBitmap_libJPEG_source_mgr_ptr;
4965 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
4967 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
4968 if (bytes <= 0) then begin
4969 src^.SrcBuffer[1] := $FF;
4970 src^.SrcBuffer[2] := JPEG_EOI;
4974 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
4975 src^.pub.bytes_in_buffer := bytes;
4980 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4981 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
4983 src: glBitmap_libJPEG_source_mgr_ptr;
4985 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
4987 if num_bytes > 0 then begin
4988 // wanted byte isn't in buffer so set stream position and read buffer
4989 if num_bytes > src^.pub.bytes_in_buffer then begin
4990 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
4991 src^.pub.fill_input_buffer(cinfo);
4993 // wanted byte is in buffer so only skip
4994 inc(src^.pub.next_input_byte, num_bytes);
4995 dec(src^.pub.bytes_in_buffer, num_bytes);
5000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5001 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
5003 dest: glBitmap_libJPEG_dest_mgr_ptr;
5005 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5007 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
5008 // write complete buffer
5009 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
5012 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
5013 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
5019 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5020 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
5023 dest: glBitmap_libJPEG_dest_mgr_ptr;
5025 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5027 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
5028 // check for endblock
5029 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
5031 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
5036 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
5041 {$IFDEF GLB_SUPPORT_JPEG_READ}
5042 {$IF DEFINED(GLB_LAZ_JPEG)}
5043 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5044 function TglBitmapData.LoadJPEG(const aStream: TStream): Boolean;
5047 JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
5049 intf: TLazIntfImage;
5050 reader: TFPReaderJPEG;
5052 magic: String[MAGIC_LEN];
5055 StreamPos := aStream.Position;
5057 SetLength(magic, MAGIC_LEN);
5058 aStream.Read(magic[1], MAGIC_LEN);
5059 aStream.Position := StreamPos;
5060 if (magic <> JPEG_MAGIC) then begin
5065 reader := TFPReaderJPEG.Create;
5066 intf := TLazIntfImage.Create(0, 0);
5068 intf.DataDescription := GetDescriptionFromDevice(0, 0, 0);
5069 reader.ImageRead(aStream, intf);
5070 AssignFromLazIntfImage(intf);
5073 aStream.Position := StreamPos;
5082 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
5083 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5084 function TglBitmapData.LoadJPEG(const aStream: TStream): Boolean;
5086 Surface: PSDL_Surface;
5091 RWops := glBitmapCreateRWops(aStream);
5093 if IMG_isJPG(RWops) > 0 then begin
5094 Surface := IMG_LoadJPG_RW(RWops);
5096 AssignFromSurface(Surface);
5099 SDL_FreeSurface(Surface);
5107 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
5108 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5109 function TglBitmapData.LoadJPEG(const aStream: TStream): Boolean;
5112 Temp: array[0..1]of Byte;
5114 jpeg: jpeg_decompress_struct;
5115 jpeg_err: jpeg_error_mgr;
5117 IntFormat: TglBitmapFormat;
5119 TempHeight, TempWidth: Integer;
5124 FormatDesc: TFormatDescriptor;
5128 if not init_libJPEG then
5129 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
5132 // reading first two bytes to test file and set cursor back to begin
5133 StreamPos := aStream.Position;
5134 aStream.Read({%H-}Temp[0], 2);
5135 aStream.Position := StreamPos;
5137 // if Bitmap then read file.
5138 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
5139 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
5140 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
5143 jpeg.err := jpeg_std_error(@jpeg_err);
5144 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
5145 jpeg_err.output_message := glBitmap_libJPEG_output_message;
5147 // decompression struct
5148 jpeg_create_decompress(@jpeg);
5150 // allocation space for streaming methods
5151 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
5153 // seeting up custom functions
5154 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
5155 pub.init_source := glBitmap_libJPEG_init_source;
5156 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
5157 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
5158 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
5159 pub.term_source := glBitmap_libJPEG_term_source;
5161 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
5162 pub.next_input_byte := nil; // until buffer loaded
5164 SrcStream := aStream;
5167 // set global decoding state
5168 jpeg.global_state := DSTATE_START;
5170 // read header of jpeg
5171 jpeg_read_header(@jpeg, false);
5173 // setting output parameter
5174 case jpeg.jpeg_color_space of
5177 jpeg.out_color_space := JCS_GRAYSCALE;
5178 IntFormat := tfLuminance8ub1;
5181 jpeg.out_color_space := JCS_RGB;
5182 IntFormat := tfRGB8ub3;
5186 jpeg_start_decompress(@jpeg);
5188 TempHeight := jpeg.output_height;
5189 TempWidth := jpeg.output_width;
5191 FormatDesc := TFormatDescriptor.Get(IntFormat);
5193 // creating new image
5194 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
5198 for Row := 0 to TempHeight -1 do begin
5199 jpeg_read_scanlines(@jpeg, @pTemp, 1);
5200 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
5203 // finish decompression
5204 jpeg_finish_decompress(@jpeg);
5206 // destroy decompression
5207 jpeg_destroy_decompress(@jpeg);
5209 SetData(pImage, IntFormat, TempWidth, TempHeight);
5213 if Assigned(pImage) then
5223 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
5224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5225 function TglBitmapData.LoadJPEG(const aStream: TStream): Boolean;
5230 Temp: array[0..1]of Byte;
5234 // reading first two bytes to test file and set cursor back to begin
5235 StreamPos := aStream.Position;
5236 aStream.Read(Temp[0], 2);
5237 aStream.Position := StreamPos;
5239 // if Bitmap then read file.
5240 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
5241 bmp := TBitmap.Create;
5243 jpg := TJPEGImage.Create;
5245 jpg.LoadFromStream(aStream);
5247 result := AssignFromBitmap(bmp);
5259 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
5260 {$IF DEFINED(GLB_LAZ_JPEG)}
5261 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5262 procedure TglBitmapData.SaveJPEG(const aStream: TStream);
5265 intf: TLazIntfImage;
5268 jpeg := TJPEGImage.Create;
5269 intf := TLazIntfImage.Create(0, 0);
5271 if not AssignToLazIntfImage(intf) then
5272 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
5273 intf.GetRawImage(raw);
5274 jpeg.LoadFromRawImage(raw, false);
5275 jpeg.SaveToStream(aStream);
5282 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
5283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5284 procedure TglBitmapData.SaveJPEG(const aStream: TStream);
5286 jpeg: jpeg_compress_struct;
5287 jpeg_err: jpeg_error_mgr;
5289 pTemp, pTemp2: pByte;
5291 procedure CopyRow(pDest, pSource: pByte);
5295 for X := 0 to Width - 1 do begin
5296 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
5297 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
5298 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
5305 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
5306 raise EglBitmapUnsupportedFormat.Create(Format);
5308 if not init_libJPEG then
5309 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
5312 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
5313 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
5316 jpeg.err := jpeg_std_error(@jpeg_err);
5317 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
5318 jpeg_err.output_message := glBitmap_libJPEG_output_message;
5320 // compression struct
5321 jpeg_create_compress(@jpeg);
5323 // allocation space for streaming methods
5324 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
5326 // seeting up custom functions
5327 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
5328 pub.init_destination := glBitmap_libJPEG_init_destination;
5329 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
5330 pub.term_destination := glBitmap_libJPEG_term_destination;
5332 pub.next_output_byte := @DestBuffer[1];
5333 pub.free_in_buffer := Length(DestBuffer);
5335 DestStream := aStream;
5338 // very important state
5339 jpeg.global_state := CSTATE_START;
5340 jpeg.image_width := Width;
5341 jpeg.image_height := Height;
5343 tfAlpha8ub1, tfLuminance8ub1: begin
5344 jpeg.input_components := 1;
5345 jpeg.in_color_space := JCS_GRAYSCALE;
5347 tfRGB8ub3, tfBGR8ub3: begin
5348 jpeg.input_components := 3;
5349 jpeg.in_color_space := JCS_RGB;
5353 jpeg_set_defaults(@jpeg);
5354 jpeg_set_quality(@jpeg, 95, true);
5355 jpeg_start_compress(@jpeg, true);
5358 if Format = tfBGR8ub3 then
5359 GetMem(pTemp2, fRowSize)
5364 for Row := 0 to jpeg.image_height -1 do begin
5366 if Format = tfBGR8ub3 then
5367 CopyRow(pTemp2, pTemp)
5372 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
5373 inc(pTemp, fRowSize);
5377 if Format = tfBGR8ub3 then
5380 jpeg_finish_compress(@jpeg);
5381 jpeg_destroy_compress(@jpeg);
5387 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
5388 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5389 procedure TglBitmapData.SaveJPEG(const aStream: TStream);
5394 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
5395 raise EglBitmapUnsupportedFormat.Create(Format);
5397 Bmp := TBitmap.Create;
5399 Jpg := TJPEGImage.Create;
5401 AssignToBitmap(Bmp);
5402 if (Format in [tfAlpha8ub1, tfLuminance8ub1]) then begin
5403 Jpg.Grayscale := true;
5404 Jpg.PixelFormat := jf8Bit;
5407 Jpg.SaveToStream(aStream);
5418 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5419 //RAW/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5420 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5422 RawHeader = packed record
5428 BitsPerPixel: Integer;
5429 Precision: TglBitmapRec4ub;
5430 Shift: TglBitmapRec4ub;
5433 function TglBitmapData.LoadRAW(const aStream: TStream): Boolean;
5437 fd: TFormatDescriptor;
5441 StartPos := aStream.Position;
5442 aStream.Read(header{%H-}, SizeOf(header));
5443 if (header.Magic <> 'glBMP') then begin
5444 aStream.Position := StartPos;
5448 fd := TFormatDescriptor.GetFromPrecShift(header.Precision, header.Shift, header.BitsPerPixel);
5449 if (fd.Format = tfEmpty) then
5450 raise EglBitmapUnsupportedFormat.Create('no supported format found');
5452 buf := GetMemory(header.DataSize);
5453 aStream.Read(buf^, header.DataSize);
5454 SetData(buf, fd.Format, header.Width, header.Height);
5459 procedure TglBitmapData.SaveRAW(const aStream: TStream);
5462 fd: TFormatDescriptor;
5464 fd := TFormatDescriptor.Get(Format);
5465 header.Magic := 'glBMP';
5466 header.Version := 1;
5467 header.Width := Width;
5468 header.Height := Height;
5469 header.DataSize := fd.GetSize(fDimension);
5470 header.BitsPerPixel := fd.BitsPerPixel;
5471 header.Precision := fd.Precision;
5472 header.Shift := fd.Shift;
5473 aStream.Write(header, SizeOf(header));
5474 aStream.Write(Data^, header.DataSize);
5477 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5478 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5479 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5486 BMP_COMP_BITFIELDS = 3;
5489 TBMPHeader = packed record
5494 bfOffBits: Cardinal;
5497 TBMPInfo = packed record
5503 biCompression: Cardinal;
5504 biSizeImage: Cardinal;
5505 biXPelsPerMeter: Longint;
5506 biYPelsPerMeter: Longint;
5507 biClrUsed: Cardinal;
5508 biClrImportant: Cardinal;
5511 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5512 function TglBitmapData.LoadBMP(const aStream: TStream): Boolean;
5514 //////////////////////////////////////////////////////////////////////////////////////////////////
5515 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapRec4ul): TglBitmapFormat;
5520 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
5521 FillChar(aMask{%H-}, SizeOf(aMask), 0);
5524 case aInfo.biCompression of
5526 BMP_COMP_RLE8: begin
5527 raise EglBitmap.Create('RLE compression is not supported');
5529 BMP_COMP_BITFIELDS: begin
5530 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
5531 for i := 0 to 2 do begin
5532 aStream.Read(tmp{%H-}, SizeOf(tmp));
5533 aMask.arr[i] := tmp;
5536 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
5540 //get suitable format
5541 case aInfo.biBitCount of
5542 8: result := tfLuminance8ub1;
5543 16: result := tfX1RGB5us1;
5544 24: result := tfBGR8ub3;
5545 32: result := tfXRGB8ui1;
5549 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
5552 fd: TFormatDescriptor;
5553 ColorTable: TbmpColorTable;
5556 if (aInfo.biBitCount >= 16) then
5558 aFormat := tfLuminance8ub1;
5559 c := aInfo.biClrUsed;
5561 c := 1 shl aInfo.biBitCount;
5562 SetLength(ColorTable, c);
5563 for i := 0 to c-1 do begin
5564 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
5565 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
5566 aFormat := tfRGB8ub3;
5569 fd := TFormatDescriptor.Get(aFormat);
5570 result := TbmpColorTableFormat.Create;
5571 result.ColorTable := ColorTable;
5572 result.SetCustomValues(aFormat, aInfo.biBitCount, fd.Precision, fd.Shift);
5575 //////////////////////////////////////////////////////////////////////////////////////////////////
5576 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapRec4ul; const aInfo: TBMPInfo): TbmpBitfieldFormat;
5578 fd: TFormatDescriptor;
5581 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
5583 // find suitable format ...
5584 fd := TFormatDescriptor.GetFromMask(aMask);
5585 if (fd.Format <> tfEmpty) then begin
5586 aFormat := fd.Format;
5590 // or create custom bitfield format
5591 result := TbmpBitfieldFormat.Create;
5592 result.SetCustomValues(aInfo.biBitCount, aMask);
5599 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
5600 PaddingBuff: Cardinal;
5601 LineBuf, ImageData, TmpData: PByte;
5602 SourceMD, DestMD: Pointer;
5603 BmpFormat: TglBitmapFormat;
5606 Mask: TglBitmapRec4ul;
5611 SpecialFormat: TFormatDescriptor;
5612 FormatDesc: TFormatDescriptor;
5614 //////////////////////////////////////////////////////////////////////////////////////////////////
5615 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
5618 Pixel: TglBitmapPixelData;
5620 aStream.Read(aLineBuf^, rbLineSize);
5621 SpecialFormat.PreparePixel(Pixel);
5622 for i := 0 to Info.biWidth-1 do begin
5623 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
5624 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
5625 FormatDesc.Map(Pixel, aData, DestMD);
5631 BmpFormat := tfEmpty;
5632 SpecialFormat := nil;
5638 StartPos := aStream.Position;
5639 aStream.Read(Header{%H-}, SizeOf(Header));
5641 if Header.bfType = BMP_MAGIC then begin
5643 BmpFormat := ReadInfo(Info, Mask);
5644 SpecialFormat := ReadColorTable(BmpFormat, Info);
5645 if not Assigned(SpecialFormat) then
5646 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
5647 aStream.Position := StartPos + Header.bfOffBits;
5649 if (BmpFormat <> tfEmpty) then begin
5650 FormatDesc := TFormatDescriptor.Get(BmpFormat);
5651 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
5652 wbLineSize := Trunc(Info.biWidth * FormatDesc.BytesPerPixel);
5653 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
5656 DestMD := FormatDesc.CreateMappingData;
5657 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
5658 GetMem(ImageData, ImageSize);
5659 if Assigned(SpecialFormat) then begin
5660 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
5661 SourceMD := SpecialFormat.CreateMappingData;
5666 FillChar(ImageData^, ImageSize, $FF);
5667 TmpData := ImageData;
5668 if (Info.biHeight > 0) then
5669 Inc(TmpData, wbLineSize * (Info.biHeight-1));
5670 for i := 0 to Abs(Info.biHeight)-1 do begin
5671 if Assigned(SpecialFormat) then
5672 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
5674 aStream.Read(TmpData^, wbLineSize); //else only read data
5675 if (Info.biHeight > 0) then
5676 dec(TmpData, wbLineSize)
5678 inc(TmpData, wbLineSize);
5679 aStream.Read(PaddingBuff{%H-}, Padding);
5681 SetData(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight));
5684 if Assigned(LineBuf) then
5686 if Assigned(SourceMD) then
5687 SpecialFormat.FreeMappingData(SourceMD);
5688 FormatDesc.FreeMappingData(DestMD);
5691 if Assigned(ImageData) then
5696 raise EglBitmap.Create('LoadBMP - No suitable format found');
5698 aStream.Position := StartPos;
5702 FreeAndNil(SpecialFormat);
5705 else aStream.Position := StartPos;
5708 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5709 procedure TglBitmapData.SaveBMP(const aStream: TStream);
5713 Converter: TFormatDescriptor;
5714 FormatDesc: TFormatDescriptor;
5715 SourceFD, DestFD: Pointer;
5716 pData, srcData, dstData, ConvertBuffer: pByte;
5718 Pixel: TglBitmapPixelData;
5719 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
5720 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
5722 PaddingBuff: Cardinal;
5724 function GetLineWidth : Integer;
5726 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
5730 if not (ftBMP in FormatGetSupportedFiles(Format)) then
5731 raise EglBitmapUnsupportedFormat.Create(Format);
5734 FormatDesc := TFormatDescriptor.Get(Format);
5735 ImageSize := FormatDesc.GetSize(Dimension);
5737 FillChar(Header{%H-}, SizeOf(Header), 0);
5738 Header.bfType := BMP_MAGIC;
5739 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
5740 Header.bfReserved1 := 0;
5741 Header.bfReserved2 := 0;
5742 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
5744 FillChar(Info{%H-}, SizeOf(Info), 0);
5745 Info.biSize := SizeOf(Info);
5746 Info.biWidth := Width;
5747 Info.biHeight := Height;
5749 Info.biCompression := BMP_COMP_RGB;
5750 Info.biSizeImage := ImageSize;
5754 tfAlpha4ub1, tfAlpha8ub1, tfLuminance4ub1, tfLuminance8ub1, tfR3G3B2ub1:
5756 Info.biBitCount := 8;
5757 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
5758 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
5759 Converter := TbmpColorTableFormat.Create;
5760 with (Converter as TbmpColorTableFormat) do begin
5761 SetCustomValues(fFormat, 8, FormatDesc.Precision, FormatDesc.Shift);
5766 tfLuminance4Alpha4ub2, tfLuminance6Alpha2ub2, tfLuminance8Alpha8ub2,
5767 tfRGBX4us1, tfXRGB4us1, tfRGB5X1us1, tfX1RGB5us1, tfR5G6B5us1, tfRGB5A1us1, tfA1RGB5us1, tfRGBA4us1, tfARGB4us1,
5768 tfBGRX4us1, tfXBGR4us1, tfBGR5X1us1, tfX1BGR5us1, tfB5G6R5us1, tfBGR5A1us1, tfA1BGR5us1, tfBGRA4us1, tfABGR4us1:
5770 Info.biBitCount := 16;
5771 Info.biCompression := BMP_COMP_BITFIELDS;
5774 tfBGR8ub3, tfRGB8ub3:
5776 Info.biBitCount := 24;
5777 if (Format = tfRGB8ub3) then
5778 Converter := TfdBGR8ub3.Create; //use BGR8 Format Descriptor to Swap RGB Values
5781 tfRGBX8ui1, tfXRGB8ui1, tfRGB10X2ui1, tfX2RGB10ui1, tfRGBA8ui1, tfARGB8ui1, tfRGBA8ub4, tfRGB10A2ui1, tfA2RGB10ui1,
5782 tfBGRX8ui1, tfXBGR8ui1, tfBGR10X2ui1, tfX2BGR10ui1, tfBGRA8ui1, tfABGR8ui1, tfBGRA8ub4, tfBGR10A2ui1, tfA2BGR10ui1:
5784 Info.biBitCount := 32;
5785 Info.biCompression := BMP_COMP_BITFIELDS;
5788 raise EglBitmapUnsupportedFormat.Create(Format);
5790 Info.biXPelsPerMeter := 2835;
5791 Info.biYPelsPerMeter := 2835;
5794 if Info.biCompression = BMP_COMP_BITFIELDS then begin
5795 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
5796 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
5798 RedMask := FormatDesc.Mask.r;
5799 GreenMask := FormatDesc.Mask.g;
5800 BlueMask := FormatDesc.Mask.b;
5801 AlphaMask := FormatDesc.Mask.a;
5805 aStream.Write(Header, SizeOf(Header));
5806 aStream.Write(Info, SizeOf(Info));
5809 if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
5810 with (Converter as TbmpColorTableFormat) do
5811 aStream.Write(ColorTable[0].b,
5812 SizeOf(TbmpColorTableEnty) * Length(ColorTable));
5815 if Info.biCompression = BMP_COMP_BITFIELDS then begin
5816 aStream.Write(RedMask, SizeOf(Cardinal));
5817 aStream.Write(GreenMask, SizeOf(Cardinal));
5818 aStream.Write(BlueMask, SizeOf(Cardinal));
5819 aStream.Write(AlphaMask, SizeOf(Cardinal));
5823 rbLineSize := Round(Info.biWidth * FormatDesc.BytesPerPixel);
5824 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
5825 Padding := GetLineWidth - wbLineSize;
5829 inc(pData, (Height-1) * rbLineSize);
5831 // prepare row buffer. But only for RGB because RGBA supports color masks
5832 // so it's possible to change color within the image.
5833 if Assigned(Converter) then begin
5834 FormatDesc.PreparePixel(Pixel);
5835 GetMem(ConvertBuffer, wbLineSize);
5836 SourceFD := FormatDesc.CreateMappingData;
5837 DestFD := Converter.CreateMappingData;
5839 ConvertBuffer := nil;
5842 for LineIdx := 0 to Height - 1 do begin
5844 if Assigned(Converter) then begin
5846 dstData := ConvertBuffer;
5847 for PixelIdx := 0 to Info.biWidth-1 do begin
5848 FormatDesc.Unmap(srcData, Pixel, SourceFD);
5849 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
5850 Converter.Map(Pixel, dstData, DestFD);
5852 aStream.Write(ConvertBuffer^, wbLineSize);
5854 aStream.Write(pData^, rbLineSize);
5856 dec(pData, rbLineSize);
5857 if (Padding > 0) then
5858 aStream.Write(PaddingBuff, Padding);
5861 // destroy row buffer
5862 if Assigned(ConvertBuffer) then begin
5863 FormatDesc.FreeMappingData(SourceFD);
5864 Converter.FreeMappingData(DestFD);
5865 FreeMem(ConvertBuffer);
5869 if Assigned(Converter) then
5874 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5875 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5876 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5878 TTGAHeader = packed record
5882 //ColorMapSpec: Array[0..4] of Byte;
5883 ColorMapStart: Word;
5884 ColorMapLength: Word;
5885 ColorMapEntrySize: Byte;
5895 TGA_UNCOMPRESSED_RGB = 2;
5896 TGA_UNCOMPRESSED_GRAY = 3;
5897 TGA_COMPRESSED_RGB = 10;
5898 TGA_COMPRESSED_GRAY = 11;
5900 TGA_NONE_COLOR_TABLE = 0;
5902 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5903 function TglBitmapData.LoadTGA(const aStream: TStream): Boolean;
5906 ImageData: System.PByte;
5907 StartPosition: Int64;
5908 PixelSize, LineSize: Integer;
5909 tgaFormat: TglBitmapFormat;
5910 FormatDesc: TFormatDescriptor;
5911 Counter: packed record
5913 low, high, dir: Integer;
5920 ////////////////////////////////////////////////////////////////////////////////////////
5921 procedure ReadUncompressed;
5924 buf, tmp1, tmp2: System.PByte;
5927 if (Counter.X.dir < 0) then
5928 GetMem(buf, LineSize);
5930 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
5932 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
5933 if (Counter.X.dir < 0) then begin //flip X
5934 aStream.Read(buf^, LineSize);
5936 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
5937 for i := 0 to Header.Width-1 do begin //for all pixels in line
5938 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
5943 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
5946 aStream.Read(tmp1^, LineSize);
5947 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
5950 if Assigned(buf) then
5955 ////////////////////////////////////////////////////////////////////////////////////////
5956 procedure ReadCompressed;
5958 /////////////////////////////////////////////////////////////////
5960 TmpData: System.PByte;
5961 LinePixelsRead: Integer;
5962 procedure CheckLine;
5964 if (LinePixelsRead >= Header.Width) then begin
5965 LinePixelsRead := 0;
5966 inc(Counter.Y.low, Counter.Y.dir); //next line index
5967 TmpData := ImageData;
5968 inc(TmpData, Counter.Y.low * LineSize); //set line
5969 if (Counter.X.dir < 0) then //if x flipped then
5970 inc(TmpData, LineSize - PixelSize); //set last pixel
5974 /////////////////////////////////////////////////////////////////
5977 CacheSize, CachePos: Integer;
5978 procedure CachedRead(out Buffer; Count: Integer);
5982 if (CachePos + Count > CacheSize) then begin
5983 //if buffer overflow save non read bytes
5985 if (CacheSize - CachePos > 0) then begin
5986 BytesRead := CacheSize - CachePos;
5987 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
5988 inc(CachePos, BytesRead);
5991 //load cache from file
5992 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
5993 aStream.Read(Cache^, CacheSize);
5996 //read rest of requested bytes
5997 if (Count - BytesRead > 0) then begin
5998 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
5999 inc(CachePos, Count - BytesRead);
6002 //if no buffer overflow just read the data
6003 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
6004 inc(CachePos, Count);
6008 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
6013 inc(aBuffer, Counter.X.dir);
6016 PWord(aBuffer)^ := PWord(aData)^;
6017 inc(aBuffer, 2 * Counter.X.dir);
6020 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
6021 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
6022 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
6023 inc(aBuffer, 3 * Counter.X.dir);
6026 PCardinal(aBuffer)^ := PCardinal(aData)^;
6027 inc(aBuffer, 4 * Counter.X.dir);
6033 TotalPixelsToRead, TotalPixelsRead: Integer;
6035 buf: array [0..3] of Byte; //1 pixel is max 32bit long
6036 PixelRepeat: Boolean;
6037 PixelsToRead, PixelCount: Integer;
6042 TotalPixelsToRead := Header.Width * Header.Height;
6043 TotalPixelsRead := 0;
6044 LinePixelsRead := 0;
6046 GetMem(Cache, CACHE_SIZE);
6048 TmpData := ImageData;
6049 inc(TmpData, Counter.Y.low * LineSize); //set line
6050 if (Counter.X.dir < 0) then //if x flipped then
6051 inc(TmpData, LineSize - PixelSize); //set last pixel
6055 CachedRead(Temp, 1);
6056 PixelRepeat := (Temp and $80) > 0;
6057 PixelsToRead := (Temp and $7F) + 1;
6058 inc(TotalPixelsRead, PixelsToRead);
6061 CachedRead(buf[0], PixelSize);
6062 while (PixelsToRead > 0) do begin
6064 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
6065 while (PixelCount > 0) do begin
6066 if not PixelRepeat then
6067 CachedRead(buf[0], PixelSize);
6068 PixelToBuffer(@buf[0], TmpData);
6069 inc(LinePixelsRead);
6074 until (TotalPixelsRead >= TotalPixelsToRead);
6080 function IsGrayFormat: Boolean;
6082 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
6088 // reading header to test file and set cursor back to begin
6089 StartPosition := aStream.Position;
6090 aStream.Read(Header{%H-}, SizeOf(Header));
6092 // no colormapped files
6093 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
6094 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
6097 if Header.ImageID <> 0 then // skip image ID
6098 aStream.Position := aStream.Position + Header.ImageID;
6100 tgaFormat := tfEmpty;
6102 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
6103 0: tgaFormat := tfLuminance8ub1;
6104 8: tgaFormat := tfAlpha8ub1;
6107 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
6108 0: tgaFormat := tfLuminance16us1;
6109 8: tgaFormat := tfLuminance8Alpha8ub2;
6110 end else case (Header.ImageDesc and $F) of
6111 0: tgaFormat := tfX1RGB5us1;
6112 1: tgaFormat := tfA1RGB5us1;
6113 4: tgaFormat := tfARGB4us1;
6116 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6117 0: tgaFormat := tfBGR8ub3;
6120 32: if IsGrayFormat then case (Header.ImageDesc and $F) of
6121 0: tgaFormat := tfDepth32ui1;
6122 end else case (Header.ImageDesc and $F) of
6123 0: tgaFormat := tfX2RGB10ui1;
6124 2: tgaFormat := tfA2RGB10ui1;
6125 8: tgaFormat := tfARGB8ui1;
6129 if (tgaFormat = tfEmpty) then
6130 raise EglBitmap.Create('LoadTga - unsupported format');
6132 FormatDesc := TFormatDescriptor.Get(tgaFormat);
6133 PixelSize := FormatDesc.GetSize(1, 1);
6134 LineSize := FormatDesc.GetSize(Header.Width, 1);
6136 GetMem(ImageData, LineSize * Header.Height);
6139 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
6140 Counter.X.low := Header.Height-1;;
6141 Counter.X.high := 0;
6142 Counter.X.dir := -1;
6145 Counter.X.high := Header.Height-1;
6150 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
6152 Counter.Y.high := Header.Height-1;
6155 Counter.Y.low := Header.Height-1;;
6156 Counter.Y.high := 0;
6157 Counter.Y.dir := -1;
6161 case Header.ImageType of
6162 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
6164 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
6168 SetData(ImageData, tgaFormat, Header.Width, Header.Height);
6171 if Assigned(ImageData) then
6176 aStream.Position := StartPosition;
6179 else aStream.Position := StartPosition;
6182 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6183 procedure TglBitmapData.SaveTGA(const aStream: TStream);
6187 FormatDesc: TFormatDescriptor;
6189 if not (ftTGA in FormatGetSupportedFiles(Format)) then
6190 raise EglBitmapUnsupportedFormat.Create(Format);
6193 FormatDesc := TFormatDescriptor.Get(Format);
6194 FillChar(Header{%H-}, SizeOf(Header), 0);
6195 Header.ImageDesc := CountSetBits(FormatDesc.Range.a) and $F;
6196 Header.Bpp := FormatDesc.BitsPerPixel;
6197 Header.Width := Width;
6198 Header.Height := Height;
6199 Header.ImageDesc := Header.ImageDesc or $20; //flip y
6200 if FormatDesc.IsGrayscale or (not FormatDesc.IsGrayscale and not FormatDesc.HasRed and FormatDesc.HasAlpha) then
6201 Header.ImageType := TGA_UNCOMPRESSED_GRAY
6203 Header.ImageType := TGA_UNCOMPRESSED_RGB;
6204 aStream.Write(Header, SizeOf(Header));
6207 Size := FormatDesc.GetSize(Dimension);
6208 aStream.Write(Data^, Size);
6211 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6212 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6213 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6215 DDS_MAGIC: Cardinal = $20534444;
6217 // DDS_header.dwFlags
6218 DDSD_CAPS = $00000001;
6219 DDSD_HEIGHT = $00000002;
6220 DDSD_WIDTH = $00000004;
6221 DDSD_PIXELFORMAT = $00001000;
6223 // DDS_header.sPixelFormat.dwFlags
6224 DDPF_ALPHAPIXELS = $00000001;
6225 DDPF_ALPHA = $00000002;
6226 DDPF_FOURCC = $00000004;
6227 DDPF_RGB = $00000040;
6228 DDPF_LUMINANCE = $00020000;
6230 // DDS_header.sCaps.dwCaps1
6231 DDSCAPS_TEXTURE = $00001000;
6233 // DDS_header.sCaps.dwCaps2
6234 DDSCAPS2_CUBEMAP = $00000200;
6236 D3DFMT_DXT1 = $31545844;
6237 D3DFMT_DXT3 = $33545844;
6238 D3DFMT_DXT5 = $35545844;
6241 TDDSPixelFormat = packed record
6245 dwRGBBitCount: Cardinal;
6246 dwRBitMask: Cardinal;
6247 dwGBitMask: Cardinal;
6248 dwBBitMask: Cardinal;
6249 dwABitMask: Cardinal;
6252 TDDSCaps = packed record
6256 dwReserved: Cardinal;
6259 TDDSHeader = packed record
6264 dwPitchOrLinearSize: Cardinal;
6266 dwMipMapCount: Cardinal;
6267 dwReserved: array[0..10] of Cardinal;
6268 PixelFormat: TDDSPixelFormat;
6270 dwReserved2: Cardinal;
6273 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6274 function TglBitmapData.LoadDDS(const aStream: TStream): Boolean;
6277 Converter: TbmpBitfieldFormat;
6279 function GetDDSFormat: TglBitmapFormat;
6281 fd: TFormatDescriptor;
6283 Mask: TglBitmapRec4ul;
6284 Range: TglBitmapRec4ui;
6288 with Header.PixelFormat do begin
6290 if ((dwFlags and DDPF_FOURCC) > 0) then begin
6291 case Header.PixelFormat.dwFourCC of
6292 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
6293 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
6294 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
6296 end else if ((dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE or DDPF_ALPHA)) > 0) then begin
6298 if ((dwFlags and DDPF_LUMINANCE) = 0) then begin
6299 Mask.r := dwRBitMask;
6300 Mask.g := dwGBitMask;
6301 Mask.b := dwBBitMask;
6303 Mask.r := dwRBitMask;
6304 Mask.g := dwRBitMask;
6305 Mask.b := dwRBitMask;
6307 if (dwFlags and DDPF_ALPHAPIXELS > 0) then
6308 Mask.a := dwABitMask
6312 //find matching format
6313 fd := TFormatDescriptor.GetFromMask(Mask, dwRGBBitCount);
6314 result := fd.Format;
6315 if (result <> tfEmpty) then
6318 //find format with same Range
6320 Range.arr[i] := (2 shl CountSetBits(Mask.arr[i])) - 1;
6321 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6322 fd := TFormatDescriptor.Get(result);
6325 if (fd.Range.arr[i] <> Range.arr[i]) then begin
6333 //no format with same range found -> use default
6334 if (result = tfEmpty) then begin
6335 if (dwABitMask > 0) then
6336 result := tfRGBA8ui1
6338 result := tfRGB8ub3;
6341 Converter := TbmpBitfieldFormat.Create;
6342 Converter.SetCustomValues(dwRGBBitCount, glBitmapRec4ul(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask));
6349 x, y, LineSize, RowSize, Magic: Cardinal;
6350 NewImage, TmpData, RowData, SrcData: System.PByte;
6351 SourceMD, DestMD: Pointer;
6352 Pixel: TglBitmapPixelData;
6353 ddsFormat: TglBitmapFormat;
6354 FormatDesc: TFormatDescriptor;
6359 StreamPos := aStream.Position;
6362 aStream.Read(Magic{%H-}, sizeof(Magic));
6363 if (Magic <> DDS_MAGIC) then begin
6364 aStream.Position := StreamPos;
6369 aStream.Read(Header{%H-}, sizeof(Header));
6370 if (Header.dwSize <> SizeOf(Header)) or
6371 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
6372 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
6374 aStream.Position := StreamPos;
6378 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
6379 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
6381 ddsFormat := GetDDSFormat;
6383 if (ddsFormat = tfEmpty) then
6384 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
6386 FormatDesc := TFormatDescriptor.Get(ddsFormat);
6387 LineSize := Trunc(Header.dwWidth * FormatDesc.BytesPerPixel);
6388 GetMem(NewImage, Header.dwHeight * LineSize);
6390 TmpData := NewImage;
6393 if Assigned(Converter) then begin
6394 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
6395 GetMem(RowData, RowSize);
6396 SourceMD := Converter.CreateMappingData;
6397 DestMD := FormatDesc.CreateMappingData;
6399 for y := 0 to Header.dwHeight-1 do begin
6400 TmpData := NewImage;
6401 inc(TmpData, y * LineSize);
6403 aStream.Read(SrcData^, RowSize);
6404 for x := 0 to Header.dwWidth-1 do begin
6405 Converter.Unmap(SrcData, Pixel, SourceMD);
6406 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
6407 FormatDesc.Map(Pixel, TmpData, DestMD);
6411 Converter.FreeMappingData(SourceMD);
6412 FormatDesc.FreeMappingData(DestMD);
6418 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
6419 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
6420 for Y := 0 to Header.dwHeight-1 do begin
6421 aStream.Read(TmpData^, RowSize);
6422 Inc(TmpData, LineSize);
6427 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
6428 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
6429 for Y := 0 to Header.dwHeight-1 do begin
6430 aStream.Read(TmpData^, RowSize);
6431 Inc(TmpData, LineSize);
6434 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
6436 SetData(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
6439 if Assigned(NewImage) then
6444 FreeAndNil(Converter);
6448 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6449 procedure TglBitmapData.SaveDDS(const aStream: TStream);
6452 FormatDesc: TFormatDescriptor;
6454 if not (ftDDS in FormatGetSupportedFiles(Format)) then
6455 raise EglBitmapUnsupportedFormat.Create(Format);
6457 FormatDesc := TFormatDescriptor.Get(Format);
6460 FillChar(Header{%H-}, SizeOf(Header), 0);
6461 Header.dwSize := SizeOf(Header);
6462 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
6464 Header.dwWidth := Max(1, Width);
6465 Header.dwHeight := Max(1, Height);
6468 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
6471 Header.PixelFormat.dwSize := sizeof(Header);
6472 if (FormatDesc.IsCompressed) then begin
6473 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
6475 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
6476 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
6477 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
6479 end else if not FormatDesc.HasColor and FormatDesc.HasAlpha then begin
6480 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
6481 Header.PixelFormat.dwRGBBitCount := FormatDesc.BitsPerPixel;
6482 Header.PixelFormat.dwABitMask := FormatDesc.Mask.a;
6483 end else if FormatDesc.IsGrayscale then begin
6484 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
6485 Header.PixelFormat.dwRGBBitCount := FormatDesc.BitsPerPixel;
6486 Header.PixelFormat.dwRBitMask := FormatDesc.Mask.r;
6487 Header.PixelFormat.dwABitMask := FormatDesc.Mask.a;
6489 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
6490 Header.PixelFormat.dwRGBBitCount := FormatDesc.BitsPerPixel;
6491 Header.PixelFormat.dwRBitMask := FormatDesc.Mask.r;
6492 Header.PixelFormat.dwGBitMask := FormatDesc.Mask.g;
6493 Header.PixelFormat.dwBBitMask := FormatDesc.Mask.b;
6494 Header.PixelFormat.dwABitMask := FormatDesc.Mask.a;
6497 if (FormatDesc.HasAlpha) then
6498 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
6500 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
6501 aStream.Write(Header, SizeOf(Header));
6502 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
6505 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6506 function TglBitmapData.FlipHorz: Boolean;
6508 fd: TglBitmapFormatDescriptor;
6509 Col, RowSize, PixelSize: Integer;
6510 pTempDest, pDest, pSource: PByte;
6513 fd := FormatDescriptor;
6514 PixelSize := Ceil(fd.BytesPerPixel);
6515 RowSize := fd.GetSize(Width, 1);
6516 if Assigned(Data) and not fd.IsCompressed then begin
6518 GetMem(pDest, RowSize);
6521 Inc(pTempDest, RowSize);
6522 for Col := 0 to Width-1 do begin
6523 dec(pTempDest, PixelSize); //dec before, because ptr is behind last byte of data
6524 Move(pSource^, pTempDest^, PixelSize);
6525 Inc(pSource, PixelSize);
6527 SetData(pDest, Format, Width);
6530 if Assigned(pDest) then
6537 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6538 function TglBitmapData.FlipVert: Boolean;
6540 fd: TglBitmapFormatDescriptor;
6541 Row, RowSize, PixelSize: Integer;
6542 TempDestData, DestData, SourceData: PByte;
6545 fd := FormatDescriptor;
6546 PixelSize := Ceil(fd.BytesPerPixel);
6547 RowSize := fd.GetSize(Width, 1);
6548 if Assigned(Data) then begin
6550 GetMem(DestData, Height * RowSize);
6552 TempDestData := DestData;
6553 Inc(TempDestData, Width * (Height -1) * PixelSize);
6554 for Row := 0 to Height -1 do begin
6555 Move(SourceData^, TempDestData^, RowSize);
6556 Dec(TempDestData, RowSize);
6557 Inc(SourceData, RowSize);
6559 SetData(DestData, Format, Width, Height);
6562 if Assigned(DestData) then
6569 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6570 procedure TglBitmapData.LoadFromFile(const aFilename: String);
6574 if not FileExists(aFilename) then
6575 raise EglBitmap.Create('file does not exist: ' + aFilename);
6576 fs := TFileStream.Create(aFilename, fmOpenRead);
6580 fFilename := aFilename;
6586 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6587 procedure TglBitmapData.LoadFromStream(const aStream: TStream);
6589 {$IFDEF GLB_SUPPORT_PNG_READ}
6590 if not LoadPNG(aStream) then
6592 {$IFDEF GLB_SUPPORT_JPEG_READ}
6593 if not LoadJPEG(aStream) then
6595 if not LoadDDS(aStream) then
6596 if not LoadTGA(aStream) then
6597 if not LoadBMP(aStream) then
6598 if not LoadRAW(aStream) then
6599 raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
6602 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6603 procedure TglBitmapData.LoadFromFunc(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat;
6604 const aFunc: TglBitmapFunction; const aArgs: Pointer);
6609 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
6610 GetMem(tmpData, size);
6612 FillChar(tmpData^, size, #$FF);
6613 SetData(tmpData, aFormat, aSize.X, aSize.Y);
6615 if Assigned(tmpData) then
6619 Convert(Self, aFunc, false, aFormat, aArgs);
6622 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6623 procedure TglBitmapData.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
6625 rs: TResourceStream;
6627 PrepareResType(aResource, aResType);
6628 rs := TResourceStream.Create(aInstance, aResource, aResType);
6636 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6637 procedure TglBitmapData.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
6639 rs: TResourceStream;
6641 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
6649 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6650 procedure TglBitmapData.SaveToFile(const aFilename: String; const aFileType: TglBitmapFileType);
6654 fs := TFileStream.Create(aFileName, fmCreate);
6657 SaveToStream(fs, aFileType);
6663 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6664 procedure TglBitmapData.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
6667 {$IFDEF GLB_SUPPORT_PNG_WRITE}
6668 ftPNG: SavePNG(aStream);
6670 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6671 ftJPEG: SaveJPEG(aStream);
6673 ftDDS: SaveDDS(aStream);
6674 ftTGA: SaveTGA(aStream);
6675 ftBMP: SaveBMP(aStream);
6676 ftRAW: SaveRAW(aStream);
6680 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6681 function TglBitmapData.Convert(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
6683 result := Convert(Self, aFunc, aCreateTemp, Format, aArgs);
6686 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6687 function TglBitmapData.Convert(const aSource: TglBitmapData; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
6688 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
6690 DestData, TmpData, SourceData: pByte;
6691 TempHeight, TempWidth: Integer;
6692 SourceFD, DestFD: TFormatDescriptor;
6693 SourceMD, DestMD: Pointer;
6695 FuncRec: TglBitmapFunctionRec;
6697 Assert(Assigned(Data));
6698 Assert(Assigned(aSource));
6699 Assert(Assigned(aSource.Data));
6702 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
6703 SourceFD := TFormatDescriptor.Get(aSource.Format);
6704 DestFD := TFormatDescriptor.Get(aFormat);
6706 if (SourceFD.IsCompressed) then
6707 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
6708 if (DestFD.IsCompressed) then
6709 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
6711 // inkompatible Formats so CreateTemp
6712 if (SourceFD.BitsPerPixel <> DestFD.BitsPerPixel) then
6713 aCreateTemp := true;
6716 TempHeight := Max(1, aSource.Height);
6717 TempWidth := Max(1, aSource.Width);
6719 FuncRec.Sender := Self;
6720 FuncRec.Args := aArgs;
6723 if aCreateTemp then begin
6724 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
6725 DestData := TmpData;
6730 SourceFD.PreparePixel(FuncRec.Source);
6731 DestFD.PreparePixel (FuncRec.Dest);
6733 SourceMD := SourceFD.CreateMappingData;
6734 DestMD := DestFD.CreateMappingData;
6736 FuncRec.Size := aSource.Dimension;
6737 FuncRec.Position.Fields := FuncRec.Size.Fields;
6740 SourceData := aSource.Data;
6741 FuncRec.Position.Y := 0;
6742 while FuncRec.Position.Y < TempHeight do begin
6743 FuncRec.Position.X := 0;
6744 while FuncRec.Position.X < TempWidth do begin
6745 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
6747 DestFD.Map(FuncRec.Dest, DestData, DestMD);
6748 inc(FuncRec.Position.X);
6750 inc(FuncRec.Position.Y);
6753 // Updating Image or InternalFormat
6755 SetData(TmpData, aFormat, aSource.Width, aSource.Height)
6756 else if (aFormat <> fFormat) then
6761 SourceFD.FreeMappingData(SourceMD);
6762 DestFD.FreeMappingData(DestMD);
6765 if aCreateTemp and Assigned(TmpData) then
6772 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6773 function TglBitmapData.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
6775 SourceFD, DestFD: TFormatDescriptor;
6776 SourcePD, DestPD: TglBitmapPixelData;
6777 ShiftData: TShiftData;
6779 function DataIsIdentical: Boolean;
6781 result := SourceFD.MaskMatch(DestFD.Mask);
6784 function CanCopyDirect: Boolean;
6787 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
6788 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
6789 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
6790 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
6793 function CanShift: Boolean;
6796 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
6797 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
6798 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
6799 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
6802 function GetShift(aSource, aDest: Cardinal) : ShortInt;
6805 while (aSource > aDest) and (aSource > 0) do begin
6807 aSource := aSource shr 1;
6812 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
6813 SourceFD := TFormatDescriptor.Get(Format);
6814 DestFD := TFormatDescriptor.Get(aFormat);
6816 if DataIsIdentical then begin
6822 SourceFD.PreparePixel(SourcePD);
6823 DestFD.PreparePixel (DestPD);
6825 if CanCopyDirect then
6826 result := Convert(Self, glBitmapConvertCopyFunc, false, aFormat)
6827 else if CanShift then begin
6828 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
6829 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
6830 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
6831 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
6832 result := Convert(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
6834 result := Convert(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
6840 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6841 function TglBitmapData.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
6843 Row, RowSize: Integer;
6844 SourceData, TmpData: PByte;
6846 FormatDesc: TFormatDescriptor;
6848 function GetRowPointer(Row: Integer): pByte;
6850 result := aSurface.pixels;
6851 Inc(result, Row * RowSize);
6857 FormatDesc := TFormatDescriptor.Get(Format);
6858 if FormatDesc.IsCompressed then
6859 raise EglBitmapUnsupportedFormat.Create(Format);
6861 if Assigned(Data) then begin
6862 case Trunc(FormatDesc.PixelSize) of
6868 raise EglBitmapUnsupportedFormat.Create(Format);
6871 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
6872 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
6874 RowSize := FormatDesc.GetSize(FileWidth, 1);
6876 for Row := 0 to FileHeight-1 do begin
6877 TmpData := GetRowPointer(Row);
6878 if Assigned(TmpData) then begin
6879 Move(SourceData^, TmpData^, RowSize);
6880 inc(SourceData, RowSize);
6887 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6888 function TglBitmapData.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
6890 pSource, pData, pTempData: PByte;
6891 Row, RowSize, TempWidth, TempHeight: Integer;
6892 IntFormat: TglBitmapFormat;
6893 fd: TFormatDescriptor;
6894 Mask: TglBitmapMask;
6896 function GetRowPointer(Row: Integer): pByte;
6898 result := aSurface^.pixels;
6899 Inc(result, Row * RowSize);
6904 if (Assigned(aSurface)) then begin
6905 with aSurface^.format^ do begin
6910 IntFormat := TFormatDescriptor.GetFromMask(Mask).Format;
6911 if (IntFormat = tfEmpty) then
6912 raise EglBitmap.Create('AssignFromSurface - Invalid Pixelformat.');
6915 fd := TFormatDescriptor.Get(IntFormat);
6916 TempWidth := aSurface^.w;
6917 TempHeight := aSurface^.h;
6918 RowSize := fd.GetSize(TempWidth, 1);
6919 GetMem(pData, TempHeight * RowSize);
6922 for Row := 0 to TempHeight -1 do begin
6923 pSource := GetRowPointer(Row);
6924 if (Assigned(pSource)) then begin
6925 Move(pSource^, pTempData^, RowSize);
6926 Inc(pTempData, RowSize);
6929 SetData(pData, IntFormat, TempWidth, TempHeight);
6932 if Assigned(pData) then
6939 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6940 function TglBitmapData.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
6942 Row, Col, AlphaInterleave: Integer;
6943 pSource, pDest: PByte;
6945 function GetRowPointer(Row: Integer): pByte;
6947 result := aSurface.pixels;
6948 Inc(result, Row * Width);
6953 if Assigned(Data) then begin
6954 if Format in [tfAlpha8ub1, tfLuminance8Alpha8ub2, tfBGRA8ub4, tfRGBA8ub4] then begin
6955 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
6957 AlphaInterleave := 0;
6959 tfLuminance8Alpha8ub2:
6960 AlphaInterleave := 1;
6961 tfBGRA8ub4, tfRGBA8ub4:
6962 AlphaInterleave := 3;
6966 for Row := 0 to Height -1 do begin
6967 pDest := GetRowPointer(Row);
6968 if Assigned(pDest) then begin
6969 for Col := 0 to Width -1 do begin
6970 Inc(pSource, AlphaInterleave);
6982 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6983 function TglBitmapData.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
6987 bmp := TglBitmap2D.Create;
6989 bmp.AssignFromSurface(aSurface);
6990 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
6998 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6999 function CreateGrayPalette: HPALETTE;
7004 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
7006 Pal.palVersion := $300;
7007 Pal.palNumEntries := 256;
7009 for Idx := 0 to Pal.palNumEntries - 1 do begin
7010 Pal.palPalEntry[Idx].peRed := Idx;
7011 Pal.palPalEntry[Idx].peGreen := Idx;
7012 Pal.palPalEntry[Idx].peBlue := Idx;
7013 Pal.palPalEntry[Idx].peFlags := 0;
7015 Result := CreatePalette(Pal^);
7019 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7020 function TglBitmapData.AssignToBitmap(const aBitmap: TBitmap): Boolean;
7022 Row, RowSize: Integer;
7023 pSource, pData: PByte;
7026 if Assigned(Data) then begin
7027 if Assigned(aBitmap) then begin
7028 aBitmap.Width := Width;
7029 aBitmap.Height := Height;
7032 tfAlpha8ub1, tfLuminance8ub1: begin
7033 aBitmap.PixelFormat := pf8bit;
7034 aBitmap.Palette := CreateGrayPalette;
7037 aBitmap.PixelFormat := pf15bit;
7039 aBitmap.PixelFormat := pf16bit;
7040 tfRGB8ub3, tfBGR8ub3:
7041 aBitmap.PixelFormat := pf24bit;
7042 tfRGBA8ub4, tfBGRA8ub4:
7043 aBitmap.PixelFormat := pf32bit;
7045 raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.');
7048 RowSize := FormatDescriptor.GetSize(Width, 1);
7050 for Row := 0 to Height-1 do begin
7051 pData := aBitmap.Scanline[Row];
7052 Move(pSource^, pData^, RowSize);
7053 Inc(pSource, RowSize);
7054 if (Format in [tfRGB8ub3, tfRGBA8ub4]) then // swap RGB(A) to BGR(A)
7055 SwapRGB(pData, Width, Format = tfRGBA8ub4);
7062 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7063 function TglBitmapData.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
7065 pSource, pData, pTempData: PByte;
7066 Row, RowSize, TempWidth, TempHeight: Integer;
7067 IntFormat: TglBitmapFormat;
7071 if (Assigned(aBitmap)) then begin
7072 case aBitmap.PixelFormat of
7074 IntFormat := tfLuminance8ub1;
7076 IntFormat := tfRGB5A1us1;
7078 IntFormat := tfR5G6B5us1;
7080 IntFormat := tfBGR8ub3;
7082 IntFormat := tfBGRA8ub4;
7084 raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.');
7087 TempWidth := aBitmap.Width;
7088 TempHeight := aBitmap.Height;
7089 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
7090 GetMem(pData, TempHeight * RowSize);
7093 for Row := 0 to TempHeight -1 do begin
7094 pSource := aBitmap.Scanline[Row];
7095 if (Assigned(pSource)) then begin
7096 Move(pSource^, pTempData^, RowSize);
7097 Inc(pTempData, RowSize);
7100 SetData(pData, IntFormat, TempWidth, TempHeight);
7103 if Assigned(pData) then
7110 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7111 function TglBitmapData.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
7113 Row, Col, AlphaInterleave: Integer;
7114 pSource, pDest: PByte;
7118 if Assigned(Data) then begin
7119 if (Format in [tfAlpha8ub1, tfLuminance8Alpha8ub2, tfRGBA8ub4, tfBGRA8ub4]) then begin
7120 if Assigned(aBitmap) then begin
7121 aBitmap.PixelFormat := pf8bit;
7122 aBitmap.Palette := CreateGrayPalette;
7123 aBitmap.Width := Width;
7124 aBitmap.Height := Height;
7127 tfLuminance8Alpha8ub2:
7128 AlphaInterleave := 1;
7129 tfRGBA8ub4, tfBGRA8ub4:
7130 AlphaInterleave := 3;
7132 AlphaInterleave := 0;
7138 for Row := 0 to Height -1 do begin
7139 pDest := aBitmap.Scanline[Row];
7140 if Assigned(pDest) then begin
7141 for Col := 0 to Width -1 do begin
7142 Inc(pSource, AlphaInterleave);
7155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7156 function TglBitmapData.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7158 data: TglBitmapData;
7160 data := TglBitmapData.Create;
7162 data.AssignFromBitmap(aBitmap);
7163 result := AddAlphaFromDataObj(data, aFunc, aArgs);
7170 {$IFDEF GLB_LAZARUS}
7171 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7172 function TglBitmapData.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
7174 rid: TRawImageDescription;
7175 FormatDesc: TFormatDescriptor;
7177 if not Assigned(Data) then
7178 raise EglBitmap.Create('no pixel data assigned. load data before save');
7181 if not Assigned(aImage) or (Format = tfEmpty) then
7183 FormatDesc := TFormatDescriptor.Get(Format);
7184 if FormatDesc.IsCompressed then
7187 FillChar(rid{%H-}, SizeOf(rid), 0);
7188 if FormatDesc.IsGrayscale then
7189 rid.Format := ricfGray
7191 rid.Format := ricfRGBA;
7194 rid.Height := Height;
7195 rid.Depth := FormatDesc.BitsPerPixel;
7196 rid.BitOrder := riboBitsInOrder;
7197 rid.ByteOrder := riboLSBFirst;
7198 rid.LineOrder := riloTopToBottom;
7199 rid.LineEnd := rileTight;
7200 rid.BitsPerPixel := FormatDesc.BitsPerPixel;
7201 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
7202 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
7203 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
7204 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
7205 rid.RedShift := FormatDesc.Shift.r;
7206 rid.GreenShift := FormatDesc.Shift.g;
7207 rid.BlueShift := FormatDesc.Shift.b;
7208 rid.AlphaShift := FormatDesc.Shift.a;
7210 rid.MaskBitsPerPixel := 0;
7211 rid.PaletteColorCount := 0;
7213 aImage.DataDescription := rid;
7216 if not Assigned(aImage.PixelData) then
7217 raise EglBitmap.Create('error while creating LazIntfImage');
7218 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
7223 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7224 function TglBitmapData.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
7227 FormatDesc: TFormatDescriptor;
7231 Mask: TglBitmapRec4ul;
7233 procedure CopyConvert;
7235 bfFormat: TbmpBitfieldFormat;
7236 pSourceLine, pDestLine: PByte;
7237 pSourceMD, pDestMD: Pointer;
7238 Shift, Prec: TglBitmapRec4ub;
7240 pixel: TglBitmapPixelData;
7242 bfFormat := TbmpBitfieldFormat.Create;
7243 with aImage.DataDescription do begin
7245 Prec.g := GreenPrec;
7247 Prec.a := AlphaPrec;
7248 Shift.r := RedShift;
7249 Shift.g := GreenShift;
7250 Shift.b := BlueShift;
7251 Shift.a := AlphaShift;
7252 bfFormat.SetCustomValues(BitsPerPixel, Prec, Shift);
7254 pSourceMD := bfFormat.CreateMappingData;
7255 pDestMD := FormatDesc.CreateMappingData;
7257 for y := 0 to aImage.Height-1 do begin
7258 pSourceLine := aImage.PixelData + y {%H-}* aImage.DataDescription.BytesPerLine;
7259 pDestLine := ImageData + y * Round(FormatDesc.BytesPerPixel * aImage.Width);
7260 for x := 0 to aImage.Width-1 do begin
7261 bfFormat.Unmap(pSourceLine, pixel, pSourceMD);
7262 FormatDesc.Map(pixel, pDestLine, pDestMD);
7266 FormatDesc.FreeMappingData(pDestMD);
7267 bfFormat.FreeMappingData(pSourceMD);
7274 if not Assigned(aImage) then
7277 with aImage.DataDescription do begin
7278 Mask.r := (QWord(1 shl RedPrec )-1) shl RedShift;
7279 Mask.g := (QWord(1 shl GreenPrec)-1) shl GreenShift;
7280 Mask.b := (QWord(1 shl BluePrec )-1) shl BlueShift;
7281 Mask.a := (QWord(1 shl AlphaPrec)-1) shl AlphaShift;
7283 FormatDesc := TFormatDescriptor.GetFromMask(Mask);
7284 f := FormatDesc.Format;
7285 if (f = tfEmpty) then
7289 (FormatDesc.BitsPerPixel = aImage.DataDescription.Depth) and
7290 (aImage.DataDescription.BitsPerPixel = aImage.DataDescription.Depth);
7292 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
7293 ImageData := GetMem(ImageSize);
7296 Move(aImage.PixelData^, ImageData^, ImageSize)
7299 SetData(ImageData, f, aImage.Width, aImage.Height);
7301 if Assigned(ImageData) then
7309 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7310 function TglBitmapData.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
7312 rid: TRawImageDescription;
7313 FormatDesc: TFormatDescriptor;
7314 Pixel: TglBitmapPixelData;
7320 if not Assigned(aImage) or (Format = tfEmpty) then
7322 FormatDesc := TFormatDescriptor.Get(Format);
7323 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
7326 FillChar(rid{%H-}, SizeOf(rid), 0);
7327 rid.Format := ricfGray;
7329 rid.Height := Height;
7330 rid.Depth := CountSetBits(FormatDesc.Range.a);
7331 rid.BitOrder := riboBitsInOrder;
7332 rid.ByteOrder := riboLSBFirst;
7333 rid.LineOrder := riloTopToBottom;
7334 rid.LineEnd := rileTight;
7335 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
7336 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
7341 rid.GreenShift := 0;
7343 rid.AlphaShift := 0;
7345 rid.MaskBitsPerPixel := 0;
7346 rid.PaletteColorCount := 0;
7348 aImage.DataDescription := rid;
7351 srcMD := FormatDesc.CreateMappingData;
7353 FormatDesc.PreparePixel(Pixel);
7355 dst := aImage.PixelData;
7356 for y := 0 to Height-1 do
7357 for x := 0 to Width-1 do begin
7358 FormatDesc.Unmap(src, Pixel, srcMD);
7359 case rid.BitsPerPixel of
7361 dst^ := Pixel.Data.a;
7365 PWord(dst)^ := Pixel.Data.a;
7369 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
7370 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
7371 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
7375 PCardinal(dst)^ := Pixel.Data.a;
7379 raise EglBitmapUnsupportedFormat.Create(Format);
7383 FormatDesc.FreeMappingData(srcMD);
7388 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7389 function TglBitmapData.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7391 data: TglBitmapData;
7393 data := TglBitmapData.Create;
7395 data.AssignFromLazIntfImage(aImage);
7396 result := AddAlphaFromDataObj(data, aFunc, aArgs);
7403 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7404 function TglBitmapData.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
7405 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7407 rs: TResourceStream;
7409 PrepareResType(aResource, aResType);
7410 rs := TResourceStream.Create(aInstance, aResource, aResType);
7412 result := AddAlphaFromStream(rs, aFunc, aArgs);
7418 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7419 function TglBitmapData.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
7420 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7422 rs: TResourceStream;
7424 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
7426 result := AddAlphaFromStream(rs, aFunc, aArgs);
7432 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7433 function TglBitmapData.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7435 if TFormatDescriptor.Get(Format).IsCompressed then
7436 raise EglBitmapUnsupportedFormat.Create(Format);
7437 result := Convert(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
7440 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7441 function TglBitmapData.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7445 FS := TFileStream.Create(aFileName, fmOpenRead);
7447 result := AddAlphaFromStream(FS, aFunc, aArgs);
7453 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7454 function TglBitmapData.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7456 data: TglBitmapData;
7458 data := TglBitmapData.Create(aStream);
7460 result := AddAlphaFromDataObj(data, aFunc, aArgs);
7466 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7467 function TglBitmapData.AddAlphaFromDataObj(const aDataObj: TglBitmapData; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7469 DestData, DestData2, SourceData: pByte;
7470 TempHeight, TempWidth: Integer;
7471 SourceFD, DestFD: TFormatDescriptor;
7472 SourceMD, DestMD, DestMD2: Pointer;
7474 FuncRec: TglBitmapFunctionRec;
7478 Assert(Assigned(Data));
7479 Assert(Assigned(aDataObj));
7480 Assert(Assigned(aDataObj.Data));
7482 if ((aDataObj.Width = Width) and (aDataObj.Height = Height)) then begin
7483 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
7485 SourceFD := TFormatDescriptor.Get(aDataObj.Format);
7486 DestFD := TFormatDescriptor.Get(Format);
7488 if not Assigned(aFunc) then begin
7489 aFunc := glBitmapAlphaFunc;
7490 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
7492 FuncRec.Args := aArgs;
7495 TempWidth := aDataObj.Width;
7496 TempHeight := aDataObj.Height;
7497 if (TempWidth <= 0) or (TempHeight <= 0) then
7500 FuncRec.Sender := Self;
7501 FuncRec.Size := Dimension;
7502 FuncRec.Position.Fields := FuncRec.Size.Fields;
7506 SourceData := aDataObj.Data;
7509 SourceFD.PreparePixel(FuncRec.Source);
7510 DestFD.PreparePixel (FuncRec.Dest);
7512 SourceMD := SourceFD.CreateMappingData;
7513 DestMD := DestFD.CreateMappingData;
7514 DestMD2 := DestFD.CreateMappingData;
7516 FuncRec.Position.Y := 0;
7517 while FuncRec.Position.Y < TempHeight do begin
7518 FuncRec.Position.X := 0;
7519 while FuncRec.Position.X < TempWidth do begin
7520 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
7521 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
7523 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
7524 inc(FuncRec.Position.X);
7526 inc(FuncRec.Position.Y);
7529 SourceFD.FreeMappingData(SourceMD);
7530 DestFD.FreeMappingData(DestMD);
7531 DestFD.FreeMappingData(DestMD2);
7536 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7537 function TglBitmapData.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
7539 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
7542 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7543 function TglBitmapData.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
7545 PixelData: TglBitmapPixelData;
7547 TFormatDescriptor.GetAlpha(Format).PreparePixel(PixelData);
7548 result := AddAlphaFromColorKeyFloat(
7549 aRed / PixelData.Range.r,
7550 aGreen / PixelData.Range.g,
7551 aBlue / PixelData.Range.b,
7552 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
7555 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7556 function TglBitmapData.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
7558 values: array[0..2] of Single;
7561 PixelData: TglBitmapPixelData;
7563 TFormatDescriptor.GetAlpha(Format).PreparePixel(PixelData);
7564 with PixelData do begin
7566 values[1] := aGreen;
7569 for i := 0 to 2 do begin
7570 tmp := Trunc(Range.arr[i] * aDeviation);
7571 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
7572 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
7577 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
7580 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7581 function TglBitmapData.AddAlphaFromValue(const aAlpha: Byte): Boolean;
7583 result := AddAlphaFromValueFloat(aAlpha / $FF);
7586 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7587 function TglBitmapData.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
7589 PixelData: TglBitmapPixelData;
7591 TFormatDescriptor.GetAlpha(Format).PreparePixel(PixelData);
7592 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
7595 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7596 function TglBitmapData.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
7598 PixelData: TglBitmapPixelData;
7600 TFormatDescriptor.GetAlpha(Format).PreparePixel(PixelData);
7602 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
7603 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
7606 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7607 function TglBitmapData.RemoveAlpha: Boolean;
7609 FormatDesc: TFormatDescriptor;
7612 FormatDesc := TFormatDescriptor.Get(Format);
7613 if Assigned(Data) then begin
7614 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
7615 raise EglBitmapUnsupportedFormat.Create(Format);
7616 result := ConvertTo(FormatDesc.WithoutAlpha);
7620 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7621 procedure TglBitmapData.FillWithColor(const aRed, aGreen, aBlue: Byte;
7622 const aAlpha: Byte);
7624 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
7627 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7628 procedure TglBitmapData.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
7630 PixelData: TglBitmapPixelData;
7632 TFormatDescriptor.GetAlpha(Format).PreparePixel(PixelData);
7634 aRed / PixelData.Range.r,
7635 aGreen / PixelData.Range.g,
7636 aBlue / PixelData.Range.b,
7637 aAlpha / PixelData.Range.a);
7640 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7641 procedure TglBitmapData.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
7643 PixelData: TglBitmapPixelData;
7645 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
7646 with PixelData do begin
7647 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
7648 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
7649 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
7650 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
7652 Convert(glBitmapFillWithColorFunc, false, @PixelData);
7655 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7656 procedure TglBitmapData.SetData(const aData: PByte; const aFormat: TglBitmapFormat; const aWidth: Integer; const aHeight: Integer);
7658 if (Data <> aData) then begin
7659 if (Assigned(Data)) then
7664 if Assigned(fData) then begin
7665 FillChar(fDimension, SizeOf(fDimension), 0);
7666 if aWidth <> -1 then begin
7667 fDimension.Fields := fDimension.Fields + [ffX];
7668 fDimension.X := aWidth;
7671 if aHeight <> -1 then begin
7672 fDimension.Fields := fDimension.Fields + [ffY];
7673 fDimension.Y := aHeight;
7683 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7684 function TglBitmapData.Clone: TglBitmapData;
7686 Temp: TglBitmapData;
7691 Temp := (ClassType.Create as TglBitmapData);
7693 // copy texture data if assigned
7694 if Assigned(Data) then begin
7695 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
7696 GetMem(TempPtr, Size);
7698 Move(Data^, TempPtr^, Size);
7699 Temp.SetData(TempPtr, Format, Width, Height);
7701 if Assigned(TempPtr) then
7707 Temp.SetData(TempPtr, Format, Width, Height);
7711 Temp.fFormat := Format;
7719 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7720 procedure TglBitmapData.Invert(const aRed, aGreen, aBlue, aAlpha: Boolean);
7725 (Byte(aRed) and 1) or
7726 ((Byte(aGreen) and 1) shl 1) or
7727 ((Byte(aBlue) and 1) shl 2) or
7728 ((Byte(aAlpha) and 1) shl 3);
7730 Convert(glBitmapInvertFunc, false, {%H-}Pointer(mask));
7733 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7735 TMatrixItem = record
7740 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
7741 TglBitmapToNormalMapRec = Record
7743 Heights: array of Single;
7744 MatrixU : array of TMatrixItem;
7745 MatrixV : array of TMatrixItem;
7749 ONE_OVER_255 = 1 / 255;
7751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7752 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
7756 with FuncRec do begin
7758 Source.Data.r * LUMINANCE_WEIGHT_R +
7759 Source.Data.g * LUMINANCE_WEIGHT_G +
7760 Source.Data.b * LUMINANCE_WEIGHT_B;
7761 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
7765 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7766 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
7769 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
7772 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7773 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
7775 TVec = Array[0..2] of Single;
7782 function GetHeight(X, Y: Integer): Single;
7784 with FuncRec do begin
7785 X := Max(0, Min(Size.X -1, X));
7786 Y := Max(0, Min(Size.Y -1, Y));
7787 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
7792 with FuncRec do begin
7793 with PglBitmapToNormalMapRec(Args)^ do begin
7795 for Idx := Low(MatrixU) to High(MatrixU) do
7796 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
7799 for Idx := Low(MatrixU) to High(MatrixU) do
7800 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
7802 Vec[0] := -du * Scale;
7803 Vec[1] := -dv * Scale;
7808 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
7809 if Len <> 0 then begin
7810 Vec[0] := Vec[0] * Len;
7811 Vec[1] := Vec[1] * Len;
7812 Vec[2] := Vec[2] * Len;
7816 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
7817 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
7818 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
7822 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7823 procedure TglBitmapData.GenerateNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
7825 Rec: TglBitmapToNormalMapRec;
7827 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
7829 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
7830 Matrix[Index].X := X;
7831 Matrix[Index].Y := Y;
7832 Matrix[Index].W := W;
7837 if TFormatDescriptor.Get(Format).IsCompressed then
7838 raise EglBitmapUnsupportedFormat.Create(Format);
7840 if aScale > 100 then
7842 else if aScale < -100 then
7845 Rec.Scale := aScale;
7847 SetLength(Rec.Heights, Width * Height);
7851 SetLength(Rec.MatrixU, 2);
7852 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
7853 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
7855 SetLength(Rec.MatrixV, 2);
7856 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
7857 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
7861 SetLength(Rec.MatrixU, 6);
7862 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
7863 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
7864 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
7865 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
7866 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
7867 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
7869 SetLength(Rec.MatrixV, 6);
7870 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
7871 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
7872 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
7873 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
7874 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
7875 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
7879 SetLength(Rec.MatrixU, 6);
7880 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
7881 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
7882 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
7883 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
7884 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
7885 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
7887 SetLength(Rec.MatrixV, 6);
7888 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
7889 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
7890 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
7891 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
7892 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
7893 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
7897 SetLength(Rec.MatrixU, 20);
7898 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
7899 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
7900 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
7901 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
7902 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
7903 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
7904 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
7905 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
7906 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
7907 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
7908 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
7909 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
7910 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
7911 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
7912 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
7913 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
7914 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
7915 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
7916 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
7917 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
7919 SetLength(Rec.MatrixV, 20);
7920 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
7921 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
7922 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
7923 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
7924 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
7925 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
7926 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
7927 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
7928 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
7929 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
7930 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
7931 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
7932 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
7933 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
7934 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
7935 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
7936 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
7937 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
7938 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
7939 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
7944 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
7945 Convert(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
7947 Convert(glBitmapToNormalMapPrepareFunc, false, @Rec);
7948 Convert(glBitmapToNormalMapFunc, false, @Rec);
7950 SetLength(Rec.Heights, 0);
7954 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7955 constructor TglBitmapData.Create;
7958 fFormat := glBitmapDefaultFormat;
7961 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7962 constructor TglBitmapData.Create(const aFileName: String);
7965 LoadFromFile(aFileName);
7968 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7969 constructor TglBitmapData.Create(const aStream: TStream);
7972 LoadFromStream(aStream);
7975 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7976 constructor TglBitmapData.Create(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat; aData: PByte);
7981 if not Assigned(aData) then begin
7982 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
7983 GetMem(aData, ImageSize);
7985 FillChar(aData^, ImageSize, #$FF);
7986 SetData(aData, aFormat, aSize.X, aSize.Y);
7988 if Assigned(aData) then
7993 SetData(aData, aFormat, aSize.X, aSize.Y);
7997 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7998 constructor TglBitmapData.Create(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer);
8001 LoadFromFunc(aSize, aFormat, aFunc, aArgs);
8004 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8005 constructor TglBitmapData.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
8008 LoadFromResource(aInstance, aResource, aResType);
8011 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8012 constructor TglBitmapData.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
8015 LoadFromResourceID(aInstance, aResourceID, aResType);
8018 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8019 destructor TglBitmapData.Destroy;
8021 SetData(nil, tfEmpty);
8025 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8026 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8027 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8028 function TglBitmap.GetWidth: Integer;
8030 if (ffX in fDimension.Fields) then
8031 result := fDimension.X
8036 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8037 function TglBitmap.GetHeight: Integer;
8039 if (ffY in fDimension.Fields) then
8040 result := fDimension.Y
8045 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8046 procedure TglBitmap.SetCustomData(const aValue: Pointer);
8048 if fCustomData = aValue then
8050 fCustomData := aValue;
8053 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8054 procedure TglBitmap.SetCustomName(const aValue: String);
8056 if fCustomName = aValue then
8058 fCustomName := aValue;
8061 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8062 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
8064 if fCustomNameW = aValue then
8066 fCustomNameW := aValue;
8069 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8070 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
8072 if fDeleteTextureOnFree = aValue then
8074 fDeleteTextureOnFree := aValue;
8077 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8078 procedure TglBitmap.SetID(const aValue: Cardinal);
8080 if fID = aValue then
8085 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8086 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
8088 if fMipMap = aValue then
8093 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8094 procedure TglBitmap.SetTarget(const aValue: Cardinal);
8096 if fTarget = aValue then
8101 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8102 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
8103 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_EXT)}
8105 MaxAnisotropic: Integer;
8108 fAnisotropic := aValue;
8109 if (ID > 0) then begin
8110 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_EXT)}
8111 if GL_EXT_texture_filter_anisotropic then begin
8112 if fAnisotropic > 0 then begin
8113 Bind({$IFNDEF OPENGL_ES}false{$ENDIF});
8114 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
8115 if aValue > MaxAnisotropic then
8116 fAnisotropic := MaxAnisotropic;
8117 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
8128 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8129 procedure TglBitmap.CreateID;
8132 glDeleteTextures(1, @fID);
8133 glGenTextures(1, @fID);
8134 Bind({$IFNDEF OPENGL_ES}false{$ENDIF});
8137 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8138 procedure TglBitmap.SetupParameters({$IFNDEF OPENGL_ES}out aBuildWithGlu: Boolean{$ENDIF});
8140 // Set Up Parameters
8141 SetWrap(fWrapS, fWrapT, fWrapR);
8142 SetFilter(fFilterMin, fFilterMag);
8143 SetAnisotropic(fAnisotropic);
8146 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
8147 if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
8148 SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
8152 // Mip Maps Generation Mode
8153 aBuildWithGlu := false;
8154 if (MipMap = mmMipmap) then begin
8155 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
8156 glTexParameteri(Target, GL_GENERATE_MIPMAP, GLint(GL_TRUE))
8158 aBuildWithGlu := true;
8159 end else if (MipMap = mmMipmapGlu) then
8160 aBuildWithGlu := true;
8162 if (MipMap = mmMipmap) then
8163 glGenerateMipmap(Target);
8167 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8168 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8169 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8170 procedure TglBitmap.AfterConstruction;
8172 inherited AfterConstruction;
8177 fIsResident := false;
8180 fMipMap := glBitmapDefaultMipmap;
8181 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
8183 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
8184 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
8186 glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
8190 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8191 procedure TglBitmap.BeforeDestruction;
8193 if (fID > 0) and fDeleteTextureOnFree then
8194 glDeleteTextures(1, @fID);
8195 inherited BeforeDestruction;
8199 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8200 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
8202 fBorderColor[0] := aRed;
8203 fBorderColor[1] := aGreen;
8204 fBorderColor[2] := aBlue;
8205 fBorderColor[3] := aAlpha;
8206 if (ID > 0) then begin
8208 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
8213 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8214 procedure TglBitmap.SetFilter(const aMin, aMag: GLenum);
8219 fFilterMin := GL_NEAREST;
8221 fFilterMin := GL_LINEAR;
8222 GL_NEAREST_MIPMAP_NEAREST:
8223 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
8224 GL_LINEAR_MIPMAP_NEAREST:
8225 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
8226 GL_NEAREST_MIPMAP_LINEAR:
8227 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
8228 GL_LINEAR_MIPMAP_LINEAR:
8229 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
8231 raise EglBitmap.Create('SetFilter - Unknow MIN filter.');
8237 fFilterMag := GL_NEAREST;
8239 fFilterMag := GL_LINEAR;
8241 raise EglBitmap.Create('SetFilter - Unknow MAG filter.');
8245 if (ID > 0) then begin
8246 Bind({$IFNDEF OPENGL_ES}false{$ENDIF});
8247 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
8249 if (MipMap = mmNone) {$IFNDEF OPENGL_ES}or (Target = GL_TEXTURE_RECTANGLE){$ENDIF} then begin
8251 GL_NEAREST, GL_LINEAR:
8252 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
8253 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
8254 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8255 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
8256 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8259 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
8263 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8264 procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum);
8266 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
8271 aTarget := GL_CLAMP;
8275 aTarget := GL_REPEAT;
8277 GL_CLAMP_TO_EDGE: begin
8279 if not GL_VERSION_1_2 and not GL_EXT_texture_edge_clamp then
8283 aTarget := GL_CLAMP_TO_EDGE;
8287 GL_CLAMP_TO_BORDER: begin
8288 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
8289 aTarget := GL_CLAMP_TO_BORDER
8291 aTarget := GL_CLAMP;
8295 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
8296 GL_MIRRORED_REPEAT: begin
8298 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
8300 if GL_VERSION_2_0 then
8302 aTarget := GL_MIRRORED_REPEAT
8304 raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
8308 raise EglBitmap.Create('SetWrap - Unknow Texturewrap');
8313 CheckAndSetWrap(S, fWrapS);
8314 CheckAndSetWrap(T, fWrapT);
8315 CheckAndSetWrap(R, fWrapR);
8317 if (ID > 0) then begin
8318 Bind({$IFNDEF OPENGL_ES}false{$ENDIF});
8319 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
8320 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
8321 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
8322 {$IFDEF OPENGL_ES} if GL_VERSION_3_0 then{$ENDIF}
8323 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
8328 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
8329 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8330 procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum);
8332 procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer);
8334 if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or
8335 (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then
8336 fSwizzle[aIndex] := aValue
8338 raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value');
8343 if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
8344 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
8346 if not GL_VERSION_3_0 then
8347 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
8349 CheckAndSetValue(r, 0);
8350 CheckAndSetValue(g, 1);
8351 CheckAndSetValue(b, 2);
8352 CheckAndSetValue(a, 3);
8354 if (ID > 0) then begin
8357 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, PGLint(@fSwizzle[0]));
8359 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_R, PGLint(@fSwizzle[0]));
8360 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_G, PGLint(@fSwizzle[1]));
8361 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_B, PGLint(@fSwizzle[2]));
8362 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_A, PGLint(@fSwizzle[3]));
8368 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8369 procedure TglBitmap.Bind({$IFNDEF OPENGL_ES}const aEnableTextureUnit: Boolean{$ENDIF});
8372 if aEnableTextureUnit then
8376 glBindTexture(Target, ID);
8379 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8380 procedure TglBitmap.Unbind({$IFNDEF OPENGL_ES}const aDisableTextureUnit: Boolean{$ENDIF});
8383 if aDisableTextureUnit then
8386 glBindTexture(Target, 0);
8389 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8390 procedure TglBitmap.UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean);
8394 w := aDataObj.Width;
8395 h := aDataObj.Height;
8396 fDimension.Fields := [];
8398 fDimension.Fields := fDimension.Fields + [ffX];
8400 fDimension.Fields := fDimension.Fields + [ffY];
8406 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8407 function TglBitmap.DownloadData(const aDataObj: TglBitmapData): Boolean;
8410 TempWidth, TempHeight: Integer;
8411 TempIntFormat: GLint;
8412 IntFormat: TglBitmapFormat;
8413 FormatDesc: TFormatDescriptor;
8419 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
8420 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
8421 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
8423 FormatDesc := (TglBitmapFormatDescriptor.GetByFormat(TempIntFormat) as TFormatDescriptor);
8424 IntFormat := FormatDesc.Format;
8426 // Getting data from OpenGL
8427 FormatDesc := TFormatDescriptor.Get(IntFormat);
8428 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
8430 if FormatDesc.IsCompressed then begin
8431 if not Assigned(glGetCompressedTexImage) then
8432 raise EglBitmap.Create('compressed formats not supported by video adapter');
8433 glGetCompressedTexImage(Target, 0, Temp)
8435 glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8436 aDataObj.SetData(Temp, IntFormat, TempWidth, TempHeight);
8439 if Assigned(Temp) then
8446 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8447 constructor TglBitmap.Create;
8449 if (ClassType = TglBitmap) then
8450 raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
8454 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8455 constructor TglBitmap.Create(const aData: TglBitmapData);
8462 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8463 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8464 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8465 procedure TglBitmap1D.UploadDataIntern(const aDataObj: TglBitmapData; const aBuildWithGlu: Boolean);
8467 fd: TglBitmapFormatDescriptor;
8470 fd := aDataObj.FormatDescriptor;
8471 if (fd.glFormat = 0) or (fd.glInternalFormat = 0) or (fd.glDataFormat = 0) then
8472 raise EglBitmap.Create('format is not supported by video adapter, please convert before uploading data');
8474 if fd.IsCompressed then begin
8475 if not Assigned(glCompressedTexImage1D) then
8476 raise EglBitmap.Create('compressed formats not supported by video adapter');
8477 glCompressedTexImage1D(Target, 0, fd.glInternalFormat, aDataObj.Width, 0, fd.GetSize(aDataObj.Width, 1), aDataObj.Data)
8478 end else if aBuildWithGlu then
8479 gluBuild1DMipmaps(Target, fd.glInternalFormat, aDataObj.Width, fd.glFormat, fd.glDataFormat, aDataObj.Data)
8481 glTexImage1D(Target, 0, fd.glInternalFormat, aDataObj.Width, 0, fd.glFormat, fd.glDataFormat, aDataObj.Data);
8484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8485 procedure TglBitmap1D.AfterConstruction;
8488 Target := GL_TEXTURE_1D;
8491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8492 procedure TglBitmap1D.UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean);
8494 BuildWithGlu, TexRec: Boolean;
8497 if not Assigned(aDataObj) then
8500 // Check Texture Size
8501 if (aCheckSize) then begin
8502 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8504 if (aDataObj.Width > TexSize) then
8505 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8507 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
8508 (Target = GL_TEXTURE_RECTANGLE);
8509 if not (IsPowerOfTwo(aDataObj.Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8510 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8515 SetupParameters(BuildWithGlu);
8516 UploadDataIntern(aDataObj, BuildWithGlu);
8517 glAreTexturesResident(1, @fID, @fIsResident);
8519 inherited UploadData(aDataObj, aCheckSize);
8523 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8524 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8525 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8526 procedure TglBitmap2D.UploadDataIntern(const aDataObj: TglBitmapData; const aTarget: GLenum{$IFNDEF OPENGL_ES}; const aBuildWithGlu: Boolean{$ENDIF});
8528 fd: TglBitmapFormatDescriptor;
8530 fd := aDataObj.FormatDescriptor;
8531 if (fd.glFormat = 0) or (fd.glInternalFormat = 0) or (fd.glDataFormat = 0) then
8532 raise EglBitmap.Create('format is not supported by video adapter, please convert before uploading data');
8534 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
8536 if fd.IsCompressed then begin
8537 if not Assigned(glCompressedTexImage2D) then
8538 raise EglBitmap.Create('compressed formats not supported by video adapter');
8539 glCompressedTexImage2D(aTarget, 0, fd.glInternalFormat, aDataObj.Width, aDataObj.Height, 0, fd.GetSize(fDimension), aDataObj.Data)
8541 end else if aBuildWithGlu then begin
8542 gluBuild2DMipmaps(aTarget, fd.ChannelCount, aDataObj.Width, aDataObj.Height, fd.glFormat, fd.glDataFormat, aDataObj.Data)
8545 glTexImage2D(aTarget, 0, fd.glInternalFormat, aDataObj.Width, aDataObj.Height, 0, fd.glFormat, fd.glDataFormat, aDataObj.Data);
8549 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8550 procedure TglBitmap2D.AfterConstruction;
8553 Target := GL_TEXTURE_2D;
8556 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8557 procedure TglBitmap2D.UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean);
8560 BuildWithGlu, TexRec: Boolean;
8565 if not Assigned(aDataObj) then
8568 // Check Texture Size
8569 if (aCheckSize) then begin
8570 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8572 if ((aDataObj.Width > TexSize) or (aDataObj.Height > TexSize)) then
8573 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8575 PotTex := IsPowerOfTwo(aDataObj.Width) and IsPowerOfTwo(aDataObj.Height);
8576 {$IF NOT DEFINED(OPENGL_ES)}
8577 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
8578 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8579 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8580 {$ELSEIF DEFINED(OPENGL_ES_EXT)}
8581 if not PotTex and not GL_OES_texture_npot then
8582 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8585 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8591 SetupParameters({$IFNDEF OPENGL_ES}BuildWithGlu{$ENDIF});
8592 UploadDataIntern(aDataObj, Target{$IFNDEF OPENGL_ES}, BuildWithGlu{$ENDIF});
8594 glAreTexturesResident(1, @fID, @fIsResident);
8597 inherited UploadData(aDataObj, aCheckSize);
8600 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8601 class procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat; const aDataObj: TglBitmapData);
8604 Size, w, h: Integer;
8605 FormatDesc: TFormatDescriptor;
8607 FormatDesc := TFormatDescriptor.Get(aFormat);
8608 if FormatDesc.IsCompressed then
8609 raise EglBitmapUnsupportedFormat.Create(aFormat);
8611 w := aRight - aLeft;
8612 h := aBottom - aTop;
8613 Size := FormatDesc.GetSize(w, h);
8616 glPixelStorei(GL_PACK_ALIGNMENT, 1);
8617 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8618 aDataObj.SetData(Temp, aFormat, w, h);
8621 if Assigned(Temp) then
8627 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
8628 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8629 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8630 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8631 procedure TglBitmapCubeMap.AfterConstruction;
8636 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8637 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8639 if not (GL_VERSION_2_0) then
8640 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8644 Target := GL_TEXTURE_CUBE_MAP;
8646 fGenMode := GL_REFLECTION_MAP;
8650 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8651 procedure TglBitmapCubeMap.UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean);
8653 Assert(false, 'TglBitmapCubeMap.UploadData - Don''t call UploadData directly, use UploadCubeMap instead');
8656 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8657 procedure TglBitmapCubeMap.UploadCubeMap(const aDataObj: TglBitmapData; const aCubeTarget: Cardinal; const aCheckSize: Boolean);
8660 BuildWithGlu: Boolean;
8664 if (aCheckSize) then begin
8665 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8667 if (aDataObj.Width > TexSize) or (aDataObj.Height > TexSize) then
8668 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenerateCubeMap - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8670 {$IF NOT DEFINED(OPENGL_ES)}
8671 if not ((IsPowerOfTwo(aDataObj.Width) and IsPowerOfTwo(aDataObj.Height)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8672 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenerateCubeMap - Cubemaps dosn''t support non power of two texture.');
8673 {$ELSEIF DEFINED(OPENGL_ES_EXT)}
8674 if not (IsPowerOfTwo(aDataObj.Width) and IsPowerOfTwo(aDataObj.Height)) and not GL_OES_texture_npot then
8675 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenerateCubeMap - Cubemaps dosn''t support non power of two texture.');
8677 if not (IsPowerOfTwo(aDataObj.Width) and IsPowerOfTwo(aDataObj.Height)) then
8678 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenerateCubeMap - Cubemaps dosn''t support non power of two texture.');
8684 SetupParameters({$IFNDEF OPENGL_ES}BuildWithGlu{$ENDIF});
8685 UploadDataIntern(aDataObj, aCubeTarget{$IFNDEF OPENGL_ES}, BuildWithGlu{$ENDIF});
8687 inherited UploadData(aDataObj, aCheckSize);
8690 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8691 procedure TglBitmapCubeMap.Bind({$IFNDEF OPENGL_ES}const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean{$ENDIF});
8693 inherited Bind({$IFNDEF OPENGL_ES}aEnableTextureUnit{$ENDIF});
8695 if aEnableTexCoordsGen then begin
8696 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8697 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8698 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8699 glEnable(GL_TEXTURE_GEN_S);
8700 glEnable(GL_TEXTURE_GEN_T);
8701 glEnable(GL_TEXTURE_GEN_R);
8706 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8707 procedure TglBitmapCubeMap.Unbind({$IFNDEF OPENGL_ES}const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean{$ENDIF});
8709 inherited Unbind({$IFNDEF OPENGL_ES}aDisableTextureUnit{$ENDIF});
8711 if aDisableTexCoordsGen then begin
8712 glDisable(GL_TEXTURE_GEN_S);
8713 glDisable(GL_TEXTURE_GEN_T);
8714 glDisable(GL_TEXTURE_GEN_R);
8720 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
8721 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8722 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8723 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8725 TVec = Array[0..2] of Single;
8726 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8728 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8729 TglBitmapNormalMapRec = record
8731 Func: TglBitmapNormalMapGetVectorFunc;
8734 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8735 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8737 aVec[0] := aHalfSize;
8738 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8739 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8742 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8743 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8745 aVec[0] := - aHalfSize;
8746 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8747 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8750 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8751 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8753 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8754 aVec[1] := aHalfSize;
8755 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8758 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8759 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8761 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8762 aVec[1] := - aHalfSize;
8763 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8766 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8767 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8769 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8770 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8771 aVec[2] := aHalfSize;
8774 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8775 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8777 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8778 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8779 aVec[2] := - aHalfSize;
8782 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8783 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8789 with FuncRec do begin
8790 with PglBitmapNormalMapRec(Args)^ do begin
8791 Func(Vec, Position, HalfSize);
8794 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8795 if Len <> 0 then begin
8796 Vec[0] := Vec[0] * Len;
8797 Vec[1] := Vec[1] * Len;
8798 Vec[2] := Vec[2] * Len;
8801 // Scale Vector and AddVectro
8802 Vec[0] := Vec[0] * 0.5 + 0.5;
8803 Vec[1] := Vec[1] * 0.5 + 0.5;
8804 Vec[2] := Vec[2] * 0.5 + 0.5;
8809 Dest.Data.arr[i] := Round(Vec[i] * 255);
8813 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8814 procedure TglBitmapNormalMap.AfterConstruction;
8818 fGenMode := GL_NORMAL_MAP;
8822 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8823 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aCheckSize: Boolean);
8825 Rec: TglBitmapNormalMapRec;
8826 SizeRec: TglBitmapSize;
8827 DataObj: TglBitmapData;
8829 Rec.HalfSize := aSize div 2;
8831 SizeRec.Fields := [ffX, ffY];
8835 DataObj := TglBitmapData.Create;
8838 Rec.Func := glBitmapNormalMapPosX;
8839 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8840 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_POSITIVE_X, aCheckSize);
8843 Rec.Func := glBitmapNormalMapNegX;
8844 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8845 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aCheckSize);
8848 Rec.Func := glBitmapNormalMapPosY;
8849 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8850 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aCheckSize);
8853 Rec.Func := glBitmapNormalMapNegY;
8854 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8855 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aCheckSize);
8858 Rec.Func := glBitmapNormalMapPosZ;
8859 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8860 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aCheckSize);
8863 Rec.Func := glBitmapNormalMapNegZ;
8864 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8865 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aCheckSize);
8867 FreeAndNil(DataObj);
8873 glBitmapSetDefaultFormat (tfEmpty);
8874 glBitmapSetDefaultMipmap (mmMipmap);
8875 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8876 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8877 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
8878 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8881 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8882 glBitmapSetDefaultDeleteTextureOnFree (true);
8884 TFormatDescriptor.Init;
8887 TFormatDescriptor.Finalize;