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}
187 {$IFDEF OPENGL_ES} dglOpenGLES,
188 {$ELSE} dglOpenGL, {$ENDIF}
190 {$IF DEFINED(GLB_WIN) AND
191 DEFINED(GLB_DELPHI)} windows, {$IFEND}
193 {$IFDEF GLB_SDL} SDL, {$ENDIF}
194 {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, Graphics, {$ENDIF}
195 {$IFDEF GLB_DELPHI} Dialogs, Graphics, Types, {$ENDIF}
197 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
198 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
199 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
200 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
201 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
207 QWord = System.UInt64;
215 { type that describes the format of the data stored in a texture.
216 the name of formats is composed of the following constituents:
218 - channel (e.g. R, G, B, A or Alpha, Luminance or X (reserved))
219 - width of the chanel in bit (4, 8, 16, ...)
220 - data type (e.g. ub, us, ui)
221 - number of elements of data types }
225 tfAlpha4ub1, //< 1 x unsigned byte
226 tfAlpha8ub1, //< 1 x unsigned byte
227 tfAlpha16us1, //< 1 x unsigned short
229 tfLuminance4ub1, //< 1 x unsigned byte
230 tfLuminance8ub1, //< 1 x unsigned byte
231 tfLuminance16us1, //< 1 x unsigned short
233 tfLuminance4Alpha4ub2, //< 1 x unsigned byte (lum), 1 x unsigned byte (alpha)
234 tfLuminance6Alpha2ub2, //< 1 x unsigned byte (lum), 1 x unsigned byte (alpha)
235 tfLuminance8Alpha8ub2, //< 1 x unsigned byte (lum), 1 x unsigned byte (alpha)
236 tfLuminance12Alpha4us2, //< 1 x unsigned short (lum), 1 x unsigned short (alpha)
237 tfLuminance16Alpha16us2, //< 1 x unsigned short (lum), 1 x unsigned short (alpha)
239 tfR3G3B2ub1, //< 1 x unsigned byte (3bit red, 3bit green, 2bit blue)
240 tfRGBX4us1, //< 1 x unsigned short (4bit red, 4bit green, 4bit blue, 4bit reserverd)
241 tfXRGB4us1, //< 1 x unsigned short (4bit reserved, 4bit red, 4bit green, 4bit blue)
242 tfR5G6B5us1, //< 1 x unsigned short (5bit red, 6bit green, 5bit blue)
243 tfRGB5X1us1, //< 1 x unsigned short (5bit red, 5bit green, 5bit blue, 1bit reserved)
244 tfX1RGB5us1, //< 1 x unsigned short (1bit reserved, 5bit red, 5bit green, 5bit blue)
245 tfRGB8ub3, //< 1 x unsigned byte (red), 1 x unsigned byte (green), 1 x unsigned byte (blue)
246 tfRGBX8ui1, //< 1 x unsigned int (8bit red, 8bit green, 8bit blue, 8bit reserved)
247 tfXRGB8ui1, //< 1 x unsigned int (8bit reserved, 8bit red, 8bit green, 8bit blue)
248 tfRGB10X2ui1, //< 1 x unsigned int (10bit red, 10bit green, 10bit blue, 2bit reserved)
249 tfX2RGB10ui1, //< 1 x unsigned int (2bit reserved, 10bit red, 10bit green, 10bit blue)
250 tfRGB16us3, //< 1 x unsigned short (red), 1 x unsigned short (green), 1 x unsigned short (blue)
252 tfRGBA4us1, //< 1 x unsigned short (4bit red, 4bit green, 4bit blue, 4bit alpha)
253 tfARGB4us1, //< 1 x unsigned short (4bit alpha, 4bit red, 4bit green, 4bit blue)
254 tfRGB5A1us1, //< 1 x unsigned short (5bit red, 5bit green, 5bit blue, 1bit alpha)
255 tfA1RGB5us1, //< 1 x unsigned short (1bit alpha, 5bit red, 5bit green, 5bit blue)
256 tfRGBA8ui1, //< 1 x unsigned int (8bit red, 8bit green, 8bit blue, 8 bit alpha)
257 tfARGB8ui1, //< 1 x unsigned int (8 bit alpha, 8bit red, 8bit green, 8bit blue)
258 tfRGBA8ub4, //< 1 x unsigned byte (red), 1 x unsigned byte (green), 1 x unsigned byte (blue), 1 x unsigned byte (alpha)
259 tfRGB10A2ui1, //< 1 x unsigned int (10bit red, 10bit green, 10bit blue, 2bit alpha)
260 tfA2RGB10ui1, //< 1 x unsigned int (2bit alpha, 10bit red, 10bit green, 10bit blue)
261 tfRGBA16us4, //< 1 x unsigned short (red), 1 x unsigned short (green), 1 x unsigned short (blue), 1 x unsigned short (alpha)
263 tfBGRX4us1, //< 1 x unsigned short (4bit blue, 4bit green, 4bit red, 4bit reserved)
264 tfXBGR4us1, //< 1 x unsigned short (4bit reserved, 4bit blue, 4bit green, 4bit red)
265 tfB5G6R5us1, //< 1 x unsigned short (5bit blue, 6bit green, 5bit red)
266 tfBGR5X1us1, //< 1 x unsigned short (5bit blue, 5bit green, 5bit red, 1bit reserved)
267 tfX1BGR5us1, //< 1 x unsigned short (1bit reserved, 5bit blue, 5bit green, 5bit red)
268 tfBGR8ub3, //< 1 x unsigned byte (blue), 1 x unsigned byte (green), 1 x unsigned byte (red)
269 tfBGRX8ui1, //< 1 x unsigned int (8bit blue, 8bit green, 8bit red, 8bit reserved)
270 tfXBGR8ui1, //< 1 x unsigned int (8bit reserved, 8bit blue, 8bit green, 8bit red)
271 tfBGR10X2ui1, //< 1 x unsigned int (10bit blue, 10bit green, 10bit red, 2bit reserved)
272 tfX2BGR10ui1, //< 1 x unsigned int (2bit reserved, 10bit blue, 10bit green, 10bit red)
273 tfBGR16us3, //< 1 x unsigned short (blue), 1 x unsigned short (green), 1 x unsigned short (red)
275 tfBGRA4us1, //< 1 x unsigned short (4bit blue, 4bit green, 4bit red, 4bit alpha)
276 tfABGR4us1, //< 1 x unsigned short (4bit alpha, 4bit blue, 4bit green, 4bit red)
277 tfBGR5A1us1, //< 1 x unsigned short (5bit blue, 5bit green, 5bit red, 1bit alpha)
278 tfA1BGR5us1, //< 1 x unsigned short (1bit alpha, 5bit blue, 5bit green, 5bit red)
279 tfBGRA8ui1, //< 1 x unsigned int (8bit blue, 8bit green, 8bit red, 8bit alpha)
280 tfABGR8ui1, //< 1 x unsigned int (8bit alpha, 8bit blue, 8bit green, 8bit red)
281 tfBGRA8ub4, //< 1 x unsigned byte (blue), 1 x unsigned byte (green), 1 x unsigned byte (red), 1 x unsigned byte (alpha)
282 tfBGR10A2ui1, //< 1 x unsigned int (10bit blue, 10bit green, 10bit red, 2bit alpha)
283 tfA2BGR10ui1, //< 1 x unsigned int (2bit alpha, 10bit blue, 10bit green, 10bit red)
284 tfBGRA16us4, //< 1 x unsigned short (blue), 1 x unsigned short (green), 1 x unsigned short (red), 1 x unsigned short (alpha)
286 tfDepth16us1, //< 1 x unsigned short (depth)
287 tfDepth24ui1, //< 1 x unsigned int (depth)
288 tfDepth32ui1, //< 1 x unsigned int (depth)
295 { type to define suitable file formats }
296 TglBitmapFileType = (
297 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF} //< Portable Network Graphic file (PNG)
298 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF} //< JPEG file
299 ftDDS, //< Direct Draw Surface file (DDS)
300 ftTGA, //< Targa Image File (TGA)
301 ftBMP, //< Windows Bitmap File (BMP)
302 ftRAW); //< glBitmap RAW file format
303 TglBitmapFileTypes = set of TglBitmapFileType;
305 { possible mipmap types }
307 mmNone, //< no mipmaps
308 mmMipmap, //< normal mipmaps
309 mmMipmapGlu); //< mipmaps generated with glu functions
311 { possible normal map functions }
312 TglBitmapNormalMapFunc = (
318 ////////////////////////////////////////////////////////////////////////////////////////////////////
319 EglBitmap = class(Exception); //< glBitmap exception
320 EglBitmapNotSupported = class(Exception); //< exception for not supported functions
321 EglBitmapSizeToLarge = class(EglBitmap); //< exception for to large textures
322 EglBitmapNonPowerOfTwo = class(EglBitmap); //< exception for non power of two textures
323 EglBitmapUnsupportedFormat = class(EglBitmap) //< exception for unsupporetd formats
325 constructor Create(const aFormat: TglBitmapFormat); overload;
326 constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload;
329 ////////////////////////////////////////////////////////////////////////////////////////////////////
330 { record that stores 4 unsigned integer values }
331 TglBitmapRec4ui = packed record
333 0: (r, g, b, a: Cardinal);
334 1: (arr: array[0..3] of Cardinal);
337 { record that stores 4 unsigned byte values }
338 TglBitmapRec4ub = packed record
340 0: (r, g, b, a: Byte);
341 1: (arr: array[0..3] of Byte);
344 { record that stores 4 unsigned long integer values }
345 TglBitmapRec4ul = packed record
347 0: (r, g, b, a: QWord);
348 1: (arr: array[0..3] of QWord);
351 { structure to store pixel data in }
352 TglBitmapPixelData = packed record
353 Data: TglBitmapRec4ui; //< color data for each color channel
354 Range: TglBitmapRec4ui; //< maximal color value for each channel
355 Format: TglBitmapFormat; //< format of the pixel
357 PglBitmapPixelData = ^TglBitmapPixelData;
359 TglBitmapSizeFields = set of (ffX, ffY);
360 TglBitmapSize = packed record
361 Fields: TglBitmapSizeFields;
365 TglBitmapPixelPosition = TglBitmapSize;
367 { describes the properties of a given texture data format }
368 TglBitmapFormatDescriptor = class(TObject)
371 fBytesPerPixel: Single; //< number of bytes for each pixel
372 fChannelCount: Integer; //< number of color channels
373 fMask: TglBitmapRec4ul; //< bitmask for each color channel
374 fRange: TglBitmapRec4ui; //< maximal value of each color channel
376 { @return @true if the format has a red color channel, @false otherwise }
377 function GetHasRed: Boolean;
379 { @return @true if the format has a green color channel, @false otherwise }
380 function GetHasGreen: Boolean;
382 { @return @true if the format has a blue color channel, @false otherwise }
383 function GetHasBlue: Boolean;
385 { @return @true if the format has a alpha color channel, @false otherwise }
386 function GetHasAlpha: Boolean;
388 { @return @true if the format has any color color channel, @false otherwise }
389 function GetHasColor: Boolean;
391 { @return @true if the format is a grayscale format, @false otherwise }
392 function GetIsGrayscale: Boolean;
394 { @return @true if the format is supported by OpenGL, @false otherwise }
395 function GetHasOpenGLSupport: Boolean;
398 fFormat: TglBitmapFormat; //< format this descriptor belongs to
399 fWithAlpha: TglBitmapFormat; //< suitable format with alpha channel
400 fWithoutAlpha: TglBitmapFormat; //< suitable format without alpha channel
401 fOpenGLFormat: TglBitmapFormat; //< suitable format that is supported by OpenGL
402 fRGBInverted: TglBitmapFormat; //< suitable format with inverted RGB channels
403 fUncompressed: TglBitmapFormat; //< suitable format with uncompressed data
405 fBitsPerPixel: Integer; //< number of bits per pixel
406 fIsCompressed: Boolean; //< @true if the format is compressed, @false otherwise
408 fPrecision: TglBitmapRec4ub; //< number of bits for each color channel
409 fShift: TglBitmapRec4ub; //< bit offset for each color channel
411 fglFormat: GLenum; //< OpenGL format enum (e.g. GL_RGB)
412 fglInternalFormat: GLenum; //< OpenGL internal format enum (e.g. GL_RGB8)
413 fglDataFormat: GLenum; //< OpenGL data format enum (e.g. GL_UNSIGNED_BYTE)
415 { set values for this format descriptor }
416 procedure SetValues; virtual;
418 { calculate cached values }
419 procedure CalcValues;
421 property Format: TglBitmapFormat read fFormat; //< format this descriptor belongs to
422 property ChannelCount: Integer read fChannelCount; //< number of color channels
423 property IsCompressed: Boolean read fIsCompressed; //< @true if the format is compressed, @false otherwise
424 property BitsPerPixel: Integer read fBitsPerPixel; //< number of bytes per pixel
425 property BytesPerPixel: Single read fBytesPerPixel; //< number of bits per pixel
427 property Precision: TglBitmapRec4ub read fPrecision; //< number of bits for each color channel
428 property Shift: TglBitmapRec4ub read fShift; //< bit offset for each color channel
429 property Range: TglBitmapRec4ui read fRange; //< maximal value of each color channel
430 property Mask: TglBitmapRec4ul read fMask; //< bitmask for each color channel
432 property RGBInverted: TglBitmapFormat read fRGBInverted; //< suitable format with inverted RGB channels
433 property WithAlpha: TglBitmapFormat read fWithAlpha; //< suitable format with alpha channel
434 property WithoutAlpha: TglBitmapFormat read fWithAlpha; //< suitable format without alpha channel
435 property OpenGLFormat: TglBitmapFormat read fOpenGLFormat; //< suitable format that is supported by OpenGL
436 property Uncompressed: TglBitmapFormat read fUncompressed; //< suitable format with uncompressed data
438 property glFormat: GLenum read fglFormat; //< OpenGL format enum (e.g. GL_RGB)
439 property glInternalFormat: GLenum read fglInternalFormat; //< OpenGL internal format enum (e.g. GL_RGB8)
440 property glDataFormat: GLenum read fglDataFormat; //< OpenGL data format enum (e.g. GL_UNSIGNED_BYTE)
442 property HasRed: Boolean read GetHasRed; //< @true if the format has a red color channel, @false otherwise
443 property HasGreen: Boolean read GetHasGreen; //< @true if the format has a green color channel, @false otherwise
444 property HasBlue: Boolean read GetHasBlue; //< @true if the format has a blue color channel, @false otherwise
445 property HasAlpha: Boolean read GetHasAlpha; //< @true if the format has a alpha color channel, @false otherwise
446 property HasColor: Boolean read GetHasColor; //< @true if the format has any color color channel, @false otherwise
447 property IsGrayscale: Boolean read GetIsGrayscale; //< @true if the format is a grayscale format, @false otherwise
449 property HasOpenGLSupport: Boolean read GetHasOpenGLSupport; //< @true if the format is supported by OpenGL, @false otherwise
451 function GetSize(const aSize: TglBitmapSize): Integer; overload; virtual;
452 function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
457 { get the format descriptor by a given OpenGL internal format
458 @param aInternalFormat OpenGL internal format to get format descriptor for
459 @returns suitable format descriptor or tfEmpty-Descriptor }
460 class function GetByFormat(const aInternalFormat: GLenum): TglBitmapFormatDescriptor;
463 ////////////////////////////////////////////////////////////////////////////////////////////////////
464 TglBitmapData = class;
466 { structure to store data for converting in }
467 TglBitmapFunctionRec = record
468 Sender: TglBitmapData; //< texture object that stores the data to convert
469 Size: TglBitmapSize; //< size of the texture
470 Position: TglBitmapPixelPosition; //< position of the currently pixel
471 Source: TglBitmapPixelData; //< pixel data of the current pixel
472 Dest: TglBitmapPixelData; //< new data of the pixel (must be filled in)
473 Args: Pointer; //< user defined args that was passed to the convert function
476 { callback to use for converting texture data }
477 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
479 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
480 { class to store texture data in. used to load, save and
481 manipulate data before assigned to texture object
482 all operations on a data object can be done from a background thread }
483 TglBitmapData = class
486 fData: PByte; //< texture data
487 fDimension: TglBitmapSize; //< pixel size of the data
488 fFormat: TglBitmapFormat; //< format the texture data is stored in
489 fFilename: String; //< file the data was load from
491 fScanlines: array of PByte; //< pointer to begin of each line
492 fHasScanlines: Boolean; //< @true if scanlines are initialized, @false otherwise
494 private { getter / setter }
496 { @returns the format descriptor suitable to the texture data format }
497 function GetFormatDescriptor: TglBitmapFormatDescriptor;
499 { @returns the width of the texture data (in pixel) or -1 if no data is set }
500 function GetWidth: Integer;
502 { @returns the height of the texture data (in pixel) or -1 if no data is set }
503 function GetHeight: Integer;
505 { get scanline at index aIndex
506 @returns Pointer to start of line or @nil }
507 function GetScanlines(const aIndex: Integer): PByte;
509 { set new value for the data format. only possible if new format has the same pixel size.
510 if you want to convert the texture data, see ConvertTo function }
511 procedure SetFormat(const aValue: TglBitmapFormat);
513 private { internal misc }
515 { splits a resource identifier into the resource and it's type
516 @param aResource resource identifier to split and store name in
517 @param aResType type of the resource }
518 procedure PrepareResType(var aResource: String; var aResType: PChar);
520 { updates scanlines array }
521 procedure UpdateScanlines;
523 private { internal load and save }
524 {$IFDEF GLB_SUPPORT_PNG_READ}
525 { try to load a PNG from a stream
526 @param aStream stream to load PNG from
527 @returns @true on success, @false otherwise }
528 function LoadPNG(const aStream: TStream): Boolean; virtual;
531 {$ifdef GLB_SUPPORT_PNG_WRITE}
532 { save texture data as PNG to stream
533 @param aStream stream to save data to}
534 procedure SavePNG(const aStream: TStream); virtual;
537 {$IFDEF GLB_SUPPORT_JPEG_READ}
538 { try to load a JPEG from a stream
539 @param aStream stream to load JPEG from
540 @returns @true on success, @false otherwise }
541 function LoadJPEG(const aStream: TStream): Boolean; virtual;
544 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
545 { save texture data as JPEG to stream
546 @param aStream stream to save data to}
547 procedure SaveJPEG(const aStream: TStream); virtual;
550 { try to load a RAW image from a stream
551 @param aStream stream to load RAW image from
552 @returns @true on success, @false otherwise }
553 function LoadRAW(const aStream: TStream): Boolean;
555 { save texture data as RAW image to stream
556 @param aStream stream to save data to}
557 procedure SaveRAW(const aStream: TStream);
559 { try to load a BMP from a stream
560 @param aStream stream to load BMP from
561 @returns @true on success, @false otherwise }
562 function LoadBMP(const aStream: TStream): Boolean;
564 { save texture data as BMP to stream
565 @param aStream stream to save data to}
566 procedure SaveBMP(const aStream: TStream);
568 { try to load a TGA from a stream
569 @param aStream stream to load TGA from
570 @returns @true on success, @false otherwise }
571 function LoadTGA(const aStream: TStream): Boolean;
573 { save texture data as TGA to stream
574 @param aStream stream to save data to}
575 procedure SaveTGA(const aStream: TStream);
577 { try to load a DDS from a stream
578 @param aStream stream to load DDS from
579 @returns @true on success, @false otherwise }
580 function LoadDDS(const aStream: TStream): Boolean;
582 { save texture data as DDS to stream
583 @param aStream stream to save data to}
584 procedure SaveDDS(const aStream: TStream);
586 public { properties }
587 property Data: PByte read fData; //< texture data (be carefull with this!)
588 property Dimension: TglBitmapSize read fDimension; //< size of the texture data (in pixel)
589 property Filename: String read fFilename; //< file the data was loaded from
590 property Width: Integer read GetWidth; //< width of the texture data (in pixel)
591 property Height: Integer read GetHeight; //< height of the texture data (in pixel)
592 property Format: TglBitmapFormat read fFormat write SetFormat; //< format the texture data is stored in
593 property Scanlines[const aIndex: Integer]: PByte read GetScanlines; //< pointer to begin of line at given index or @nil
595 property FormatDescriptor: TglBitmapFormatDescriptor read GetFormatDescriptor; //< descriptor object that describes the format of the stored data
599 { flip texture horizontal
600 @returns @true in success, @false otherwise }
601 function FlipHorz: Boolean; virtual;
603 { flip texture vertical
604 @returns @true in success, @false otherwise }
605 function FlipVert: Boolean; virtual;
609 { load a texture from a file
610 @param aFilename file to load texuture from }
611 procedure LoadFromFile(const aFilename: String);
613 { load a texture from a stream
614 @param aStream stream to load texture from }
615 procedure LoadFromStream(const aStream: TStream); virtual;
617 { use a function to generate texture data
618 @param aSize size of the texture
619 @param aFormat format of the texture data
620 @param aFunc callback to use for generation
621 @param aArgs user defined paramaters (use at will) }
622 procedure LoadFromFunc(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil);
624 { load a texture from a resource
625 @param aInstance resource handle
626 @param aResource resource indentifier
627 @param aResType resource type (if known) }
628 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil);
630 { load a texture from a resource id
631 @param aInstance resource handle
632 @param aResource resource ID
633 @param aResType resource type }
634 procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
638 { save texture data to a file
639 @param aFilename filename to store texture in
640 @param aFileType file type to store data into }
641 procedure SaveToFile(const aFilename: String; const aFileType: TglBitmapFileType);
643 { save texture data to a stream
644 @param aFilename filename to store texture in
645 @param aFileType file type to store data into }
646 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
650 { convert texture data using a user defined callback
651 @param aFunc callback to use for converting
652 @param aCreateTemp create a temporary buffer to use for converting
653 @param aArgs user defined paramters (use at will)
654 @returns @true if converting was successful, @false otherwise }
655 function Convert(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
657 { convert texture data using a user defined callback
658 @param aSource glBitmap to read data from
659 @param aFunc callback to use for converting
660 @param aCreateTemp create a temporary buffer to use for converting
661 @param aFormat format of the new data
662 @param aArgs user defined paramters (use at will)
663 @returns @true if converting was successful, @false otherwise }
664 function Convert(const aSource: TglBitmapData; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
665 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
667 { convert texture data using a specific format
668 @param aFormat new format of texture data
669 @returns @true if converting was successful, @false otherwise }
670 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
675 { assign texture data to SDL surface
676 @param aSurface SDL surface to write data to
677 @returns @true on success, @false otherwise }
678 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
680 { assign texture data from SDL surface
681 @param aSurface SDL surface to read data from
682 @returns @true on success, @false otherwise }
683 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
685 { assign alpha channel data to SDL surface
686 @param aSurface SDL surface to write alpha channel data to
687 @returns @true on success, @false otherwise }
688 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
690 { assign alpha channel data from SDL surface
691 @param aSurface SDL surface to read data from
692 @param aFunc callback to use for converting
693 @param aArgs user defined parameters (use at will)
694 @returns @true on success, @false otherwise }
695 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
701 { assign texture data to TBitmap object
702 @param aBitmap TBitmap to write data to
703 @returns @true on success, @false otherwise }
704 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
706 { assign texture data from TBitmap object
707 @param aBitmap TBitmap to read data from
708 @returns @true on success, @false otherwise }
709 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
711 { assign alpha channel data to TBitmap object
712 @param aBitmap TBitmap to write data to
713 @returns @true on success, @false otherwise }
714 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
716 { assign alpha channel data from TBitmap object
717 @param aBitmap TBitmap to read data from
718 @param aFunc callback to use for converting
719 @param aArgs user defined parameters (use at will)
720 @returns @true on success, @false otherwise }
721 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
727 { assign texture data to TLazIntfImage object
728 @param aImage TLazIntfImage to write data to
729 @returns @true on success, @false otherwise }
730 function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
732 { assign texture data from TLazIntfImage object
733 @param aImage TLazIntfImage to read data from
734 @returns @true on success, @false otherwise }
735 function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
737 { assign alpha channel data to TLazIntfImage object
738 @param aImage TLazIntfImage to write data to
739 @returns @true on success, @false otherwise }
740 function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
742 { assign alpha channel data from TLazIntfImage object
743 @param aImage TLazIntfImage to read data from
744 @param aFunc callback to use for converting
745 @param aArgs user defined parameters (use at will)
746 @returns @true on success, @false otherwise }
747 function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
751 { load alpha channel data from resource
752 @param aInstance resource handle
753 @param aResource resource ID
754 @param aResType resource type
755 @param aFunc callback to use for converting
756 @param aArgs user defined parameters (use at will)
757 @returns @true on success, @false otherwise }
758 function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
760 { load alpha channel data from resource ID
761 @param aInstance resource handle
762 @param aResourceID resource ID
763 @param aResType resource type
764 @param aFunc callback to use for converting
765 @param aArgs user defined parameters (use at will)
766 @returns @true on success, @false otherwise }
767 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
769 { add alpha channel data from function
770 @param aFunc callback to get data from
771 @param aArgs user defined parameters (use at will)
772 @returns @true on success, @false otherwise }
773 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
775 { add alpha channel data from file (macro for: new glBitmap, LoadFromFile, AddAlphaFromGlBitmap)
776 @param aFilename file to load alpha channel data from
777 @param aFunc callback to use for converting
778 @param aArgs SetFormat user defined parameters (use at will)
779 @returns @true on success, @false otherwise }
780 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
782 { add alpha channel data from stream (macro for: new glBitmap, LoadFromStream, AddAlphaFromGlBitmap)
783 @param aStream stream to load alpha channel data from
784 @param aFunc callback to use for converting
785 @param aArgs user defined parameters (use at will)
786 @returns @true on success, @false otherwise }
787 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
789 { add alpha channel data from existing glBitmap object
790 @param aBitmap TglBitmap to copy alpha channel data from
791 @param aFunc callback to use for converting
792 @param aArgs user defined parameters (use at will)
793 @returns @true on success, @false otherwise }
794 function AddAlphaFromDataObj(const aDataObj: TglBitmapData; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
796 { add alpha to pixel if the pixels color is greter than the given color value
797 @param aRed red threshold (0-255)
798 @param aGreen green threshold (0-255)
799 @param aBlue blue threshold (0-255)
800 @param aDeviatation accepted deviatation (0-255)
801 @returns @true on success, @false otherwise }
802 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
804 { add alpha to pixel if the pixels color is greter than the given color value
805 @param aRed red threshold (0-Range.r)
806 @param aGreen green threshold (0-Range.g)
807 @param aBlue blue threshold (0-Range.b)
808 @param aDeviatation accepted deviatation (0-max(Range.rgb))
809 @returns @true on success, @false otherwise }
810 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
812 { add alpha to pixel if the pixels color is greter than the given color value
813 @param aRed red threshold (0.0-1.0)
814 @param aGreen green threshold (0.0-1.0)
815 @param aBlue blue threshold (0.0-1.0)
816 @param aDeviatation accepted deviatation (0.0-1.0)
817 @returns @true on success, @false otherwise }
818 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
820 { add a constand alpha value to all pixels
821 @param aAlpha alpha value to add (0-255)
822 @returns @true on success, @false otherwise }
823 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
825 { add a constand alpha value to all pixels
826 @param aAlpha alpha value to add (0-max(Range.rgb))
827 @returns @true on success, @false otherwise }
828 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
830 { add a constand alpha value to all pixels
831 @param aAlpha alpha value to add (0.0-1.0)
832 @returns @true on success, @false otherwise }
833 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
835 { remove alpha channel
836 @returns @true on success, @false otherwise }
837 function RemoveAlpha: Boolean; virtual;
840 { fill complete texture with one color
841 @param aRed red color for border (0-255)
842 @param aGreen green color for border (0-255)
843 @param aBlue blue color for border (0-255)
844 @param aAlpha alpha color for border (0-255) }
845 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
847 { fill complete texture with one color
848 @param aRed red color for border (0-Range.r)
849 @param aGreen green color for border (0-Range.g)
850 @param aBlue blue color for border (0-Range.b)
851 @param aAlpha alpha color for border (0-Range.a) }
852 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
854 { fill complete texture with one color
855 @param aRed red color for border (0.0-1.0)
856 @param aGreen green color for border (0.0-1.0)
857 @param aBlue blue color for border (0.0-1.0)
858 @param aAlpha alpha color for border (0.0-1.0) }
859 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single = 1.0);
863 { set data pointer of texture data
864 @param aData pointer to new texture data
865 @param aFormat format of the data stored at aData
866 @param aWidth width of the texture data
867 @param aHeight height of the texture data }
868 procedure SetData(const aData: PByte; const aFormat: TglBitmapFormat;
869 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual;
871 { create a clone of the current object
872 @returns clone of this object}
873 function Clone: TglBitmapData;
875 { invert color data (bitwise not)
876 @param aRed invert red channel
877 @param aGreen invert green channel
878 @param aBlue invert blue channel
879 @param aAlpha invert alpha channel }
880 procedure Invert(const aRed, aGreen, aBlue, aAlpha: Boolean);
882 { create normal map from texture data
883 @param aFunc normal map function to generate normalmap with
884 @param aScale scale of the normale stored in the normal map
885 @param aUseAlpha generate normalmap from alpha channel data (if present) }
886 procedure GenerateNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
887 const aScale: Single = 2; const aUseAlpha: Boolean = false);
889 public { constructor }
891 { constructor - creates a texutre data object }
892 constructor Create; overload;
894 { constructor - creates a texture data object and loads it from a file
895 @param aFilename file to load texture from }
896 constructor Create(const aFileName: String); overload;
898 { constructor - creates a texture data object and loads it from a stream
899 @param aStream stream to load texture from }
900 constructor Create(const aStream: TStream); overload;
902 { constructor - creates a texture data object with the given size, format and data
903 @param aSize size of the texture
904 @param aFormat format of the given data
905 @param aData texture data - be carefull: the data will now be managed by the texture data object }
906 constructor Create(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat; aData: PByte = nil); overload;
908 { constructor - creates a texture data object with the given size and format and uses the given callback to create the data
909 @param aSize size of the texture
910 @param aFormat format of the given data
911 @param aFunc callback to use for generating the data
912 @param aArgs user defined parameters (use at will) }
913 constructor Create(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
915 { constructor - creates a texture data object and loads it from a resource
916 @param aInstance resource handle
917 @param aResource resource indentifier
918 @param aResType resource type (if known) }
919 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
921 { constructor - creates a texture data object and loads it from a resource
922 @param aInstance resource handle
923 @param aResourceID resource ID
924 @param aResType resource type (if known) }
925 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
928 destructor Destroy; override;
932 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
933 { base class for all glBitmap classes. used to manage OpenGL texture objects
934 all operations on a bitmap object must be done from the render thread }
937 fID: GLuint; //< name of the OpenGL texture object
938 fTarget: GLuint; //< texture target (e.g. GL_TEXTURE_2D)
939 fDeleteTextureOnFree: Boolean; //< delete OpenGL texture object when this object is destroyed
941 // texture properties
942 fFilterMin: GLenum; //< min filter to apply to the texture
943 fFilterMag: GLenum; //< mag filter to apply to the texture
944 fWrapS: GLenum; //< texture wrapping for x axis
945 fWrapT: GLenum; //< texture wrapping for y axis
946 fWrapR: GLenum; //< texture wrapping for z axis
947 fAnisotropic: Integer; //< anisotropic level
948 fBorderColor: array[0..3] of Single; //< color of the texture border
950 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
952 fSwizzle: array[0..3] of GLenum; //< color channel swizzle
955 fIsResident: GLboolean; //< @true if OpenGL texture object has data, @false otherwise
958 fDimension: TglBitmapSize; //< size of this texture
959 fMipMap: TglBitmapMipMap; //< mipmap type
962 fCustomData: Pointer; //< user defined data
963 fCustomName: String; //< user defined name
964 fCustomNameW: WideString; //< user defined name
966 { @returns the actual width of the texture }
967 function GetWidth: Integer; virtual;
969 { @returns the actual height of the texture }
970 function GetHeight: Integer; virtual;
973 { set a new value for fCustomData }
974 procedure SetCustomData(const aValue: Pointer);
976 { set a new value for fCustomName }
977 procedure SetCustomName(const aValue: String);
979 { set a new value for fCustomNameW }
980 procedure SetCustomNameW(const aValue: WideString);
982 { set new value for fDeleteTextureOnFree }
983 procedure SetDeleteTextureOnFree(const aValue: Boolean);
985 { set name of OpenGL texture object }
986 procedure SetID(const aValue: Cardinal);
988 { set new value for fMipMap }
989 procedure SetMipMap(const aValue: TglBitmapMipMap);
991 { set new value for target }
992 procedure SetTarget(const aValue: Cardinal);
994 { set new value for fAnisotrophic }
995 procedure SetAnisotropic(const aValue: Integer);
998 { create OpenGL texture object (delete exisiting object if exists) }
1001 { setup texture parameters }
1002 procedure SetupParameters({$IFNDEF OPENGL_ES}out aBuildWithGlu: Boolean{$ENDIF});
1005 property Width: Integer read GetWidth; //< the actual width of the texture
1006 property Height: Integer read GetHeight; //< the actual height of the texture
1009 property ID: Cardinal read fID write SetID; //< name of the OpenGL texture object
1010 property Target: Cardinal read fTarget write SetTarget; //< texture target (e.g. GL_TEXTURE_2D)
1011 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree; //< delete texture object when this object is destroyed
1013 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap; //< mipmap type
1014 property Anisotropic: Integer read fAnisotropic write SetAnisotropic; //< anisotropic level
1016 property CustomData: Pointer read fCustomData write SetCustomData; //< user defined data (use at will)
1017 property CustomName: String read fCustomName write SetCustomName; //< user defined name (use at will)
1018 property CustomNameW: WideString read fCustomNameW write SetCustomNameW; //< user defined name (as WideString; use at will)
1020 property Dimension: TglBitmapSize read fDimension; //< size of the texture
1022 property IsResident: GLboolean read fIsResident; //< @true if OpenGL texture object has data, @false otherwise
1025 { this method is called after the constructor and sets the default values of this object }
1026 procedure AfterConstruction; override;
1028 { this method is called before the destructor and does some cleanup }
1029 procedure BeforeDestruction; override;
1033 { set the new value for texture border color
1034 @param aRed red color for border (0.0-1.0)
1035 @param aGreen green color for border (0.0-1.0)
1036 @param aBlue blue color for border (0.0-1.0)
1037 @param aAlpha alpha color for border (0.0-1.0) }
1038 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
1042 { set new texture filer
1043 @param aMin min filter
1044 @param aMag mag filter }
1045 procedure SetFilter(const aMin, aMag: GLenum);
1047 { set new texture wrapping
1048 @param S texture wrapping for x axis
1049 @param T texture wrapping for y axis
1050 @param R texture wrapping for z axis }
1052 const S: GLenum = GL_CLAMP_TO_EDGE;
1053 const T: GLenum = GL_CLAMP_TO_EDGE;
1054 const R: GLenum = GL_CLAMP_TO_EDGE);
1056 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
1058 @param r swizzle for red channel
1059 @param g swizzle for green channel
1060 @param b swizzle for blue channel
1061 @param a swizzle for alpha channel }
1062 procedure SetSwizzle(const r, g, b, a: GLenum);
1067 @param aEnableTextureUnit enable texture unit for this texture (e.g. glEnable(GL_TEXTURE_2D)) }
1068 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
1071 @param aDisableTextureUnit disable texture unit for this texture (e.g. glEnable(GL_TEXTURE_2D)) }
1072 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
1074 { upload texture data from given data object to video card
1075 @param aData texture data object that contains the actual data
1076 @param aCheckSize check size before upload and throw exception if something is wrong }
1077 procedure UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean = true); virtual;
1080 { download texture data from video card and store it into given data object
1081 @returns @true when download was successfull, @false otherwise }
1082 function DownloadData(const aDataObj: TglBitmapData): Boolean; virtual;
1085 { constructor - creates an empty texture }
1086 constructor Create; overload;
1088 { constructor - creates an texture object and uploads the given data }
1089 constructor Create(const aData: TglBitmapData); overload;
1093 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1094 {$IF NOT DEFINED(OPENGL_ES)}
1095 { wrapper class for 1-dimensional textures (OpenGL target = GL_TEXTURE_1D
1096 all operations on a bitmap object must be done from the render thread }
1097 TglBitmap1D = class(TglBitmap)
1100 { upload the texture data to video card
1101 @param aDataObj texture data object that contains the actual data
1102 @param aBuildWithGlu use glu functions to build mipmaps }
1103 procedure UploadDataIntern(const aDataObj: TglBitmapData; const aBuildWithGlu: Boolean);
1106 property Width; //< actual with of the texture
1108 { this method is called after constructor and initializes the object }
1109 procedure AfterConstruction; override;
1111 { upload texture data from given data object to video card
1112 @param aData texture data object that contains the actual data
1113 @param aCheckSize check size before upload and throw exception if something is wrong }
1114 procedure UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean = true); override;
1119 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1120 { wrapper class for 2-dimensional textures (OpenGL target = GL_TEXTURE_2D)
1121 all operations on a bitmap object must be done from the render thread }
1122 TglBitmap2D = class(TglBitmap)
1125 { upload the texture data to video card
1126 @param aDataObj texture data object that contains the actual data
1127 @param aTarget target o upload data to (e.g. GL_TEXTURE_2D)
1128 @param aBuildWithGlu use glu functions to build mipmaps }
1129 procedure UploadDataIntern(const aDataObj: TglBitmapData; const aTarget: GLenum
1130 {$IFNDEF OPENGL_ES}; const aBuildWithGlu: Boolean{$ENDIF});
1133 property Width; //< actual width of the texture
1134 property Height; //< actual height of the texture
1136 { this method is called after constructor and initializes the object }
1137 procedure AfterConstruction; override;
1139 { upload texture data from given data object to video card
1140 @param aData texture data object that contains the actual data
1141 @param aCheckSize check size before upload and throw exception if something is wrong }
1142 procedure UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean = true); override;
1146 { copy a part of the frame buffer to the texture
1147 @param aTop topmost pixel to copy
1148 @param aLeft leftmost pixel to copy
1149 @param aRight rightmost pixel to copy
1150 @param aBottom bottommost pixel to copy
1151 @param aFormat format to store data in
1152 @param aDataObj texture data object to store the data in }
1153 class procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat; const aDataObj: TglBitmapData);
1157 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1158 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
1159 { wrapper class for cube maps (OpenGL target = GL_TEXTURE_CUBE_MAP)
1160 all operations on a bitmap object must be done from the render thread }
1161 TglBitmapCubeMap = class(TglBitmap2D)
1164 fGenMode: Integer; //< generation mode for the cube map (e.g. GL_REFLECTION_MAP)
1168 { this method is called after constructor and initializes the object }
1169 procedure AfterConstruction; override;
1171 { upload texture data from given data object to video card
1172 @param aData texture data object that contains the actual data
1173 @param aCheckSize check size before upload and throw exception if something is wrong }
1174 procedure UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean = true); override;
1176 { upload texture data from given data object to video card
1177 @param aData texture data object that contains the actual data
1178 @param aCubeTarget cube map target to upload data to (e.g. GL_TEXTURE_CUBE_MAP_POSITIVE_X)
1179 @param aCheckSize check size before upload and throw exception if something is wrong }
1180 procedure UploadCubeMap(const aDataObj: TglBitmapData; const aCubeTarget: Cardinal; const aCheckSize: Boolean);
1183 @param aEnableTexCoordsGen enable cube map generator
1184 @param aEnableTextureUnit enable texture unit }
1185 procedure Bind({$IFNDEF OPENGL_ES}const aEnableTexCoordsGen: Boolean = true;{$ENDIF} const aEnableTextureUnit: Boolean = true); reintroduce; virtual;
1188 @param aDisableTexCoordsGen disable cube map generator
1189 @param aDisableTextureUnit disable texture unit }
1190 procedure Unbind({$IFNDEF OPENGL_ES}const aDisableTexCoordsGen: Boolean = true;{$ENDIF} const aDisableTextureUnit: Boolean = true); reintroduce; virtual;
1194 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
1195 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1196 { wrapper class for cube normal maps
1197 all operations on a bitmap object must be done from the render thread }
1198 TglBitmapNormalMap = class(TglBitmapCubeMap)
1200 { this method is called after constructor and initializes the object }
1201 procedure AfterConstruction; override;
1203 { create cube normal map from texture data and upload it to video card
1204 @param aSize size of each cube map texture
1205 @param aCheckSize check size before upload and throw exception if something is wrong }
1206 procedure GenerateNormalMap(const aSize: Integer = 32; const aCheckSize: Boolean = true);
1211 NULL_SIZE: TglBitmapSize = (Fields: []; X: 0; Y: 0);
1213 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1214 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1215 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1216 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1217 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1218 procedure glBitmapSetDefaultWrap(
1219 const S: Cardinal = GL_CLAMP_TO_EDGE;
1220 const T: Cardinal = GL_CLAMP_TO_EDGE;
1221 const R: Cardinal = GL_CLAMP_TO_EDGE);
1223 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
1224 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
1227 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1228 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1229 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1230 function glBitmapGetDefaultFormat: TglBitmapFormat;
1231 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1232 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1233 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
1234 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
1237 function glBitmapSize(X: Integer = -1; Y: Integer = -1): TglBitmapSize;
1238 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1239 function glBitmapRec4ub(const r, g, b, a: Byte): TglBitmapRec4ub;
1240 function glBitmapRec4ui(const r, g, b, a: Cardinal): TglBitmapRec4ui;
1241 function glBitmapRec4ul(const r, g, b, a: QWord): TglBitmapRec4ul;
1242 function glBitmapRec4ubCompare(const r1, r2: TglBitmapRec4ub): Boolean;
1243 function glBitmapRec4uiCompare(const r1, r2: TglBitmapRec4ui): Boolean;
1245 function glBitmapCreateTestData(const aFormat: TglBitmapFormat): TglBitmapData;
1248 function CreateGrayPalette: HPALETTE;
1254 Math, syncobjs, typinfo
1255 {$IF DEFINED(GLB_SUPPORT_JPEG_READ) AND DEFINED(GLB_LAZ_JPEG)}, FPReadJPEG{$IFEND};
1259 glBitmapDefaultDeleteTextureOnFree: Boolean;
1260 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1261 glBitmapDefaultFormat: TglBitmapFormat;
1262 glBitmapDefaultMipmap: TglBitmapMipMap;
1263 glBitmapDefaultFilterMin: Cardinal;
1264 glBitmapDefaultFilterMag: Cardinal;
1265 glBitmapDefaultWrapS: Cardinal;
1266 glBitmapDefaultWrapT: Cardinal;
1267 glBitmapDefaultWrapR: Cardinal;
1268 glDefaultSwizzle: array[0..3] of GLenum;
1270 ////////////////////////////////////////////////////////////////////////////////////////////////////
1272 TFormatDescriptor = class(TglBitmapFormatDescriptor)
1274 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1275 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1277 function CreateMappingData: Pointer; virtual;
1278 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1280 function IsEmpty: Boolean; virtual;
1281 function MaskMatch(const aMask: TglBitmapRec4ul): Boolean; virtual;
1283 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1285 constructor Create; virtual;
1287 class procedure Init;
1288 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1289 class function GetAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1290 class function GetFromMask(const aMask: TglBitmapRec4ul; const aBitCount: Integer = 0): TFormatDescriptor;
1291 class function GetFromPrecShift(const aPrec, aShift: TglBitmapRec4ub; const aBitCount: Integer): TFormatDescriptor;
1292 class procedure Clear;
1293 class procedure Finalize;
1295 TFormatDescriptorClass = class of TFormatDescriptor;
1297 TfdEmpty = class(TFormatDescriptor);
1299 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1300 TfdAlphaUB1 = class(TFormatDescriptor) //1* unsigned byte
1301 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1302 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1305 TfdLuminanceUB1 = class(TFormatDescriptor) //1* unsigned byte
1306 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1307 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1310 TfdUniversalUB1 = class(TFormatDescriptor) //1* unsigned byte
1311 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1312 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1315 TfdLuminanceAlphaUB2 = class(TfdLuminanceUB1) //2* unsigned byte
1316 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1317 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1320 TfdRGBub3 = class(TFormatDescriptor) //3* unsigned byte
1321 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1322 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1325 TfdBGRub3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1326 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1327 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1330 TfdRGBAub4 = class(TfdRGBub3) //3* unsigned byte
1331 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1332 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1335 TfdBGRAub4 = class(TfdBGRub3) //3* unsigned byte (inverse)
1336 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1337 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1340 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1341 TfdAlphaUS1 = class(TFormatDescriptor) //1* unsigned short
1342 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1343 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1346 TfdLuminanceUS1 = class(TFormatDescriptor) //1* unsigned short
1347 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1348 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1351 TfdUniversalUS1 = class(TFormatDescriptor) //1* unsigned short
1352 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1353 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1356 TfdDepthUS1 = class(TFormatDescriptor) //1* unsigned short
1357 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1358 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1361 TfdLuminanceAlphaUS2 = class(TfdLuminanceUS1) //2* unsigned short
1362 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1363 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1366 TfdRGBus3 = class(TFormatDescriptor) //3* unsigned short
1367 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1368 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1371 TfdBGRus3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1372 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1373 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1376 TfdRGBAus4 = class(TfdRGBus3) //4* unsigned short
1377 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1378 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1381 TfdARGBus4 = class(TfdRGBus3) //4* unsigned short
1382 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1383 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1386 TfdBGRAus4 = class(TfdBGRus3) //4* unsigned short (inverse)
1387 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1388 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1391 TfdABGRus4 = class(TfdBGRus3) //4* unsigned short (inverse)
1392 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1393 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1396 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1397 TfdUniversalUI1 = class(TFormatDescriptor) //1* unsigned int
1398 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1399 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1402 TfdDepthUI1 = class(TFormatDescriptor) //1* unsigned int
1403 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1404 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1407 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1408 TfdAlpha4ub1 = class(TfdAlphaUB1)
1409 procedure SetValues; override;
1412 TfdAlpha8ub1 = class(TfdAlphaUB1)
1413 procedure SetValues; override;
1416 TfdAlpha16us1 = class(TfdAlphaUS1)
1417 procedure SetValues; override;
1420 TfdLuminance4ub1 = class(TfdLuminanceUB1)
1421 procedure SetValues; override;
1424 TfdLuminance8ub1 = class(TfdLuminanceUB1)
1425 procedure SetValues; override;
1428 TfdLuminance16us1 = class(TfdLuminanceUS1)
1429 procedure SetValues; override;
1432 TfdLuminance4Alpha4ub2 = class(TfdLuminanceAlphaUB2)
1433 procedure SetValues; override;
1436 TfdLuminance6Alpha2ub2 = class(TfdLuminanceAlphaUB2)
1437 procedure SetValues; override;
1440 TfdLuminance8Alpha8ub2 = class(TfdLuminanceAlphaUB2)
1441 procedure SetValues; override;
1444 TfdLuminance12Alpha4us2 = class(TfdLuminanceAlphaUS2)
1445 procedure SetValues; override;
1448 TfdLuminance16Alpha16us2 = class(TfdLuminanceAlphaUS2)
1449 procedure SetValues; override;
1452 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1453 TfdR3G3B2ub1 = class(TfdUniversalUB1)
1454 procedure SetValues; override;
1457 TfdRGBX4us1 = class(TfdUniversalUS1)
1458 procedure SetValues; override;
1461 TfdXRGB4us1 = class(TfdUniversalUS1)
1462 procedure SetValues; override;
1465 TfdR5G6B5us1 = class(TfdUniversalUS1)
1466 procedure SetValues; override;
1469 TfdRGB5X1us1 = class(TfdUniversalUS1)
1470 procedure SetValues; override;
1473 TfdX1RGB5us1 = class(TfdUniversalUS1)
1474 procedure SetValues; override;
1477 TfdRGB8ub3 = class(TfdRGBub3)
1478 procedure SetValues; override;
1481 TfdRGBX8ui1 = class(TfdUniversalUI1)
1482 procedure SetValues; override;
1485 TfdXRGB8ui1 = class(TfdUniversalUI1)
1486 procedure SetValues; override;
1489 TfdRGB10X2ui1 = class(TfdUniversalUI1)
1490 procedure SetValues; override;
1493 TfdX2RGB10ui1 = class(TfdUniversalUI1)
1494 procedure SetValues; override;
1497 TfdRGB16us3 = class(TfdRGBus3)
1498 procedure SetValues; override;
1501 TfdRGBA4us1 = class(TfdUniversalUS1)
1502 procedure SetValues; override;
1505 TfdARGB4us1 = class(TfdUniversalUS1)
1506 procedure SetValues; override;
1509 TfdRGB5A1us1 = class(TfdUniversalUS1)
1510 procedure SetValues; override;
1513 TfdA1RGB5us1 = class(TfdUniversalUS1)
1514 procedure SetValues; override;
1517 TfdRGBA8ui1 = class(TfdUniversalUI1)
1518 procedure SetValues; override;
1521 TfdARGB8ui1 = class(TfdUniversalUI1)
1522 procedure SetValues; override;
1525 TfdRGBA8ub4 = class(TfdRGBAub4)
1526 procedure SetValues; override;
1529 TfdRGB10A2ui1 = class(TfdUniversalUI1)
1530 procedure SetValues; override;
1533 TfdA2RGB10ui1 = class(TfdUniversalUI1)
1534 procedure SetValues; override;
1537 TfdRGBA16us4 = class(TfdRGBAus4)
1538 procedure SetValues; override;
1541 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1542 TfdBGRX4us1 = class(TfdUniversalUS1)
1543 procedure SetValues; override;
1546 TfdXBGR4us1 = class(TfdUniversalUS1)
1547 procedure SetValues; override;
1550 TfdB5G6R5us1 = class(TfdUniversalUS1)
1551 procedure SetValues; override;
1554 TfdBGR5X1us1 = class(TfdUniversalUS1)
1555 procedure SetValues; override;
1558 TfdX1BGR5us1 = class(TfdUniversalUS1)
1559 procedure SetValues; override;
1562 TfdBGR8ub3 = class(TfdBGRub3)
1563 procedure SetValues; override;
1566 TfdBGRX8ui1 = class(TfdUniversalUI1)
1567 procedure SetValues; override;
1570 TfdXBGR8ui1 = class(TfdUniversalUI1)
1571 procedure SetValues; override;
1574 TfdBGR10X2ui1 = class(TfdUniversalUI1)
1575 procedure SetValues; override;
1578 TfdX2BGR10ui1 = class(TfdUniversalUI1)
1579 procedure SetValues; override;
1582 TfdBGR16us3 = class(TfdBGRus3)
1583 procedure SetValues; override;
1586 TfdBGRA4us1 = class(TfdUniversalUS1)
1587 procedure SetValues; override;
1590 TfdABGR4us1 = class(TfdUniversalUS1)
1591 procedure SetValues; override;
1594 TfdBGR5A1us1 = class(TfdUniversalUS1)
1595 procedure SetValues; override;
1598 TfdA1BGR5us1 = class(TfdUniversalUS1)
1599 procedure SetValues; override;
1602 TfdBGRA8ui1 = class(TfdUniversalUI1)
1603 procedure SetValues; override;
1606 TfdABGR8ui1 = class(TfdUniversalUI1)
1607 procedure SetValues; override;
1610 TfdBGRA8ub4 = class(TfdBGRAub4)
1611 procedure SetValues; override;
1614 TfdBGR10A2ui1 = class(TfdUniversalUI1)
1615 procedure SetValues; override;
1618 TfdA2BGR10ui1 = class(TfdUniversalUI1)
1619 procedure SetValues; override;
1622 TfdBGRA16us4 = class(TfdBGRAus4)
1623 procedure SetValues; override;
1626 TfdDepth16us1 = class(TfdDepthUS1)
1627 procedure SetValues; override;
1630 TfdDepth24ui1 = class(TfdDepthUI1)
1631 procedure SetValues; override;
1634 TfdDepth32ui1 = class(TfdDepthUI1)
1635 procedure SetValues; override;
1638 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1639 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1640 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1641 procedure SetValues; override;
1644 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1645 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1646 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1647 procedure SetValues; override;
1650 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1651 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1652 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1653 procedure SetValues; override;
1656 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1657 TbmpBitfieldFormat = class(TFormatDescriptor)
1659 procedure SetCustomValues(const aBPP: Integer; aMask: TglBitmapRec4ul); overload;
1660 procedure SetCustomValues(const aBBP: Integer; const aPrec, aShift: TglBitmapRec4ub); overload;
1661 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1662 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1665 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1666 TbmpColorTableEnty = packed record
1669 TbmpColorTable = array of TbmpColorTableEnty;
1670 TbmpColorTableFormat = class(TFormatDescriptor)
1672 fColorTable: TbmpColorTable;
1674 procedure SetValues; override;
1676 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1678 procedure SetCustomValues(const aFormat: TglBitmapFormat; const aBPP: Integer; const aPrec, aShift: TglBitmapRec4ub); overload;
1679 procedure CalcValues;
1680 procedure CreateColorTable;
1682 function CreateMappingData: Pointer; override;
1683 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1684 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1685 destructor Destroy; override;
1689 LUMINANCE_WEIGHT_R = 0.30;
1690 LUMINANCE_WEIGHT_G = 0.59;
1691 LUMINANCE_WEIGHT_B = 0.11;
1693 ALPHA_WEIGHT_R = 0.30;
1694 ALPHA_WEIGHT_G = 0.59;
1695 ALPHA_WEIGHT_B = 0.11;
1697 DEPTH_WEIGHT_R = 0.333333333;
1698 DEPTH_WEIGHT_G = 0.333333333;
1699 DEPTH_WEIGHT_B = 0.333333333;
1701 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1712 TfdLuminance4Alpha4ub2,
1713 TfdLuminance6Alpha2ub2,
1714 TfdLuminance8Alpha8ub2,
1715 TfdLuminance12Alpha4us2,
1716 TfdLuminance16Alpha16us2,
1775 FormatDescriptorCS: TCriticalSection;
1776 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1778 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1779 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1781 inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1784 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1785 constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat);
1787 inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1790 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1791 function glBitmapSize(X: Integer; Y: Integer): TglBitmapSize;
1793 result.Fields := [];
1795 result.Fields := result.Fields + [ffX];
1797 result.Fields := result.Fields + [ffY];
1798 result.X := Max(0, X);
1799 result.Y := Max(0, Y);
1802 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1803 function glBitmapPosition(X: Integer; Y: Integer): TglBitmapPixelPosition;
1805 result := glBitmapSize(X, Y);
1808 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1809 function glBitmapRec4ub(const r, g, b, a: Byte): TglBitmapRec4ub;
1817 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1818 function glBitmapRec4ui(const r, g, b, a: Cardinal): TglBitmapRec4ui;
1826 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1827 function glBitmapRec4ul(const r, g, b, a: QWord): TglBitmapRec4ul;
1835 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1836 function glBitmapRec4ubCompare(const r1, r2: TglBitmapRec4ub): Boolean;
1841 for i := 0 to high(r1.arr) do
1842 if (r1.arr[i] <> r2.arr[i]) then
1847 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1848 function glBitmapRec4uiCompare(const r1, r2: TglBitmapRec4ui): Boolean;
1853 for i := 0 to high(r1.arr) do
1854 if (r1.arr[i] <> r2.arr[i]) then
1859 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1860 function glBitmapCreateTestData(const aFormat: TglBitmapFormat): TglBitmapData;
1862 desc: TFormatDescriptor;
1866 px: TglBitmapPixelData;
1869 desc := TFormatDescriptor.Get(aFormat);
1870 if (desc.IsCompressed) or (desc.glFormat = 0) then
1873 p := GetMemory(ceil(25 * desc.BytesPerPixel)); // 5 x 5 pixel
1874 md := desc.CreateMappingData;
1877 desc.PreparePixel(px);
1879 for x := 0 to 4 do begin
1880 px.Data := glBitmapRec4ui(0, 0, 0, 0);
1881 for i := 0 to 3 do begin
1882 if ((y < 3) and (y = i)) or
1883 ((y = 3) and (i < 3)) or
1884 ((y = 4) and (i = 3))
1886 px.Data.arr[i] := Trunc(px.Range.arr[i] / 4 * x)
1887 else if ((y < 4) and (i = 3)) or
1888 ((y = 4) and (i < 3))
1890 px.Data.arr[i] := px.Range.arr[i]
1892 px.Data.arr[i] := 0; //px.Range.arr[i];
1894 desc.Map(px, tmp, md);
1897 desc.FreeMappingData(md);
1900 result := TglBitmapData.Create(glBitmapPosition(5, 5), aFormat, p);
1903 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1904 function glBitmapShiftRec(const r, g, b, a: Byte): TglBitmapRec4ub;
1912 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1913 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1919 tfAlpha4ub1, tfAlpha8ub1,
1920 tfLuminance4ub1, tfLuminance8ub1, tfR3G3B2ub1,
1923 tfLuminance4Alpha4ub2, tfLuminance6Alpha2ub2, tfLuminance8Alpha8ub2,
1924 tfRGBX4us1, tfXRGB4us1, tfRGB5X1us1, tfX1RGB5us1, tfR5G6B5us1, tfRGB5A1us1, tfA1RGB5us1, tfRGBA4us1, tfARGB4us1,
1925 tfBGRX4us1, tfXBGR4us1, tfBGR5X1us1, tfX1BGR5us1, tfB5G6R5us1, tfBGR5A1us1, tfA1BGR5us1, tfBGRA4us1, tfABGR4us1,
1928 tfBGR8ub3, tfRGB8ub3,
1931 tfRGBX8ui1, tfXRGB8ui1, tfRGB10X2ui1, tfX2RGB10ui1, tfRGBA8ui1, tfARGB8ui1, tfRGBA8ub4, tfRGB10A2ui1, tfA2RGB10ui1,
1932 tfBGRX8ui1, tfXBGR8ui1, tfBGR10X2ui1, tfX2BGR10ui1, tfBGRA8ui1, tfABGR8ui1, tfBGRA8ub4, tfBGR10A2ui1, tfA2BGR10ui1])
1934 result := result + [ ftBMP ];
1938 tfAlpha4ub1, tfAlpha8ub1, tfLuminance4ub1, tfLuminance8ub1,
1941 tfAlpha16us1, tfLuminance16us1,
1942 tfLuminance4Alpha4ub2, tfLuminance6Alpha2ub2, tfLuminance8Alpha8ub2,
1943 tfX1RGB5us1, tfARGB4us1, tfA1RGB5us1, tfDepth16us1,
1949 tfX2RGB10ui1, tfARGB8ui1, tfBGRA8ub4, tfA2RGB10ui1,
1950 tfDepth24ui1, tfDepth32ui1])
1952 result := result + [ftTGA];
1954 if not (aFormat in [tfEmpty, tfRGB16us3, tfBGR16us3]) then
1955 result := result + [ftDDS];
1957 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1959 tfAlpha8ub1, tfLuminance8ub1, tfLuminance8Alpha8ub2,
1960 tfRGB8ub3, tfRGBA8ui1,
1961 tfBGR8ub3, tfBGRA8ui1] then
1962 result := result + [ftPNG];
1965 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1966 if aFormat in [tfAlpha8ub1, tfLuminance8ub1, tfRGB8ub3, tfBGR8ub3] then
1967 result := result + [ftJPEG];
1971 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1972 function IsPowerOfTwo(aNumber: Integer): Boolean;
1974 while (aNumber and 1) = 0 do
1975 aNumber := aNumber shr 1;
1976 result := aNumber = 1;
1979 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1980 function GetTopMostBit(aBitSet: QWord): Integer;
1983 while aBitSet > 0 do begin
1985 aBitSet := aBitSet shr 1;
1989 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1990 function CountSetBits(aBitSet: QWord): Integer;
1993 while aBitSet > 0 do begin
1994 if (aBitSet and 1) = 1 then
1996 aBitSet := aBitSet shr 1;
2000 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
2004 LUMINANCE_WEIGHT_R * aPixel.Data.r +
2005 LUMINANCE_WEIGHT_G * aPixel.Data.g +
2006 LUMINANCE_WEIGHT_B * aPixel.Data.b);
2009 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2010 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
2013 DEPTH_WEIGHT_R * aPixel.Data.r +
2014 DEPTH_WEIGHT_G * aPixel.Data.g +
2015 DEPTH_WEIGHT_B * aPixel.Data.b);
2018 {$IFDEF GLB_SDL_IMAGE}
2019 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2020 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2021 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2022 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2024 result := TStream(context^.unknown.data1).Seek(offset, whence);
2027 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2029 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2032 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2034 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2037 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2042 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2044 result := SDL_AllocRW;
2046 if result = nil then
2047 raise EglBitmap.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2049 result^.seek := glBitmapRWseek;
2050 result^.read := glBitmapRWread;
2051 result^.write := glBitmapRWwrite;
2052 result^.close := glBitmapRWclose;
2053 result^.unknown.data1 := Stream;
2057 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2058 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2060 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2063 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2064 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2066 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2069 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2070 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2072 glBitmapDefaultMipmap := aValue;
2075 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2076 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2078 glBitmapDefaultFormat := aFormat;
2081 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2082 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2084 glBitmapDefaultFilterMin := aMin;
2085 glBitmapDefaultFilterMag := aMag;
2088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2089 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2091 glBitmapDefaultWrapS := S;
2092 glBitmapDefaultWrapT := T;
2093 glBitmapDefaultWrapR := R;
2096 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2097 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
2098 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
2100 glDefaultSwizzle[0] := r;
2101 glDefaultSwizzle[1] := g;
2102 glDefaultSwizzle[2] := b;
2103 glDefaultSwizzle[3] := a;
2107 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2108 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2110 result := glBitmapDefaultDeleteTextureOnFree;
2113 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2114 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2116 result := glBitmapDefaultFreeDataAfterGenTextures;
2119 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2120 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2122 result := glBitmapDefaultMipmap;
2125 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2126 function glBitmapGetDefaultFormat: TglBitmapFormat;
2128 result := glBitmapDefaultFormat;
2131 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2132 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
2134 aMin := glBitmapDefaultFilterMin;
2135 aMag := glBitmapDefaultFilterMag;
2138 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2139 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
2141 S := glBitmapDefaultWrapS;
2142 T := glBitmapDefaultWrapT;
2143 R := glBitmapDefaultWrapR;
2146 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
2147 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2148 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
2150 r := glDefaultSwizzle[0];
2151 g := glDefaultSwizzle[1];
2152 b := glDefaultSwizzle[2];
2153 a := glDefaultSwizzle[3];
2157 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2158 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2159 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2160 function TFormatDescriptor.CreateMappingData: Pointer;
2165 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2166 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2171 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2172 function TFormatDescriptor.IsEmpty: Boolean;
2174 result := (fFormat = tfEmpty);
2177 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2178 function TFormatDescriptor.MaskMatch(const aMask: TglBitmapRec4ul): Boolean;
2184 if (aMask.r = 0) and (aMask.g = 0) and (aMask.b = 0) and (aMask.a = 0) then
2185 raise EglBitmap.Create('FormatCheckFormat - All Masks are 0');
2188 if (aMask.arr[i] <> m.arr[i]) then
2193 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2194 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2196 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2197 aPixel.Data := Range;
2198 aPixel.Format := fFormat;
2199 aPixel.Range := Range;
2202 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2203 constructor TFormatDescriptor.Create;
2208 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2209 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2210 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2211 procedure TfdAlphaUB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2213 aData^ := aPixel.Data.a;
2217 procedure TfdAlphaUB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2222 aPixel.Data.a := aData^;
2226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2227 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2229 procedure TfdLuminanceUB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2231 aData^ := LuminanceWeight(aPixel);
2235 procedure TfdLuminanceUB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2237 aPixel.Data.r := aData^;
2238 aPixel.Data.g := aData^;
2239 aPixel.Data.b := aData^;
2244 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2245 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2246 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2247 procedure TfdUniversalUB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2253 if (Range.arr[i] > 0) then
2254 aData^ := aData^ or ((aPixel.Data.arr[i] and Range.arr[i]) shl fShift.arr[i]);
2258 procedure TfdUniversalUB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2263 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and Range.arr[i];
2267 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2268 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2269 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2270 procedure TfdLuminanceAlphaUB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2272 inherited Map(aPixel, aData, aMapData);
2273 aData^ := aPixel.Data.a;
2277 procedure TfdLuminanceAlphaUB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2279 inherited Unmap(aData, aPixel, aMapData);
2280 aPixel.Data.a := aData^;
2284 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2285 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2286 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2287 procedure TfdRGBub3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2289 aData^ := aPixel.Data.r;
2291 aData^ := aPixel.Data.g;
2293 aData^ := aPixel.Data.b;
2297 procedure TfdRGBub3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2299 aPixel.Data.r := aData^;
2301 aPixel.Data.g := aData^;
2303 aPixel.Data.b := aData^;
2308 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2309 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2310 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2311 procedure TfdBGRub3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2313 aData^ := aPixel.Data.b;
2315 aData^ := aPixel.Data.g;
2317 aData^ := aPixel.Data.r;
2321 procedure TfdBGRub3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2323 aPixel.Data.b := aData^;
2325 aPixel.Data.g := aData^;
2327 aPixel.Data.r := aData^;
2332 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2333 //TfdRGBA_UB4//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2334 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2335 procedure TfdRGBAub4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2337 inherited Map(aPixel, aData, aMapData);
2338 aData^ := aPixel.Data.a;
2342 procedure TfdRGBAub4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2344 inherited Unmap(aData, aPixel, aMapData);
2345 aPixel.Data.a := aData^;
2349 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2350 //TfdBGRA_UB4//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2351 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2352 procedure TfdBGRAub4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2354 inherited Map(aPixel, aData, aMapData);
2355 aData^ := aPixel.Data.a;
2359 procedure TfdBGRAub4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2361 inherited Unmap(aData, aPixel, aMapData);
2362 aPixel.Data.a := aData^;
2366 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2367 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2368 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2369 procedure TfdAlphaUS1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2371 PWord(aData)^ := aPixel.Data.a;
2375 procedure TfdAlphaUS1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2380 aPixel.Data.a := PWord(aData)^;
2384 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2385 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2386 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2387 procedure TfdLuminanceUS1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2389 PWord(aData)^ := LuminanceWeight(aPixel);
2393 procedure TfdLuminanceUS1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2395 aPixel.Data.r := PWord(aData)^;
2396 aPixel.Data.g := PWord(aData)^;
2397 aPixel.Data.b := PWord(aData)^;
2402 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2403 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2404 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2405 procedure TfdUniversalUS1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2411 if (Range.arr[i] > 0) then
2412 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and Range.arr[i]) shl fShift.arr[i]);
2416 procedure TfdUniversalUS1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2421 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and Range.arr[i];
2425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2426 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2428 procedure TfdDepthUS1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2430 PWord(aData)^ := DepthWeight(aPixel);
2434 procedure TfdDepthUS1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2436 aPixel.Data.r := PWord(aData)^;
2437 aPixel.Data.g := PWord(aData)^;
2438 aPixel.Data.b := PWord(aData)^;
2439 aPixel.Data.a := PWord(aData)^;;
2443 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2444 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2445 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2446 procedure TfdLuminanceAlphaUS2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2448 inherited Map(aPixel, aData, aMapData);
2449 PWord(aData)^ := aPixel.Data.a;
2453 procedure TfdLuminanceAlphaUS2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2455 inherited Unmap(aData, aPixel, aMapData);
2456 aPixel.Data.a := PWord(aData)^;
2460 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2461 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2462 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2463 procedure TfdRGBus3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2465 PWord(aData)^ := aPixel.Data.r;
2467 PWord(aData)^ := aPixel.Data.g;
2469 PWord(aData)^ := aPixel.Data.b;
2473 procedure TfdRGBus3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2475 aPixel.Data.r := PWord(aData)^;
2477 aPixel.Data.g := PWord(aData)^;
2479 aPixel.Data.b := PWord(aData)^;
2484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2485 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2486 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2487 procedure TfdBGRus3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2489 PWord(aData)^ := aPixel.Data.b;
2491 PWord(aData)^ := aPixel.Data.g;
2493 PWord(aData)^ := aPixel.Data.r;
2497 procedure TfdBGRus3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2499 aPixel.Data.b := PWord(aData)^;
2501 aPixel.Data.g := PWord(aData)^;
2503 aPixel.Data.r := PWord(aData)^;
2508 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2509 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2510 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2511 procedure TfdRGBAus4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2513 inherited Map(aPixel, aData, aMapData);
2514 PWord(aData)^ := aPixel.Data.a;
2518 procedure TfdRGBAus4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2520 inherited Unmap(aData, aPixel, aMapData);
2521 aPixel.Data.a := PWord(aData)^;
2525 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2526 //TfdARGB_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2527 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2528 procedure TfdARGBus4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2530 PWord(aData)^ := aPixel.Data.a;
2532 inherited Map(aPixel, aData, aMapData);
2535 procedure TfdARGBus4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2537 aPixel.Data.a := PWord(aData)^;
2539 inherited Unmap(aData, aPixel, aMapData);
2542 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2543 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2544 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2545 procedure TfdBGRAus4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2547 inherited Map(aPixel, aData, aMapData);
2548 PWord(aData)^ := aPixel.Data.a;
2552 procedure TfdBGRAus4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2554 inherited Unmap(aData, aPixel, aMapData);
2555 aPixel.Data.a := PWord(aData)^;
2559 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2560 //TfdABGR_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2561 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2562 procedure TfdABGRus4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2564 PWord(aData)^ := aPixel.Data.a;
2566 inherited Map(aPixel, aData, aMapData);
2569 procedure TfdABGRus4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2571 aPixel.Data.a := PWord(aData)^;
2573 inherited Unmap(aData, aPixel, aMapData);
2576 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2577 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2578 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2579 procedure TfdUniversalUI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2583 PCardinal(aData)^ := 0;
2585 if (Range.arr[i] > 0) then
2586 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and Range.arr[i]) shl fShift.arr[i]);
2590 procedure TfdUniversalUI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2595 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and Range.arr[i];
2599 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2600 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2601 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2602 procedure TfdDepthUI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2604 PCardinal(aData)^ := DepthWeight(aPixel);
2608 procedure TfdDepthUI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2610 aPixel.Data.r := PCardinal(aData)^;
2611 aPixel.Data.g := PCardinal(aData)^;
2612 aPixel.Data.b := PCardinal(aData)^;
2613 aPixel.Data.a := PCardinal(aData)^;
2617 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2618 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2619 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2620 procedure TfdAlpha4ub1.SetValues;
2622 inherited SetValues;
2624 fFormat := tfAlpha4ub1;
2625 fWithAlpha := tfAlpha4ub1;
2626 fPrecision := glBitmapRec4ub(0, 0, 0, 8);
2627 fShift := glBitmapRec4ub(0, 0, 0, 0);
2629 fOpenGLFormat := tfAlpha4ub1;
2630 fglFormat := GL_ALPHA;
2631 fglInternalFormat := GL_ALPHA4;
2632 fglDataFormat := GL_UNSIGNED_BYTE;
2634 fOpenGLFormat := tfAlpha8ub1;
2638 procedure TfdAlpha8ub1.SetValues;
2640 inherited SetValues;
2642 fFormat := tfAlpha8ub1;
2643 fWithAlpha := tfAlpha8ub1;
2644 fPrecision := glBitmapRec4ub(0, 0, 0, 8);
2645 fShift := glBitmapRec4ub(0, 0, 0, 0);
2646 fOpenGLFormat := tfAlpha8ub1;
2647 fglFormat := GL_ALPHA;
2648 fglInternalFormat := {$IFNDEF OPENGL_ES}GL_ALPHA8{$ELSE}GL_ALPHA{$ENDIF};
2649 fglDataFormat := GL_UNSIGNED_BYTE;
2652 procedure TfdAlpha16us1.SetValues;
2654 inherited SetValues;
2655 fBitsPerPixel := 16;
2656 fFormat := tfAlpha16us1;
2657 fWithAlpha := tfAlpha16us1;
2658 fPrecision := glBitmapRec4ub(0, 0, 0, 16);
2659 fShift := glBitmapRec4ub(0, 0, 0, 0);
2661 fOpenGLFormat := tfAlpha16us1;
2662 fglFormat := GL_ALPHA;
2663 fglInternalFormat := GL_ALPHA16;
2664 fglDataFormat := GL_UNSIGNED_SHORT;
2666 fOpenGLFormat := tfAlpha8ub1;
2670 procedure TfdLuminance4ub1.SetValues;
2672 inherited SetValues;
2674 fFormat := tfLuminance4ub1;
2675 fWithAlpha := tfLuminance4Alpha4ub2;
2676 fWithoutAlpha := tfLuminance4ub1;
2677 fPrecision := glBitmapRec4ub(8, 8, 8, 0);
2678 fShift := glBitmapRec4ub(0, 0, 0, 0);
2680 fOpenGLFormat := tfLuminance4ub1;
2681 fglFormat := GL_LUMINANCE;
2682 fglInternalFormat := GL_LUMINANCE4;
2683 fglDataFormat := GL_UNSIGNED_BYTE;
2685 fOpenGLFormat := tfLuminance8ub1;
2689 procedure TfdLuminance8ub1.SetValues;
2691 inherited SetValues;
2693 fFormat := tfLuminance8ub1;
2694 fWithAlpha := tfLuminance8Alpha8ub2;
2695 fWithoutAlpha := tfLuminance8ub1;
2696 fOpenGLFormat := tfLuminance8ub1;
2697 fPrecision := glBitmapRec4ub(8, 8, 8, 0);
2698 fShift := glBitmapRec4ub(0, 0, 0, 0);
2699 fglFormat := GL_LUMINANCE;
2700 fglInternalFormat := {$IFNDEF OPENGL_ES}GL_LUMINANCE8{$ELSE}GL_LUMINANCE{$ENDIF};
2701 fglDataFormat := GL_UNSIGNED_BYTE;
2704 procedure TfdLuminance16us1.SetValues;
2706 inherited SetValues;
2707 fBitsPerPixel := 16;
2708 fFormat := tfLuminance16us1;
2709 fWithAlpha := tfLuminance16Alpha16us2;
2710 fWithoutAlpha := tfLuminance16us1;
2711 fPrecision := glBitmapRec4ub(16, 16, 16, 0);
2712 fShift := glBitmapRec4ub( 0, 0, 0, 0);
2714 fOpenGLFormat := tfLuminance16us1;
2715 fglFormat := GL_LUMINANCE;
2716 fglInternalFormat := GL_LUMINANCE16;
2717 fglDataFormat := GL_UNSIGNED_SHORT;
2719 fOpenGLFormat := tfLuminance8ub1;
2723 procedure TfdLuminance4Alpha4ub2.SetValues;
2725 inherited SetValues;
2726 fBitsPerPixel := 16;
2727 fFormat := tfLuminance4Alpha4ub2;
2728 fWithAlpha := tfLuminance4Alpha4ub2;
2729 fWithoutAlpha := tfLuminance4ub1;
2730 fPrecision := glBitmapRec4ub(8, 8, 8, 8);
2731 fShift := glBitmapRec4ub(0, 0, 0, 8);
2733 fOpenGLFormat := tfLuminance4Alpha4ub2;
2734 fglFormat := GL_LUMINANCE_ALPHA;
2735 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
2736 fglDataFormat := GL_UNSIGNED_BYTE;
2738 fOpenGLFormat := tfLuminance8Alpha8ub2;
2742 procedure TfdLuminance6Alpha2ub2.SetValues;
2744 inherited SetValues;
2745 fBitsPerPixel := 16;
2746 fFormat := tfLuminance6Alpha2ub2;
2747 fWithAlpha := tfLuminance6Alpha2ub2;
2748 fWithoutAlpha := tfLuminance8ub1;
2749 fPrecision := glBitmapRec4ub(8, 8, 8, 8);
2750 fShift := glBitmapRec4ub(0, 0, 0, 8);
2752 fOpenGLFormat := tfLuminance6Alpha2ub2;
2753 fglFormat := GL_LUMINANCE_ALPHA;
2754 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
2755 fglDataFormat := GL_UNSIGNED_BYTE;
2757 fOpenGLFormat := tfLuminance8Alpha8ub2;
2761 procedure TfdLuminance8Alpha8ub2.SetValues;
2763 inherited SetValues;
2764 fBitsPerPixel := 16;
2765 fFormat := tfLuminance8Alpha8ub2;
2766 fWithAlpha := tfLuminance8Alpha8ub2;
2767 fWithoutAlpha := tfLuminance8ub1;
2768 fOpenGLFormat := tfLuminance8Alpha8ub2;
2769 fPrecision := glBitmapRec4ub(8, 8, 8, 8);
2770 fShift := glBitmapRec4ub(0, 0, 0, 8);
2771 fglFormat := GL_LUMINANCE_ALPHA;
2772 fglInternalFormat := {$IFNDEF OPENGL_ES}GL_LUMINANCE8_ALPHA8{$ELSE}GL_LUMINANCE_ALPHA{$ENDIF};
2773 fglDataFormat := GL_UNSIGNED_BYTE;
2776 procedure TfdLuminance12Alpha4us2.SetValues;
2778 inherited SetValues;
2779 fBitsPerPixel := 32;
2780 fFormat := tfLuminance12Alpha4us2;
2781 fWithAlpha := tfLuminance12Alpha4us2;
2782 fWithoutAlpha := tfLuminance16us1;
2783 fPrecision := glBitmapRec4ub(16, 16, 16, 16);
2784 fShift := glBitmapRec4ub( 0, 0, 0, 16);
2786 fOpenGLFormat := tfLuminance12Alpha4us2;
2787 fglFormat := GL_LUMINANCE_ALPHA;
2788 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
2789 fglDataFormat := GL_UNSIGNED_SHORT;
2791 fOpenGLFormat := tfLuminance8Alpha8ub2;
2795 procedure TfdLuminance16Alpha16us2.SetValues;
2797 inherited SetValues;
2798 fBitsPerPixel := 32;
2799 fFormat := tfLuminance16Alpha16us2;
2800 fWithAlpha := tfLuminance16Alpha16us2;
2801 fWithoutAlpha := tfLuminance16us1;
2802 fPrecision := glBitmapRec4ub(16, 16, 16, 16);
2803 fShift := glBitmapRec4ub( 0, 0, 0, 16);
2805 fOpenGLFormat := tfLuminance16Alpha16us2;
2806 fglFormat := GL_LUMINANCE_ALPHA;
2807 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
2808 fglDataFormat := GL_UNSIGNED_SHORT;
2810 fOpenGLFormat := tfLuminance8Alpha8ub2;
2814 procedure TfdR3G3B2ub1.SetValues;
2816 inherited SetValues;
2818 fFormat := tfR3G3B2ub1;
2819 fWithAlpha := tfRGBA4us1;
2820 fWithoutAlpha := tfR3G3B2ub1;
2821 fRGBInverted := tfEmpty;
2822 fPrecision := glBitmapRec4ub(3, 3, 2, 0);
2823 fShift := glBitmapRec4ub(5, 2, 0, 0);
2825 fOpenGLFormat := tfR3G3B2ub1;
2826 fglFormat := GL_RGB;
2827 fglInternalFormat := GL_R3_G3_B2;
2828 fglDataFormat := GL_UNSIGNED_BYTE_3_3_2;
2830 fOpenGLFormat := tfR5G6B5us1;
2834 procedure TfdRGBX4us1.SetValues;
2836 inherited SetValues;
2837 fBitsPerPixel := 16;
2838 fFormat := tfRGBX4us1;
2839 fWithAlpha := tfRGBA4us1;
2840 fWithoutAlpha := tfRGBX4us1;
2841 fRGBInverted := tfBGRX4us1;
2842 fPrecision := glBitmapRec4ub( 4, 4, 4, 0);
2843 fShift := glBitmapRec4ub(12, 8, 4, 0);
2845 fOpenGLFormat := tfRGBX4us1;
2846 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
2847 fglInternalFormat := GL_RGB4;
2848 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4;
2850 fOpenGLFormat := tfR5G6B5us1;
2854 procedure TfdXRGB4us1.SetValues;
2856 inherited SetValues;
2857 fBitsPerPixel := 16;
2858 fFormat := tfXRGB4us1;
2859 fWithAlpha := tfARGB4us1;
2860 fWithoutAlpha := tfXRGB4us1;
2861 fRGBInverted := tfXBGR4us1;
2862 fPrecision := glBitmapRec4ub(4, 4, 4, 0);
2863 fShift := glBitmapRec4ub(8, 4, 0, 0);
2865 fOpenGLFormat := tfXRGB4us1;
2866 fglFormat := GL_BGRA;
2867 fglInternalFormat := GL_RGB4;
2868 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
2870 fOpenGLFormat := tfR5G6B5us1;
2874 procedure TfdR5G6B5us1.SetValues;
2876 inherited SetValues;
2877 fBitsPerPixel := 16;
2878 fFormat := tfR5G6B5us1;
2879 fWithAlpha := tfRGB5A1us1;
2880 fWithoutAlpha := tfR5G6B5us1;
2881 fRGBInverted := tfB5G6R5us1;
2882 fPrecision := glBitmapRec4ub( 5, 6, 5, 0);
2883 fShift := glBitmapRec4ub(11, 5, 0, 0);
2884 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
2885 fOpenGLFormat := tfR5G6B5us1;
2886 fglFormat := GL_RGB;
2887 fglInternalFormat := GL_RGB565;
2888 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
2890 fOpenGLFormat := tfRGB8ub3;
2894 procedure TfdRGB5X1us1.SetValues;
2896 inherited SetValues;
2897 fBitsPerPixel := 16;
2898 fFormat := tfRGB5X1us1;
2899 fWithAlpha := tfRGB5A1us1;
2900 fWithoutAlpha := tfRGB5X1us1;
2901 fRGBInverted := tfBGR5X1us1;
2902 fPrecision := glBitmapRec4ub( 5, 5, 5, 0);
2903 fShift := glBitmapRec4ub(11, 6, 1, 0);
2905 fOpenGLFormat := tfRGB5X1us1;
2906 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
2907 fglInternalFormat := GL_RGB5;
2908 fglDataFormat := GL_UNSIGNED_SHORT_5_5_5_1;
2910 fOpenGLFormat := tfR5G6B5us1;
2914 procedure TfdX1RGB5us1.SetValues;
2916 inherited SetValues;
2917 fBitsPerPixel := 16;
2918 fFormat := tfX1RGB5us1;
2919 fWithAlpha := tfA1RGB5us1;
2920 fWithoutAlpha := tfX1RGB5us1;
2921 fRGBInverted := tfX1BGR5us1;
2922 fPrecision := glBitmapRec4ub( 5, 5, 5, 0);
2923 fShift := glBitmapRec4ub(10, 5, 0, 0);
2925 fOpenGLFormat := tfX1RGB5us1;
2926 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
2927 fglInternalFormat := GL_RGB5;
2928 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
2930 fOpenGLFormat := tfR5G6B5us1;
2934 procedure TfdRGB8ub3.SetValues;
2936 inherited SetValues;
2937 fBitsPerPixel := 24;
2938 fFormat := tfRGB8ub3;
2939 fWithAlpha := tfRGBA8ub4;
2940 fWithoutAlpha := tfRGB8ub3;
2941 fRGBInverted := tfBGR8ub3;
2942 fPrecision := glBitmapRec4ub(8, 8, 8, 0);
2943 fShift := glBitmapRec4ub(0, 8, 16, 0);
2944 fOpenGLFormat := tfRGB8ub3;
2945 fglFormat := GL_RGB;
2946 fglInternalFormat := {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}GL_RGB8{$ELSE}GL_RGB{$IFEND};
2947 fglDataFormat := GL_UNSIGNED_BYTE;
2950 procedure TfdRGBX8ui1.SetValues;
2952 inherited SetValues;
2953 fBitsPerPixel := 32;
2954 fFormat := tfRGBX8ui1;
2955 fWithAlpha := tfRGBA8ui1;
2956 fWithoutAlpha := tfRGBX8ui1;
2957 fRGBInverted := tfBGRX8ui1;
2958 fPrecision := glBitmapRec4ub( 8, 8, 8, 0);
2959 fShift := glBitmapRec4ub(24, 16, 8, 0);
2961 fOpenGLFormat := tfRGBX8ui1;
2962 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
2963 fglInternalFormat := GL_RGB8;
2964 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8;
2966 fOpenGLFormat := tfRGB8ub3;
2970 procedure TfdXRGB8ui1.SetValues;
2972 inherited SetValues;
2973 fBitsPerPixel := 32;
2974 fFormat := tfXRGB8ui1;
2975 fWithAlpha := tfXRGB8ui1;
2976 fWithoutAlpha := tfXRGB8ui1;
2977 fOpenGLFormat := tfXRGB8ui1;
2978 fRGBInverted := tfXBGR8ui1;
2979 fPrecision := glBitmapRec4ub( 8, 8, 8, 0);
2980 fShift := glBitmapRec4ub(16, 8, 0, 0);
2982 fOpenGLFormat := tfXRGB8ui1;
2983 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
2984 fglInternalFormat := GL_RGB8;
2985 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8_REV;
2987 fOpenGLFormat := tfRGB8ub3;
2991 procedure TfdRGB10X2ui1.SetValues;
2993 inherited SetValues;
2994 fBitsPerPixel := 32;
2995 fFormat := tfRGB10X2ui1;
2996 fWithAlpha := tfRGB10A2ui1;
2997 fWithoutAlpha := tfRGB10X2ui1;
2998 fRGBInverted := tfBGR10X2ui1;
2999 fPrecision := glBitmapRec4ub(10, 10, 10, 0);
3000 fShift := glBitmapRec4ub(22, 12, 2, 0);
3002 fOpenGLFormat := tfRGB10X2ui1;
3003 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3004 fglInternalFormat := GL_RGB10;
3005 fglDataFormat := GL_UNSIGNED_INT_10_10_10_2;
3007 fOpenGLFormat := tfRGB16us3;
3011 procedure TfdX2RGB10ui1.SetValues;
3013 inherited SetValues;
3014 fBitsPerPixel := 32;
3015 fFormat := tfX2RGB10ui1;
3016 fWithAlpha := tfA2RGB10ui1;
3017 fWithoutAlpha := tfX2RGB10ui1;
3018 fRGBInverted := tfX2BGR10ui1;
3019 fPrecision := glBitmapRec4ub(10, 10, 10, 0);
3020 fShift := glBitmapRec4ub(20, 10, 0, 0);
3022 fOpenGLFormat := tfX2RGB10ui1;
3023 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3024 fglInternalFormat := GL_RGB10;
3025 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3027 fOpenGLFormat := tfRGB16us3;
3031 procedure TfdRGB16us3.SetValues;
3033 inherited SetValues;
3034 fBitsPerPixel := 48;
3035 fFormat := tfRGB16us3;
3036 fWithAlpha := tfRGBA16us4;
3037 fWithoutAlpha := tfRGB16us3;
3038 fRGBInverted := tfBGR16us3;
3039 fPrecision := glBitmapRec4ub(16, 16, 16, 0);
3040 fShift := glBitmapRec4ub( 0, 16, 32, 0);
3041 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
3042 fOpenGLFormat := tfRGB16us3;
3043 fglFormat := GL_RGB;
3044 fglInternalFormat := {$IFNDEF OPENGL_ES}GL_RGB16{$ELSE}GL_RGB16UI{$ENDIF};
3045 fglDataFormat := GL_UNSIGNED_SHORT;
3047 fOpenGLFormat := tfRGB8ub3;
3051 procedure TfdRGBA4us1.SetValues;
3053 inherited SetValues;
3054 fBitsPerPixel := 16;
3055 fFormat := tfRGBA4us1;
3056 fWithAlpha := tfRGBA4us1;
3057 fWithoutAlpha := tfRGBX4us1;
3058 fOpenGLFormat := tfRGBA4us1;
3059 fRGBInverted := tfBGRA4us1;
3060 fPrecision := glBitmapRec4ub( 4, 4, 4, 4);
3061 fShift := glBitmapRec4ub(12, 8, 4, 0);
3062 fglFormat := GL_RGBA;
3063 fglInternalFormat := {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}GL_RGBA8{$ELSE}GL_RGBA{$IFEND};
3064 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4;
3067 procedure TfdARGB4us1.SetValues;
3069 inherited SetValues;
3070 fBitsPerPixel := 16;
3071 fFormat := tfARGB4us1;
3072 fWithAlpha := tfARGB4us1;
3073 fWithoutAlpha := tfXRGB4us1;
3074 fRGBInverted := tfABGR4us1;
3075 fPrecision := glBitmapRec4ub( 4, 4, 4, 4);
3076 fShift := glBitmapRec4ub( 8, 4, 0, 12);
3078 fOpenGLFormat := tfARGB4us1;
3079 fglFormat := GL_BGRA;
3080 fglInternalFormat := GL_RGBA4;
3081 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3083 fOpenGLFormat := tfRGBA4us1;
3087 procedure TfdRGB5A1us1.SetValues;
3089 inherited SetValues;
3090 fBitsPerPixel := 16;
3091 fFormat := tfRGB5A1us1;
3092 fWithAlpha := tfRGB5A1us1;
3093 fWithoutAlpha := tfRGB5X1us1;
3094 fOpenGLFormat := tfRGB5A1us1;
3095 fRGBInverted := tfBGR5A1us1;
3096 fPrecision := glBitmapRec4ub( 5, 5, 5, 1);
3097 fShift := glBitmapRec4ub(11, 6, 1, 0);
3098 fglFormat := GL_RGBA;
3099 fglInternalFormat := {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}GL_RGB5_A1{$ELSE}GL_RGBA{$IFEND};
3100 fglDataFormat := GL_UNSIGNED_SHORT_5_5_5_1;
3103 procedure TfdA1RGB5us1.SetValues;
3105 inherited SetValues;
3106 fBitsPerPixel := 16;
3107 fFormat := tfA1RGB5us1;
3108 fWithAlpha := tfA1RGB5us1;
3109 fWithoutAlpha := tfX1RGB5us1;
3110 fRGBInverted := tfA1BGR5us1;
3111 fPrecision := glBitmapRec4ub( 5, 5, 5, 1);
3112 fShift := glBitmapRec4ub(10, 5, 0, 15);
3114 fOpenGLFormat := tfA1RGB5us1;
3115 fglFormat := GL_BGRA;
3116 fglInternalFormat := GL_RGB5_A1;
3117 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3119 fOpenGLFormat := tfRGB5A1us1;
3123 procedure TfdRGBA8ui1.SetValues;
3125 inherited SetValues;
3126 fBitsPerPixel := 32;
3127 fFormat := tfRGBA8ui1;
3128 fWithAlpha := tfRGBA8ui1;
3129 fWithoutAlpha := tfRGBX8ui1;
3130 fRGBInverted := tfBGRA8ui1;
3131 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3132 fShift := glBitmapRec4ub(24, 16, 8, 0);
3134 fOpenGLFormat := tfRGBA8ui1;
3135 fglFormat := GL_RGBA;
3136 fglInternalFormat := GL_RGBA8;
3137 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8;
3139 fOpenGLFormat := tfRGBA8ub4;
3143 procedure TfdARGB8ui1.SetValues;
3145 inherited SetValues;
3146 fBitsPerPixel := 32;
3147 fFormat := tfARGB8ui1;
3148 fWithAlpha := tfARGB8ui1;
3149 fWithoutAlpha := tfXRGB8ui1;
3150 fRGBInverted := tfABGR8ui1;
3151 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3152 fShift := glBitmapRec4ub(16, 8, 0, 24);
3154 fOpenGLFormat := tfARGB8ui1;
3155 fglFormat := GL_BGRA;
3156 fglInternalFormat := GL_RGBA8;
3157 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8_REV;
3159 fOpenGLFormat := tfRGBA8ub4;
3163 procedure TfdRGBA8ub4.SetValues;
3165 inherited SetValues;
3166 fBitsPerPixel := 32;
3167 fFormat := tfRGBA8ub4;
3168 fWithAlpha := tfRGBA8ub4;
3169 fWithoutAlpha := tfRGB8ub3;
3170 fOpenGLFormat := tfRGBA8ub4;
3171 fRGBInverted := tfBGRA8ub4;
3172 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3173 fShift := glBitmapRec4ub( 0, 8, 16, 24);
3174 fglFormat := GL_RGBA;
3175 fglInternalFormat := {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}GL_RGBA8{$ELSE}GL_RGBA{$IFEND};
3176 fglDataFormat := GL_UNSIGNED_BYTE;
3179 procedure TfdRGB10A2ui1.SetValues;
3181 inherited SetValues;
3182 fBitsPerPixel := 32;
3183 fFormat := tfRGB10A2ui1;
3184 fWithAlpha := tfRGB10A2ui1;
3185 fWithoutAlpha := tfRGB10X2ui1;
3186 fRGBInverted := tfBGR10A2ui1;
3187 fPrecision := glBitmapRec4ub(10, 10, 10, 2);
3188 fShift := glBitmapRec4ub(22, 12, 2, 0);
3190 fOpenGLFormat := tfRGB10A2ui1;
3191 fglFormat := GL_RGBA;
3192 fglInternalFormat := GL_RGB10_A2;
3193 fglDataFormat := GL_UNSIGNED_INT_10_10_10_2;
3195 fOpenGLFormat := tfA2RGB10ui1;
3199 procedure TfdA2RGB10ui1.SetValues;
3201 inherited SetValues;
3202 fBitsPerPixel := 32;
3203 fFormat := tfA2RGB10ui1;
3204 fWithAlpha := tfA2RGB10ui1;
3205 fWithoutAlpha := tfX2RGB10ui1;
3206 fRGBInverted := tfA2BGR10ui1;
3207 fPrecision := glBitmapRec4ub(10, 10, 10, 2);
3208 fShift := glBitmapRec4ub(20, 10, 0, 30);
3209 {$IF NOT DEFINED(OPENGL_ES)}
3210 fOpenGLFormat := tfA2RGB10ui1;
3211 fglFormat := GL_BGRA;
3212 fglInternalFormat := GL_RGB10_A2;
3213 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3214 {$ELSEIF DEFINED(OPENGL_ES_3_0)}
3215 fOpenGLFormat := tfA2RGB10ui1;
3216 fglFormat := GL_RGBA;
3217 fglInternalFormat := GL_RGB10_A2;
3218 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3220 fOpenGLFormat := tfRGBA8ui1;
3224 procedure TfdRGBA16us4.SetValues;
3226 inherited SetValues;
3227 fBitsPerPixel := 64;
3228 fFormat := tfRGBA16us4;
3229 fWithAlpha := tfRGBA16us4;
3230 fWithoutAlpha := tfRGB16us3;
3231 fRGBInverted := tfBGRA16us4;
3232 fPrecision := glBitmapRec4ub(16, 16, 16, 16);
3233 fShift := glBitmapRec4ub( 0, 16, 32, 48);
3234 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
3235 fOpenGLFormat := tfRGBA16us4;
3236 fglFormat := GL_RGBA;
3237 fglInternalFormat := {$IFNDEF OPENGL_ES}GL_RGBA16{$ELSE}GL_RGBA16UI{$ENDIF};
3238 fglDataFormat := GL_UNSIGNED_SHORT;
3240 fOpenGLFormat := tfRGBA8ub4;
3244 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3245 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3246 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3247 procedure TfdBGRX4us1.SetValues;
3249 inherited SetValues;
3250 fBitsPerPixel := 16;
3251 fFormat := tfBGRX4us1;
3252 fWithAlpha := tfBGRA4us1;
3253 fWithoutAlpha := tfBGRX4us1;
3254 fRGBInverted := tfRGBX4us1;
3255 fPrecision := glBitmapRec4ub( 4, 4, 4, 0);
3256 fShift := glBitmapRec4ub( 4, 8, 12, 0);
3258 fOpenGLFormat := tfBGRX4us1;
3259 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3260 fglInternalFormat := GL_RGB4;
3261 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4;
3263 fOpenGLFormat := tfR5G6B5us1;
3267 procedure TfdXBGR4us1.SetValues;
3269 inherited SetValues;
3270 fBitsPerPixel := 16;
3271 fFormat := tfXBGR4us1;
3272 fWithAlpha := tfABGR4us1;
3273 fWithoutAlpha := tfXBGR4us1;
3274 fRGBInverted := tfXRGB4us1;
3275 fPrecision := glBitmapRec4ub( 4, 4, 4, 0);
3276 fShift := glBitmapRec4ub( 0, 4, 8, 0);
3278 fOpenGLFormat := tfXBGR4us1;
3279 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3280 fglInternalFormat := GL_RGB4;
3281 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3283 fOpenGLFormat := tfR5G6B5us1;
3287 procedure TfdB5G6R5us1.SetValues;
3289 inherited SetValues;
3290 fBitsPerPixel := 16;
3291 fFormat := tfB5G6R5us1;
3292 fWithAlpha := tfBGR5A1us1;
3293 fWithoutAlpha := tfB5G6R5us1;
3294 fRGBInverted := tfR5G6B5us1;
3295 fPrecision := glBitmapRec4ub( 5, 6, 5, 0);
3296 fShift := glBitmapRec4ub( 0, 5, 11, 0);
3298 fOpenGLFormat := tfB5G6R5us1;
3299 fglFormat := GL_RGB;
3300 fglInternalFormat := GL_RGB565;
3301 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3303 fOpenGLFormat := tfR5G6B5us1;
3307 procedure TfdBGR5X1us1.SetValues;
3309 inherited SetValues;
3310 fBitsPerPixel := 16;
3311 fFormat := tfBGR5X1us1;
3312 fWithAlpha := tfBGR5A1us1;
3313 fWithoutAlpha := tfBGR5X1us1;
3314 fRGBInverted := tfRGB5X1us1;
3315 fPrecision := glBitmapRec4ub( 5, 5, 5, 0);
3316 fShift := glBitmapRec4ub( 1, 6, 11, 0);
3318 fOpenGLFormat := tfBGR5X1us1;
3319 fglFormat := GL_BGRA;
3320 fglInternalFormat := GL_RGB5;
3321 fglDataFormat := GL_UNSIGNED_SHORT_5_5_5_1;
3323 fOpenGLFormat := tfR5G6B5us1;
3327 procedure TfdX1BGR5us1.SetValues;
3329 inherited SetValues;
3330 fBitsPerPixel := 16;
3331 fFormat := tfX1BGR5us1;
3332 fWithAlpha := tfA1BGR5us1;
3333 fWithoutAlpha := tfX1BGR5us1;
3334 fRGBInverted := tfX1RGB5us1;
3335 fPrecision := glBitmapRec4ub( 5, 5, 5, 0);
3336 fShift := glBitmapRec4ub( 0, 5, 10, 0);
3338 fOpenGLFormat := tfX1BGR5us1;
3339 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3340 fglInternalFormat := GL_RGB5;
3341 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3343 fOpenGLFormat := tfR5G6B5us1;
3347 procedure TfdBGR8ub3.SetValues;
3349 inherited SetValues;
3350 fBitsPerPixel := 24;
3351 fFormat := tfBGR8ub3;
3352 fWithAlpha := tfBGRA8ub4;
3353 fWithoutAlpha := tfBGR8ub3;
3354 fRGBInverted := tfRGB8ub3;
3355 fPrecision := glBitmapRec4ub( 8, 8, 8, 0);
3356 fShift := glBitmapRec4ub(16, 8, 0, 0);
3358 fOpenGLFormat := tfBGR8ub3;
3359 fglFormat := GL_BGR;
3360 fglInternalFormat := GL_RGB8;
3361 fglDataFormat := GL_UNSIGNED_BYTE;
3363 fOpenGLFormat := tfRGB8ub3;
3367 procedure TfdBGRX8ui1.SetValues;
3369 inherited SetValues;
3370 fBitsPerPixel := 32;
3371 fFormat := tfBGRX8ui1;
3372 fWithAlpha := tfBGRA8ui1;
3373 fWithoutAlpha := tfBGRX8ui1;
3374 fRGBInverted := tfRGBX8ui1;
3375 fPrecision := glBitmapRec4ub( 8, 8, 8, 0);
3376 fShift := glBitmapRec4ub( 8, 16, 24, 0);
3378 fOpenGLFormat := tfBGRX8ui1;
3379 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3380 fglInternalFormat := GL_RGB8;
3381 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8;
3383 fOpenGLFormat := tfRGB8ub3;
3387 procedure TfdXBGR8ui1.SetValues;
3389 inherited SetValues;
3390 fBitsPerPixel := 32;
3391 fFormat := tfXBGR8ui1;
3392 fWithAlpha := tfABGR8ui1;
3393 fWithoutAlpha := tfXBGR8ui1;
3394 fRGBInverted := tfXRGB8ui1;
3395 fPrecision := glBitmapRec4ub( 8, 8, 8, 0);
3396 fShift := glBitmapRec4ub( 0, 8, 16, 0);
3398 fOpenGLFormat := tfXBGR8ui1;
3399 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3400 fglInternalFormat := GL_RGB8;
3401 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8_REV;
3403 fOpenGLFormat := tfRGB8ub3;
3407 procedure TfdBGR10X2ui1.SetValues;
3409 inherited SetValues;
3410 fBitsPerPixel := 32;
3411 fFormat := tfBGR10X2ui1;
3412 fWithAlpha := tfBGR10A2ui1;
3413 fWithoutAlpha := tfBGR10X2ui1;
3414 fRGBInverted := tfRGB10X2ui1;
3415 fPrecision := glBitmapRec4ub(10, 10, 10, 0);
3416 fShift := glBitmapRec4ub( 2, 12, 22, 0);
3418 fOpenGLFormat := tfBGR10X2ui1;
3419 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3420 fglInternalFormat := GL_RGB10;
3421 fglDataFormat := GL_UNSIGNED_INT_10_10_10_2;
3423 fOpenGLFormat := tfRGB16us3;
3427 procedure TfdX2BGR10ui1.SetValues;
3429 inherited SetValues;
3430 fBitsPerPixel := 32;
3431 fFormat := tfX2BGR10ui1;
3432 fWithAlpha := tfA2BGR10ui1;
3433 fWithoutAlpha := tfX2BGR10ui1;
3434 fRGBInverted := tfX2RGB10ui1;
3435 fPrecision := glBitmapRec4ub(10, 10, 10, 0);
3436 fShift := glBitmapRec4ub( 0, 10, 20, 0);
3438 fOpenGLFormat := tfX2BGR10ui1;
3439 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3440 fglInternalFormat := GL_RGB10;
3441 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3443 fOpenGLFormat := tfRGB16us3;
3447 procedure TfdBGR16us3.SetValues;
3449 inherited SetValues;
3450 fBitsPerPixel := 48;
3451 fFormat := tfBGR16us3;
3452 fWithAlpha := tfBGRA16us4;
3453 fWithoutAlpha := tfBGR16us3;
3454 fRGBInverted := tfRGB16us3;
3455 fPrecision := glBitmapRec4ub(16, 16, 16, 0);
3456 fShift := glBitmapRec4ub(32, 16, 0, 0);
3458 fOpenGLFormat := tfBGR16us3;
3459 fglFormat := GL_BGR;
3460 fglInternalFormat := GL_RGB16;
3461 fglDataFormat := GL_UNSIGNED_SHORT;
3463 fOpenGLFormat := tfRGB16us3;
3467 procedure TfdBGRA4us1.SetValues;
3469 inherited SetValues;
3470 fBitsPerPixel := 16;
3471 fFormat := tfBGRA4us1;
3472 fWithAlpha := tfBGRA4us1;
3473 fWithoutAlpha := tfBGRX4us1;
3474 fRGBInverted := tfRGBA4us1;
3475 fPrecision := glBitmapRec4ub( 4, 4, 4, 4);
3476 fShift := glBitmapRec4ub( 4, 8, 12, 0);
3478 fOpenGLFormat := tfBGRA4us1;
3479 fglFormat := GL_BGRA;
3480 fglInternalFormat := GL_RGBA4;
3481 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4;
3483 fOpenGLFormat := tfRGBA4us1;
3487 procedure TfdABGR4us1.SetValues;
3489 inherited SetValues;
3490 fBitsPerPixel := 16;
3491 fFormat := tfABGR4us1;
3492 fWithAlpha := tfABGR4us1;
3493 fWithoutAlpha := tfXBGR4us1;
3494 fRGBInverted := tfARGB4us1;
3495 fPrecision := glBitmapRec4ub( 4, 4, 4, 4);
3496 fShift := glBitmapRec4ub( 0, 4, 8, 12);
3498 fOpenGLFormat := tfABGR4us1;
3499 fglFormat := GL_RGBA;
3500 fglInternalFormat := GL_RGBA4;
3501 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3503 fOpenGLFormat := tfRGBA4us1;
3507 procedure TfdBGR5A1us1.SetValues;
3509 inherited SetValues;
3510 fBitsPerPixel := 16;
3511 fFormat := tfBGR5A1us1;
3512 fWithAlpha := tfBGR5A1us1;
3513 fWithoutAlpha := tfBGR5X1us1;
3514 fRGBInverted := tfRGB5A1us1;
3515 fPrecision := glBitmapRec4ub( 5, 5, 5, 1);
3516 fShift := glBitmapRec4ub( 1, 6, 11, 0);
3518 fOpenGLFormat := tfBGR5A1us1;
3519 fglFormat := GL_BGRA;
3520 fglInternalFormat := GL_RGB5_A1;
3521 fglDataFormat := GL_UNSIGNED_SHORT_5_5_5_1;
3523 fOpenGLFormat := tfRGB5A1us1;
3527 procedure TfdA1BGR5us1.SetValues;
3529 inherited SetValues;
3530 fBitsPerPixel := 16;
3531 fFormat := tfA1BGR5us1;
3532 fWithAlpha := tfA1BGR5us1;
3533 fWithoutAlpha := tfX1BGR5us1;
3534 fRGBInverted := tfA1RGB5us1;
3535 fPrecision := glBitmapRec4ub( 5, 5, 5, 1);
3536 fShift := glBitmapRec4ub( 0, 5, 10, 15);
3538 fOpenGLFormat := tfA1BGR5us1;
3539 fglFormat := GL_RGBA;
3540 fglInternalFormat := GL_RGB5_A1;
3541 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3543 fOpenGLFormat := tfRGB5A1us1;
3547 procedure TfdBGRA8ui1.SetValues;
3549 inherited SetValues;
3550 fBitsPerPixel := 32;
3551 fFormat := tfBGRA8ui1;
3552 fWithAlpha := tfBGRA8ui1;
3553 fWithoutAlpha := tfBGRX8ui1;
3554 fRGBInverted := tfRGBA8ui1;
3555 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3556 fShift := glBitmapRec4ub( 8, 16, 24, 0);
3558 fOpenGLFormat := tfBGRA8ui1;
3559 fglFormat := GL_BGRA;
3560 fglInternalFormat := GL_RGBA8;
3561 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8;
3563 fOpenGLFormat := tfRGBA8ub4;
3567 procedure TfdABGR8ui1.SetValues;
3569 inherited SetValues;
3570 fBitsPerPixel := 32;
3571 fFormat := tfABGR8ui1;
3572 fWithAlpha := tfABGR8ui1;
3573 fWithoutAlpha := tfXBGR8ui1;
3574 fRGBInverted := tfARGB8ui1;
3575 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3576 fShift := glBitmapRec4ub( 0, 8, 16, 24);
3578 fOpenGLFormat := tfABGR8ui1;
3579 fglFormat := GL_RGBA;
3580 fglInternalFormat := GL_RGBA8;
3581 fglDataFormat := GL_UNSIGNED_INT_8_8_8_8_REV;
3583 fOpenGLFormat := tfRGBA8ub4
3587 procedure TfdBGRA8ub4.SetValues;
3589 inherited SetValues;
3590 fBitsPerPixel := 32;
3591 fFormat := tfBGRA8ub4;
3592 fWithAlpha := tfBGRA8ub4;
3593 fWithoutAlpha := tfBGR8ub3;
3594 fRGBInverted := tfRGBA8ub4;
3595 fPrecision := glBitmapRec4ub( 8, 8, 8, 8);
3596 fShift := glBitmapRec4ub(16, 8, 0, 24);
3598 fOpenGLFormat := tfBGRA8ub4;
3599 fglFormat := GL_BGRA;
3600 fglInternalFormat := GL_RGBA8;
3601 fglDataFormat := GL_UNSIGNED_BYTE;
3603 fOpenGLFormat := tfRGBA8ub4;
3607 procedure TfdBGR10A2ui1.SetValues;
3609 inherited SetValues;
3610 fBitsPerPixel := 32;
3611 fFormat := tfBGR10A2ui1;
3612 fWithAlpha := tfBGR10A2ui1;
3613 fWithoutAlpha := tfBGR10X2ui1;
3614 fRGBInverted := tfRGB10A2ui1;
3615 fPrecision := glBitmapRec4ub(10, 10, 10, 2);
3616 fShift := glBitmapRec4ub( 2, 12, 22, 0);
3618 fOpenGLFormat := tfBGR10A2ui1;
3619 fglFormat := GL_BGRA;
3620 fglInternalFormat := GL_RGB10_A2;
3621 fglDataFormat := GL_UNSIGNED_INT_10_10_10_2;
3623 fOpenGLFormat := tfA2RGB10ui1;
3627 procedure TfdA2BGR10ui1.SetValues;
3629 inherited SetValues;
3630 fBitsPerPixel := 32;
3631 fFormat := tfA2BGR10ui1;
3632 fWithAlpha := tfA2BGR10ui1;
3633 fWithoutAlpha := tfX2BGR10ui1;
3634 fRGBInverted := tfA2RGB10ui1;
3635 fPrecision := glBitmapRec4ub(10, 10, 10, 2);
3636 fShift := glBitmapRec4ub( 0, 10, 20, 30);
3638 fOpenGLFormat := tfA2BGR10ui1;
3639 fglFormat := GL_RGBA;
3640 fglInternalFormat := GL_RGB10_A2;
3641 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3643 fOpenGLFormat := tfA2RGB10ui1;
3647 procedure TfdBGRA16us4.SetValues;
3649 inherited SetValues;
3650 fBitsPerPixel := 64;
3651 fFormat := tfBGRA16us4;
3652 fWithAlpha := tfBGRA16us4;
3653 fWithoutAlpha := tfBGR16us3;
3654 fRGBInverted := tfRGBA16us4;
3655 fPrecision := glBitmapRec4ub(16, 16, 16, 16);
3656 fShift := glBitmapRec4ub(32, 16, 0, 48);
3658 fOpenGLFormat := tfBGRA16us4;
3659 fglFormat := GL_BGRA;
3660 fglInternalFormat := GL_RGBA16;
3661 fglDataFormat := GL_UNSIGNED_SHORT;
3663 fOpenGLFormat := tfRGBA16us4;
3667 procedure TfdDepth16us1.SetValues;
3669 inherited SetValues;
3670 fBitsPerPixel := 16;
3671 fFormat := tfDepth16us1;
3672 fWithoutAlpha := tfDepth16us1;
3673 fPrecision := glBitmapRec4ub(16, 16, 16, 16);
3674 fShift := glBitmapRec4ub( 0, 0, 0, 0);
3675 {$IF NOT DEFINED (OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
3676 fOpenGLFormat := tfDepth16us1;
3677 fglFormat := GL_DEPTH_COMPONENT;
3678 fglInternalFormat := GL_DEPTH_COMPONENT16;
3679 fglDataFormat := GL_UNSIGNED_SHORT;
3683 procedure TfdDepth24ui1.SetValues;
3685 inherited SetValues;
3686 fBitsPerPixel := 32;
3687 fFormat := tfDepth24ui1;
3688 fWithoutAlpha := tfDepth24ui1;
3689 fOpenGLFormat := tfDepth24ui1;
3690 fPrecision := glBitmapRec4ub(32, 32, 32, 32);
3691 fShift := glBitmapRec4ub( 0, 0, 0, 0);
3692 {$IF NOT DEFINED (OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
3693 fOpenGLFormat := tfDepth24ui1;
3694 fglFormat := GL_DEPTH_COMPONENT;
3695 fglInternalFormat := GL_DEPTH_COMPONENT24;
3696 fglDataFormat := GL_UNSIGNED_INT;
3700 procedure TfdDepth32ui1.SetValues;
3702 inherited SetValues;
3703 fBitsPerPixel := 32;
3704 fFormat := tfDepth32ui1;
3705 fWithoutAlpha := tfDepth32ui1;
3706 fPrecision := glBitmapRec4ub(32, 32, 32, 32);
3707 fShift := glBitmapRec4ub( 0, 0, 0, 0);
3708 {$IF NOT DEFINED(OPENGL_ES)}
3709 fOpenGLFormat := tfDepth32ui1;
3710 fglFormat := GL_DEPTH_COMPONENT;
3711 fglInternalFormat := GL_DEPTH_COMPONENT32;
3712 fglDataFormat := GL_UNSIGNED_INT;
3713 {$ELSEIF DEFINED(OPENGL_ES_3_0)}
3714 fOpenGLFormat := tfDepth24ui1;
3715 {$ELSEIF DEFINED(OPENGL_ES_2_0)}
3716 fOpenGLFormat := tfDepth16us1;
3720 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3721 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3722 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3723 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3725 raise EglBitmap.Create('mapping for compressed formats is not supported');
3728 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3730 raise EglBitmap.Create('mapping for compressed formats is not supported');
3733 procedure TfdS3tcDtx1RGBA.SetValues;
3735 inherited SetValues;
3736 fFormat := tfS3tcDtx1RGBA;
3737 fWithAlpha := tfS3tcDtx1RGBA;
3738 fUncompressed := tfRGB5A1us1;
3740 fIsCompressed := true;
3742 fOpenGLFormat := tfS3tcDtx1RGBA;
3743 fglFormat := GL_COMPRESSED_RGBA;
3744 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3745 fglDataFormat := GL_UNSIGNED_BYTE;
3747 fOpenGLFormat := fUncompressed;
3751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3752 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3753 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3754 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3756 raise EglBitmap.Create('mapping for compressed formats is not supported');
3759 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3761 raise EglBitmap.Create('mapping for compressed formats is not supported');
3764 procedure TfdS3tcDtx3RGBA.SetValues;
3766 inherited SetValues;
3767 fFormat := tfS3tcDtx3RGBA;
3768 fWithAlpha := tfS3tcDtx3RGBA;
3769 fUncompressed := tfRGBA8ub4;
3771 fIsCompressed := true;
3773 fOpenGLFormat := tfS3tcDtx3RGBA;
3774 fglFormat := GL_COMPRESSED_RGBA;
3775 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3776 fglDataFormat := GL_UNSIGNED_BYTE;
3778 fOpenGLFormat := fUncompressed;
3782 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3783 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3784 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3785 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3787 raise EglBitmap.Create('mapping for compressed formats is not supported');
3790 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3792 raise EglBitmap.Create('mapping for compressed formats is not supported');
3795 procedure TfdS3tcDtx5RGBA.SetValues;
3797 inherited SetValues;
3798 fFormat := tfS3tcDtx3RGBA;
3799 fWithAlpha := tfS3tcDtx3RGBA;
3800 fUncompressed := tfRGBA8ub4;
3802 fIsCompressed := true;
3804 fOpenGLFormat := tfS3tcDtx3RGBA;
3805 fglFormat := GL_COMPRESSED_RGBA;
3806 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3807 fglDataFormat := GL_UNSIGNED_BYTE;
3809 fOpenGLFormat := fUncompressed;
3813 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3814 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3816 function TglBitmapFormatDescriptor.GetHasRed: Boolean;
3818 result := (fPrecision.r > 0);
3821 function TglBitmapFormatDescriptor.GetHasGreen: Boolean;
3823 result := (fPrecision.g > 0);
3826 function TglBitmapFormatDescriptor.GetHasBlue: Boolean;
3828 result := (fPrecision.b > 0);
3831 function TglBitmapFormatDescriptor.GetHasAlpha: Boolean;
3833 result := (fPrecision.a > 0);
3836 function TglBitmapFormatDescriptor.GetHasColor: Boolean;
3838 result := HasRed or HasGreen or HasBlue;
3841 function TglBitmapFormatDescriptor.GetIsGrayscale: Boolean;
3843 result := (Mask.r = Mask.g) and (Mask.g = Mask.b) and (Mask.r > 0);
3846 function TglBitmapFormatDescriptor.GetHasOpenGLSupport: Boolean;
3848 result := (OpenGLFormat = Format);
3851 procedure TglBitmapFormatDescriptor.SetValues;
3854 fWithAlpha := tfEmpty;
3855 fWithoutAlpha := tfEmpty;
3856 fOpenGLFormat := tfEmpty;
3857 fRGBInverted := tfEmpty;
3858 fUncompressed := tfEmpty;
3861 fIsCompressed := false;
3864 fglInternalFormat := 0;
3867 FillChar(fPrecision, 0, SizeOf(fPrecision));
3868 FillChar(fShift, 0, SizeOf(fShift));
3871 procedure TglBitmapFormatDescriptor.CalcValues;
3875 fBytesPerPixel := fBitsPerPixel / 8;
3877 for i := 0 to 3 do begin
3878 if (fPrecision.arr[i] > 0) then
3880 fRange.arr[i] := (1 shl fPrecision.arr[i]) - 1;
3881 fMask.arr[i] := fRange.arr[i] shl fShift.arr[i];
3885 function TglBitmapFormatDescriptor.GetSize(const aSize: TglBitmapSize): Integer;
3889 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
3890 w := Max(1, aSize.X);
3891 h := Max(1, aSize.Y);
3892 result := GetSize(w, h);
3897 function TglBitmapFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
3900 if (aWidth <= 0) or (aHeight <= 0) then
3902 result := Ceil(aWidth * aHeight * BytesPerPixel);
3905 constructor TglBitmapFormatDescriptor.Create;
3912 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3913 class function TglBitmapFormatDescriptor.GetByFormat(const aInternalFormat: GLenum): TglBitmapFormatDescriptor;
3917 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
3918 result := TFormatDescriptor.Get(f);
3919 if (result.glInternalFormat = aInternalFormat) then
3922 result := TFormatDescriptor.Get(tfEmpty);
3925 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3926 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3927 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3928 class procedure TFormatDescriptor.Init;
3930 if not Assigned(FormatDescriptorCS) then
3931 FormatDescriptorCS := TCriticalSection.Create;
3934 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3935 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3937 FormatDescriptorCS.Enter;
3939 result := FormatDescriptors[aFormat];
3940 if not Assigned(result) then begin
3941 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3942 FormatDescriptors[aFormat] := result;
3945 FormatDescriptorCS.Leave;
3949 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3950 class function TFormatDescriptor.GetAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3952 result := Get(Get(aFormat).WithAlpha);
3955 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3956 class function TFormatDescriptor.GetFromMask(const aMask: TglBitmapRec4ul; const aBitCount: Integer): TFormatDescriptor;
3958 ft: TglBitmapFormat;
3960 // find matching format with OpenGL support
3961 for ft := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
3963 if (result.MaskMatch(aMask)) and
3964 (result.glFormat <> 0) and
3965 (result.glInternalFormat <> 0) and
3966 ((aBitCount = 0) or (aBitCount = result.BitsPerPixel))
3971 // find matching format without OpenGL Support
3972 for ft := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
3974 if result.MaskMatch(aMask) and ((aBitCount = 0) or (aBitCount = result.BitsPerPixel)) then
3978 result := TFormatDescriptor.Get(tfEmpty);
3981 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3982 class function TFormatDescriptor.GetFromPrecShift(const aPrec, aShift: TglBitmapRec4ub; const aBitCount: Integer): TFormatDescriptor;
3984 ft: TglBitmapFormat;
3986 // find matching format with OpenGL support
3987 for ft := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
3989 if glBitmapRec4ubCompare(result.Shift, aShift) and
3990 glBitmapRec4ubCompare(result.Precision, aPrec) and
3991 (result.glFormat <> 0) and
3992 (result.glInternalFormat <> 0) and
3993 ((aBitCount = 0) or (aBitCount = result.BitsPerPixel))
3998 // find matching format without OpenGL Support
3999 for ft := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
4001 if glBitmapRec4ubCompare(result.Shift, aShift) and
4002 glBitmapRec4ubCompare(result.Precision, aPrec) and
4003 ((aBitCount = 0) or (aBitCount = result.BitsPerPixel)) then
4007 result := TFormatDescriptor.Get(tfEmpty);
4010 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4011 class procedure TFormatDescriptor.Clear;
4015 FormatDescriptorCS.Enter;
4017 for f := low(FormatDescriptors) to high(FormatDescriptors) do
4018 FreeAndNil(FormatDescriptors[f]);
4020 FormatDescriptorCS.Leave;
4024 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4025 class procedure TFormatDescriptor.Finalize;
4028 FreeAndNil(FormatDescriptorCS);
4031 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4032 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4033 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4034 procedure TbmpBitfieldFormat.SetCustomValues(const aBPP: Integer; aMask: TglBitmapRec4ul);
4038 for i := 0 to 3 do begin
4040 while (aMask.arr[i] > 0) and ((aMask.arr[i] and 1) = 0) do begin
4041 aMask.arr[i] := aMask.arr[i] shr 1;
4044 fPrecision.arr[i] := CountSetBits(aMask.arr[i]);
4046 fBitsPerPixel := aBPP;
4050 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4051 procedure TbmpBitfieldFormat.SetCustomValues(const aBBP: Integer; const aPrec, aShift: TglBitmapRec4ub);
4053 fBitsPerPixel := aBBP;
4054 fPrecision := aPrec;
4059 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4060 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
4065 ((aPixel.Data.r and Range.r) shl Shift.r) or
4066 ((aPixel.Data.g and Range.g) shl Shift.g) or
4067 ((aPixel.Data.b and Range.b) shl Shift.b) or
4068 ((aPixel.Data.a and Range.a) shl Shift.a);
4069 case BitsPerPixel of
4071 16: PWord(aData)^ := data;
4072 32: PCardinal(aData)^ := data;
4073 64: PQWord(aData)^ := data;
4075 raise EglBitmap.CreateFmt('invalid pixel size: %d', [BitsPerPixel]);
4077 inc(aData, Round(BytesPerPixel));
4080 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4081 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
4086 case BitsPerPixel of
4088 16: data := PWord(aData)^;
4089 32: data := PCardinal(aData)^;
4090 64: data := PQWord(aData)^;
4092 raise EglBitmap.CreateFmt('invalid pixel size: %d', [BitsPerPixel]);
4095 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and Range.arr[i];
4096 inc(aData, Round(BytesPerPixel));
4099 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4100 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4101 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4102 procedure TbmpColorTableFormat.SetValues;
4104 inherited SetValues;
4105 fShift := glBitmapRec4ub(8, 8, 8, 0);
4108 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4109 procedure TbmpColorTableFormat.SetCustomValues(const aFormat: TglBitmapFormat; const aBPP: Integer; const aPrec, aShift: TglBitmapRec4ub);
4112 fBitsPerPixel := aBPP;
4113 fPrecision := aPrec;
4118 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4119 procedure TbmpColorTableFormat.CalcValues;
4121 inherited CalcValues;
4124 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4125 procedure TbmpColorTableFormat.CreateColorTable;
4129 SetLength(fColorTable, 256);
4130 if not HasColor then begin
4132 for i := 0 to High(fColorTable) do begin
4133 fColorTable[i].r := Round(((i shr Shift.a) and Range.a) / Range.a * 255);
4134 fColorTable[i].g := Round(((i shr Shift.a) and Range.a) / Range.a * 255);
4135 fColorTable[i].b := Round(((i shr Shift.a) and Range.a) / Range.a * 255);
4136 fColorTable[i].a := 0;
4140 for i := 0 to High(fColorTable) do begin
4141 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
4142 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
4143 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
4144 fColorTable[i].a := 0;
4149 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4150 function TbmpColorTableFormat.CreateMappingData: Pointer;
4152 result := Pointer(0);
4155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4156 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
4158 if (BitsPerPixel <> 8) then
4159 raise EglBitmapUnsupportedFormat.Create('color table are only supported for 8bit formats');
4160 if not HasColor then
4162 aData^ := aPixel.Data.a
4166 ((aPixel.Data.r shr Shift.r) and Range.r) * LUMINANCE_WEIGHT_R +
4167 ((aPixel.Data.g shr Shift.g) and Range.g) * LUMINANCE_WEIGHT_G +
4168 ((aPixel.Data.b shr Shift.b) and Range.b) * LUMINANCE_WEIGHT_B);
4172 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4173 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
4175 function ReadValue: Byte;
4179 if (BitsPerPixel = 8) then begin
4183 i := {%H-}PtrUInt(aMapData);
4184 if (BitsPerPixel > 1) then
4185 result := (aData^ shr i) and ((1 shl BitsPerPixel) - 1)
4187 result := (aData^ shr (7-i)) and ((1 shl BitsPerPixel) - 1);
4188 inc(i, BitsPerPixel);
4189 while (i >= 8) do begin
4193 aMapData := {%H-}Pointer(i);
4198 if (BitsPerPixel > 8) then
4199 raise EglBitmapUnsupportedFormat.Create('color table are only supported for 8bit formats');
4200 with fColorTable[ReadValue] do begin
4208 destructor TbmpColorTableFormat.Destroy;
4210 SetLength(fColorTable, 0);
4214 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4215 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4217 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
4221 for i := 0 to 3 do begin
4222 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
4223 if (aSourceFD.Range.arr[i] > 0) then
4224 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
4226 aPixel.Data.arr[i] := 0;
4231 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4232 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
4234 with aFuncRec do begin
4235 if (Source.Range.r > 0) then
4236 Dest.Data.r := Source.Data.r;
4237 if (Source.Range.g > 0) then
4238 Dest.Data.g := Source.Data.g;
4239 if (Source.Range.b > 0) then
4240 Dest.Data.b := Source.Data.b;
4241 if (Source.Range.a > 0) then
4242 Dest.Data.a := Source.Data.a;
4246 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4247 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4251 with aFuncRec do begin
4253 if (Source.Range.arr[i] > 0) then
4254 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4259 TShiftData = packed record
4261 0: (r, g, b, a: SmallInt);
4262 1: (arr: array[0..3] of SmallInt);
4264 PShiftData = ^TShiftData;
4266 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4267 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4273 if (Source.Range.arr[i] > 0) then
4274 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4277 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4278 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4282 with aFuncRec do begin
4283 Dest.Data := Source.Data;
4285 if ({%H-}PtrUInt(Args) and (1 shl i) > 0) then
4286 Dest.Data.arr[i] := Dest.Data.arr[i] xor Dest.Range.arr[i];
4290 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4291 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4295 with aFuncRec do begin
4297 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4301 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4302 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4306 with FuncRec do begin
4307 if (FuncRec.Args = nil) then begin //source has no alpha
4309 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4310 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4311 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4312 Dest.Data.a := Round(Dest.Range.a * Temp);
4314 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4318 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4319 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4321 PglBitmapPixelData = ^TglBitmapPixelData;
4323 with FuncRec do begin
4324 Dest.Data.r := Source.Data.r;
4325 Dest.Data.g := Source.Data.g;
4326 Dest.Data.b := Source.Data.b;
4328 with PglBitmapPixelData(Args)^ do
4329 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4330 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4331 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4334 Dest.Data.a := Dest.Range.a;
4338 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4339 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4341 with FuncRec do begin
4342 Dest.Data.r := Source.Data.r;
4343 Dest.Data.g := Source.Data.g;
4344 Dest.Data.b := Source.Data.b;
4345 Dest.Data.a := PCardinal(Args)^;
4349 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4350 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4353 TRGBPix = array [0..2] of byte;
4357 while aWidth > 0 do begin
4358 Temp := PRGBPix(aData)^[0];
4359 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4360 PRGBPix(aData)^[2] := Temp;
4370 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4371 //TglBitmapData///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4372 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4373 function TglBitmapData.GetFormatDescriptor: TglBitmapFormatDescriptor;
4375 result := TFormatDescriptor.Get(fFormat);
4378 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4379 function TglBitmapData.GetWidth: Integer;
4381 if (ffX in fDimension.Fields) then
4382 result := fDimension.X
4387 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4388 function TglBitmapData.GetHeight: Integer;
4390 if (ffY in fDimension.Fields) then
4391 result := fDimension.Y
4396 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4397 function TglBitmapData.GetScanlines(const aIndex: Integer): PByte;
4399 if fHasScanlines and (aIndex >= Low(fScanlines)) and (aIndex <= High(fScanlines)) then
4400 result := fScanlines[aIndex]
4405 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4406 procedure TglBitmapData.SetFormat(const aValue: TglBitmapFormat);
4408 if fFormat = aValue then
4410 if TFormatDescriptor.Get(Format).BitsPerPixel <> TFormatDescriptor.Get(aValue).BitsPerPixel then
4411 raise EglBitmapUnsupportedFormat.Create(Format);
4412 SetData(fData, aValue, Width, Height);
4415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4416 procedure TglBitmapData.PrepareResType(var aResource: String; var aResType: PChar);
4420 if not Assigned(aResType) then begin
4421 TempPos := Pos('.', aResource);
4422 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4423 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4428 procedure TglBitmapData.UpdateScanlines;
4430 w, h, i, LineWidth: Integer;
4434 fHasScanlines := Assigned(fData) and (w > 0) and (h > 0);
4435 if fHasScanlines then begin
4436 SetLength(fScanlines, h);
4437 LineWidth := Trunc(w * FormatDescriptor.BytesPerPixel);
4438 for i := 0 to h-1 do begin
4439 fScanlines[i] := fData;
4440 Inc(fScanlines[i], i * LineWidth);
4443 SetLength(fScanlines, 0);
4446 {$IFDEF GLB_SUPPORT_PNG_READ}
4447 {$IF DEFINED(GLB_LAZ_PNG)}
4448 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4449 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4450 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4451 function TglBitmapData.LoadPNG(const aStream: TStream): Boolean;
4454 PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A;
4456 reader: TLazReaderPNG;
4457 intf: TLazIntfImage;
4459 magic: String[MAGIC_LEN];
4462 StreamPos := aStream.Position;
4464 SetLength(magic, MAGIC_LEN);
4465 aStream.Read(magic[1], MAGIC_LEN);
4466 aStream.Position := StreamPos;
4467 if (magic <> PNG_MAGIC) then begin
4472 intf := TLazIntfImage.Create(0, 0);
4473 reader := TLazReaderPNG.Create;
4475 reader.UpdateDescription := true;
4476 reader.ImageRead(aStream, intf);
4477 AssignFromLazIntfImage(intf);
4480 aStream.Position := StreamPos;
4489 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
4490 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4491 function TglBitmapData.LoadPNG(const aStream: TStream): Boolean;
4493 Surface: PSDL_Surface;
4497 RWops := glBitmapCreateRWops(aStream);
4499 if IMG_isPNG(RWops) > 0 then begin
4500 Surface := IMG_LoadPNG_RW(RWops);
4502 AssignFromSurface(Surface);
4505 SDL_FreeSurface(Surface);
4513 {$ELSEIF DEFINED(GLB_LIB_PNG)}
4514 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4515 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
4517 TStream(png_get_io_ptr(png)).Read(buffer^, size);
4520 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4521 function TglBitmapData.LoadPNG(const aStream: TStream): Boolean;
4524 signature: array [0..7] of byte;
4526 png_info: png_infop;
4528 TempHeight, TempWidth: Integer;
4529 Format: TglBitmapFormat;
4532 png_rows: array of pByte;
4533 Row, LineSize: Integer;
4537 if not init_libPNG then
4538 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
4542 StreamPos := aStream.Position;
4543 aStream.Read(signature{%H-}, 8);
4544 aStream.Position := StreamPos;
4546 if png_check_sig(@signature, 8) <> 0 then begin
4548 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
4550 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
4553 png_info := png_create_info_struct(png);
4554 if png_info = nil then begin
4555 png_destroy_read_struct(@png, nil, nil);
4556 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
4559 // set read callback
4560 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
4562 // read informations
4563 png_read_info(png, png_info);
4566 TempHeight := png_get_image_height(png, png_info);
4567 TempWidth := png_get_image_width(png, png_info);
4570 case png_get_color_type(png, png_info) of
4571 PNG_COLOR_TYPE_GRAY:
4572 Format := tfLuminance8ub1;
4573 PNG_COLOR_TYPE_GRAY_ALPHA:
4574 Format := tfLuminance8Alpha8us1;
4576 Format := tfRGB8ub3;
4577 PNG_COLOR_TYPE_RGB_ALPHA:
4578 Format := tfRGBA8ub4;
4580 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
4583 // cut upper 8 bit from 16 bit formats
4584 if png_get_bit_depth(png, png_info) > 8 then
4585 png_set_strip_16(png);
4587 // expand bitdepth smaller than 8
4588 if png_get_bit_depth(png, png_info) < 8 then
4589 png_set_expand(png);
4591 // allocating mem for scanlines
4592 LineSize := png_get_rowbytes(png, png_info);
4593 GetMem(png_data, TempHeight * LineSize);
4595 SetLength(png_rows, TempHeight);
4596 for Row := Low(png_rows) to High(png_rows) do begin
4597 png_rows[Row] := png_data;
4598 Inc(png_rows[Row], Row * LineSize);
4601 // read complete image into scanlines
4602 png_read_image(png, @png_rows[0]);
4605 png_read_end(png, png_info);
4607 // destroy read struct
4608 png_destroy_read_struct(@png, @png_info, nil);
4610 SetLength(png_rows, 0);
4613 SetData(png_data, Format, TempWidth, TempHeight);
4617 if Assigned(png_data) then
4627 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
4628 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4629 function TglBitmapData.LoadPNG(const aStream: TStream): Boolean;
4634 Row, Col, PixSize, LineSize: Integer;
4635 NewImage, pSource, pDest, pAlpha: pByte;
4636 PngFormat: TglBitmapFormat;
4637 FormatDesc: TFormatDescriptor;
4640 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
4645 StreamPos := aStream.Position;
4646 aStream.Read(Header[0], SizeOf(Header));
4647 aStream.Position := StreamPos;
4649 {Test if the header matches}
4650 if Header = PngHeader then begin
4651 Png := TPNGObject.Create;
4653 Png.LoadFromStream(aStream);
4655 case Png.Header.ColorType of
4657 PngFormat := tfLuminance8ub1;
4658 COLOR_GRAYSCALEALPHA:
4659 PngFormat := tfLuminance8Alpha8us1;
4661 PngFormat := tfBGR8ub3;
4663 PngFormat := tfBGRA8ub4;
4665 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
4668 FormatDesc := TFormatDescriptor.Get(PngFormat);
4669 PixSize := Round(FormatDesc.PixelSize);
4670 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
4672 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
4676 case Png.Header.ColorType of
4677 COLOR_RGB, COLOR_GRAYSCALE:
4679 for Row := 0 to Png.Height -1 do begin
4680 Move (Png.Scanline[Row]^, pDest^, LineSize);
4681 Inc(pDest, LineSize);
4684 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
4686 PixSize := PixSize -1;
4688 for Row := 0 to Png.Height -1 do begin
4689 pSource := Png.Scanline[Row];
4690 pAlpha := pByte(Png.AlphaScanline[Row]);
4692 for Col := 0 to Png.Width -1 do begin
4693 Move (pSource^, pDest^, PixSize);
4694 Inc(pSource, PixSize);
4695 Inc(pDest, PixSize);
4704 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
4707 SetData(NewImage, PngFormat, Png.Header.Width, Png.Header.Height);
4711 if Assigned(NewImage) then
4723 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4724 {$IFDEF GLB_LIB_PNG}
4725 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4726 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
4728 TStream(png_get_io_ptr(png)).Write(buffer^, size);
4732 {$IF DEFINED(GLB_LAZ_PNG)}
4733 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4734 procedure TglBitmapData.SavePNG(const aStream: TStream);
4736 png: TPortableNetworkGraphic;
4737 intf: TLazIntfImage;
4740 png := TPortableNetworkGraphic.Create;
4741 intf := TLazIntfImage.Create(0, 0);
4743 if not AssignToLazIntfImage(intf) then
4744 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
4745 intf.GetRawImage(raw);
4746 png.LoadFromRawImage(raw, false);
4747 png.SaveToStream(aStream);
4754 {$ELSEIF DEFINED(GLB_LIB_PNG)}
4755 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4756 procedure TglBitmapData.SavePNG(const aStream: TStream);
4759 png_info: png_infop;
4760 png_rows: array of pByte;
4764 FormatDesc: TFormatDescriptor;
4766 if not (ftPNG in FormatGetSupportedFiles(Format)) then
4767 raise EglBitmapUnsupportedFormat.Create(Format);
4769 if not init_libPNG then
4770 raise Exception.Create('unable to initialize libPNG.');
4774 tfAlpha8ub1, tfLuminance8ub1:
4775 ColorType := PNG_COLOR_TYPE_GRAY;
4776 tfLuminance8Alpha8us1:
4777 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
4778 tfBGR8ub3, tfRGB8ub3:
4779 ColorType := PNG_COLOR_TYPE_RGB;
4780 tfBGRA8ub4, tfRGBA8ub4:
4781 ColorType := PNG_COLOR_TYPE_RGBA;
4783 raise EglBitmapUnsupportedFormat.Create(Format);
4786 FormatDesc := TFormatDescriptor.Get(Format);
4787 LineSize := FormatDesc.GetSize(Width, 1);
4789 // creating array for scanline
4790 SetLength(png_rows, Height);
4792 for Row := 0 to Height - 1 do begin
4793 png_rows[Row] := Data;
4794 Inc(png_rows[Row], Row * LineSize)
4798 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
4800 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
4803 png_info := png_create_info_struct(png);
4804 if png_info = nil then begin
4805 png_destroy_write_struct(@png, nil);
4806 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
4809 // set read callback
4810 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
4813 png_set_compression_level(png, 6);
4815 if Format in [tfBGR8ub3, tfBGRA8ub4] then
4818 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
4819 png_write_info(png, png_info);
4820 png_write_image(png, @png_rows[0]);
4821 png_write_end(png, png_info);
4822 png_destroy_write_struct(@png, @png_info);
4824 SetLength(png_rows, 0);
4831 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
4832 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4833 procedure TglBitmapData.SavePNG(const aStream: TStream);
4837 pSource, pDest: pByte;
4838 X, Y, PixSize: Integer;
4839 ColorType: Cardinal;
4845 if not (ftPNG in FormatGetSupportedFiles (Format)) then
4846 raise EglBitmapUnsupportedFormat.Create(Format);
4849 tfAlpha8ub1, tfLuminance8ub1: begin
4850 ColorType := COLOR_GRAYSCALE;
4854 tfLuminance8Alpha8us1: begin
4855 ColorType := COLOR_GRAYSCALEALPHA;
4859 tfBGR8ub3, tfRGB8ub3: begin
4860 ColorType := COLOR_RGB;
4864 tfBGRA8ub4, tfRGBA8ub4: begin
4865 ColorType := COLOR_RGBALPHA;
4870 raise EglBitmapUnsupportedFormat.Create(Format);
4873 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
4877 for Y := 0 to Height -1 do begin
4878 pDest := png.ScanLine[Y];
4879 for X := 0 to Width -1 do begin
4880 Move(pSource^, pDest^, PixSize);
4881 Inc(pDest, PixSize);
4882 Inc(pSource, PixSize);
4884 png.AlphaScanline[Y]^[X] := pSource^;
4889 // convert RGB line to BGR
4890 if Format in [tfRGB8ub3, tfRGBA8ub4] then begin
4891 pTemp := png.ScanLine[Y];
4892 for X := 0 to Width -1 do begin
4893 Temp := pByteArray(pTemp)^[0];
4894 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
4895 pByteArray(pTemp)^[2] := Temp;
4902 Png.CompressionLevel := 6;
4903 Png.SaveToStream(aStream);
4911 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4912 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4913 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4914 {$IFDEF GLB_LIB_JPEG}
4916 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
4917 glBitmap_libJPEG_source_mgr = record
4918 pub: jpeg_source_mgr;
4921 SrcBuffer: array [1..4096] of byte;
4924 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
4925 glBitmap_libJPEG_dest_mgr = record
4926 pub: jpeg_destination_mgr;
4928 DestStream: TStream;
4929 DestBuffer: array [1..4096] of byte;
4932 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
4938 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
4944 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
4949 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
4955 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
4961 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4962 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
4964 src: glBitmap_libJPEG_source_mgr_ptr;
4967 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
4969 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
4970 if (bytes <= 0) then begin
4971 src^.SrcBuffer[1] := $FF;
4972 src^.SrcBuffer[2] := JPEG_EOI;
4976 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
4977 src^.pub.bytes_in_buffer := bytes;
4982 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4983 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
4985 src: glBitmap_libJPEG_source_mgr_ptr;
4987 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
4989 if num_bytes > 0 then begin
4990 // wanted byte isn't in buffer so set stream position and read buffer
4991 if num_bytes > src^.pub.bytes_in_buffer then begin
4992 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
4993 src^.pub.fill_input_buffer(cinfo);
4995 // wanted byte is in buffer so only skip
4996 inc(src^.pub.next_input_byte, num_bytes);
4997 dec(src^.pub.bytes_in_buffer, num_bytes);
5002 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5003 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
5005 dest: glBitmap_libJPEG_dest_mgr_ptr;
5007 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5009 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
5010 // write complete buffer
5011 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
5014 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
5015 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
5021 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5022 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
5025 dest: glBitmap_libJPEG_dest_mgr_ptr;
5027 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5029 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
5030 // check for endblock
5031 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
5033 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
5038 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
5043 {$IFDEF GLB_SUPPORT_JPEG_READ}
5044 {$IF DEFINED(GLB_LAZ_JPEG)}
5045 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5046 function TglBitmapData.LoadJPEG(const aStream: TStream): Boolean;
5049 JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
5051 intf: TLazIntfImage;
5052 reader: TFPReaderJPEG;
5054 magic: String[MAGIC_LEN];
5057 StreamPos := aStream.Position;
5059 SetLength(magic, MAGIC_LEN);
5060 aStream.Read(magic[1], MAGIC_LEN);
5061 aStream.Position := StreamPos;
5062 if (magic <> JPEG_MAGIC) then begin
5067 reader := TFPReaderJPEG.Create;
5068 intf := TLazIntfImage.Create(0, 0);
5070 intf.DataDescription := GetDescriptionFromDevice(0, 0, 0);
5071 reader.ImageRead(aStream, intf);
5072 AssignFromLazIntfImage(intf);
5075 aStream.Position := StreamPos;
5084 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
5085 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5086 function TglBitmapData.LoadJPEG(const aStream: TStream): Boolean;
5088 Surface: PSDL_Surface;
5093 RWops := glBitmapCreateRWops(aStream);
5095 if IMG_isJPG(RWops) > 0 then begin
5096 Surface := IMG_LoadJPG_RW(RWops);
5098 AssignFromSurface(Surface);
5101 SDL_FreeSurface(Surface);
5109 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
5110 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5111 function TglBitmapData.LoadJPEG(const aStream: TStream): Boolean;
5114 Temp: array[0..1]of Byte;
5116 jpeg: jpeg_decompress_struct;
5117 jpeg_err: jpeg_error_mgr;
5119 IntFormat: TglBitmapFormat;
5121 TempHeight, TempWidth: Integer;
5126 FormatDesc: TFormatDescriptor;
5130 if not init_libJPEG then
5131 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
5134 // reading first two bytes to test file and set cursor back to begin
5135 StreamPos := aStream.Position;
5136 aStream.Read({%H-}Temp[0], 2);
5137 aStream.Position := StreamPos;
5139 // if Bitmap then read file.
5140 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
5141 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
5142 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
5145 jpeg.err := jpeg_std_error(@jpeg_err);
5146 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
5147 jpeg_err.output_message := glBitmap_libJPEG_output_message;
5149 // decompression struct
5150 jpeg_create_decompress(@jpeg);
5152 // allocation space for streaming methods
5153 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
5155 // seeting up custom functions
5156 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
5157 pub.init_source := glBitmap_libJPEG_init_source;
5158 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
5159 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
5160 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
5161 pub.term_source := glBitmap_libJPEG_term_source;
5163 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
5164 pub.next_input_byte := nil; // until buffer loaded
5166 SrcStream := aStream;
5169 // set global decoding state
5170 jpeg.global_state := DSTATE_START;
5172 // read header of jpeg
5173 jpeg_read_header(@jpeg, false);
5175 // setting output parameter
5176 case jpeg.jpeg_color_space of
5179 jpeg.out_color_space := JCS_GRAYSCALE;
5180 IntFormat := tfLuminance8ub1;
5183 jpeg.out_color_space := JCS_RGB;
5184 IntFormat := tfRGB8ub3;
5188 jpeg_start_decompress(@jpeg);
5190 TempHeight := jpeg.output_height;
5191 TempWidth := jpeg.output_width;
5193 FormatDesc := TFormatDescriptor.Get(IntFormat);
5195 // creating new image
5196 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
5200 for Row := 0 to TempHeight -1 do begin
5201 jpeg_read_scanlines(@jpeg, @pTemp, 1);
5202 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
5205 // finish decompression
5206 jpeg_finish_decompress(@jpeg);
5208 // destroy decompression
5209 jpeg_destroy_decompress(@jpeg);
5211 SetData(pImage, IntFormat, TempWidth, TempHeight);
5215 if Assigned(pImage) then
5225 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
5226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5227 function TglBitmapData.LoadJPEG(const aStream: TStream): Boolean;
5232 Temp: array[0..1]of Byte;
5236 // reading first two bytes to test file and set cursor back to begin
5237 StreamPos := aStream.Position;
5238 aStream.Read(Temp[0], 2);
5239 aStream.Position := StreamPos;
5241 // if Bitmap then read file.
5242 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
5243 bmp := TBitmap.Create;
5245 jpg := TJPEGImage.Create;
5247 jpg.LoadFromStream(aStream);
5249 result := AssignFromBitmap(bmp);
5261 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
5262 {$IF DEFINED(GLB_LAZ_JPEG)}
5263 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5264 procedure TglBitmapData.SaveJPEG(const aStream: TStream);
5267 intf: TLazIntfImage;
5270 jpeg := TJPEGImage.Create;
5271 intf := TLazIntfImage.Create(0, 0);
5273 if not AssignToLazIntfImage(intf) then
5274 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
5275 intf.GetRawImage(raw);
5276 jpeg.LoadFromRawImage(raw, false);
5277 jpeg.SaveToStream(aStream);
5284 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
5285 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5286 procedure TglBitmapData.SaveJPEG(const aStream: TStream);
5288 jpeg: jpeg_compress_struct;
5289 jpeg_err: jpeg_error_mgr;
5291 pTemp, pTemp2: pByte;
5293 procedure CopyRow(pDest, pSource: pByte);
5297 for X := 0 to Width - 1 do begin
5298 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
5299 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
5300 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
5307 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
5308 raise EglBitmapUnsupportedFormat.Create(Format);
5310 if not init_libJPEG then
5311 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
5314 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
5315 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
5318 jpeg.err := jpeg_std_error(@jpeg_err);
5319 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
5320 jpeg_err.output_message := glBitmap_libJPEG_output_message;
5322 // compression struct
5323 jpeg_create_compress(@jpeg);
5325 // allocation space for streaming methods
5326 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
5328 // seeting up custom functions
5329 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
5330 pub.init_destination := glBitmap_libJPEG_init_destination;
5331 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
5332 pub.term_destination := glBitmap_libJPEG_term_destination;
5334 pub.next_output_byte := @DestBuffer[1];
5335 pub.free_in_buffer := Length(DestBuffer);
5337 DestStream := aStream;
5340 // very important state
5341 jpeg.global_state := CSTATE_START;
5342 jpeg.image_width := Width;
5343 jpeg.image_height := Height;
5345 tfAlpha8ub1, tfLuminance8ub1: begin
5346 jpeg.input_components := 1;
5347 jpeg.in_color_space := JCS_GRAYSCALE;
5349 tfRGB8ub3, tfBGR8ub3: begin
5350 jpeg.input_components := 3;
5351 jpeg.in_color_space := JCS_RGB;
5355 jpeg_set_defaults(@jpeg);
5356 jpeg_set_quality(@jpeg, 95, true);
5357 jpeg_start_compress(@jpeg, true);
5360 if Format = tfBGR8ub3 then
5361 GetMem(pTemp2, fRowSize)
5366 for Row := 0 to jpeg.image_height -1 do begin
5368 if Format = tfBGR8ub3 then
5369 CopyRow(pTemp2, pTemp)
5374 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
5375 inc(pTemp, fRowSize);
5379 if Format = tfBGR8ub3 then
5382 jpeg_finish_compress(@jpeg);
5383 jpeg_destroy_compress(@jpeg);
5389 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
5390 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5391 procedure TglBitmapData.SaveJPEG(const aStream: TStream);
5396 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
5397 raise EglBitmapUnsupportedFormat.Create(Format);
5399 Bmp := TBitmap.Create;
5401 Jpg := TJPEGImage.Create;
5403 AssignToBitmap(Bmp);
5404 if (Format in [tfAlpha8ub1, tfLuminance8ub1]) then begin
5405 Jpg.Grayscale := true;
5406 Jpg.PixelFormat := jf8Bit;
5409 Jpg.SaveToStream(aStream);
5420 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5421 //RAW/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5422 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5424 RawHeader = packed record
5430 BitsPerPixel: Integer;
5431 Precision: TglBitmapRec4ub;
5432 Shift: TglBitmapRec4ub;
5435 function TglBitmapData.LoadRAW(const aStream: TStream): Boolean;
5439 fd: TFormatDescriptor;
5443 StartPos := aStream.Position;
5444 aStream.Read(header{%H-}, SizeOf(header));
5445 if (header.Magic <> 'glBMP') then begin
5446 aStream.Position := StartPos;
5450 fd := TFormatDescriptor.GetFromPrecShift(header.Precision, header.Shift, header.BitsPerPixel);
5451 if (fd.Format = tfEmpty) then
5452 raise EglBitmapUnsupportedFormat.Create('no supported format found');
5454 buf := GetMemory(header.DataSize);
5455 aStream.Read(buf^, header.DataSize);
5456 SetData(buf, fd.Format, header.Width, header.Height);
5461 procedure TglBitmapData.SaveRAW(const aStream: TStream);
5464 fd: TFormatDescriptor;
5466 fd := TFormatDescriptor.Get(Format);
5467 header.Magic := 'glBMP';
5468 header.Version := 1;
5469 header.Width := Width;
5470 header.Height := Height;
5471 header.DataSize := fd.GetSize(fDimension);
5472 header.BitsPerPixel := fd.BitsPerPixel;
5473 header.Precision := fd.Precision;
5474 header.Shift := fd.Shift;
5475 aStream.Write(header, SizeOf(header));
5476 aStream.Write(Data^, header.DataSize);
5479 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5480 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5481 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5488 BMP_COMP_BITFIELDS = 3;
5491 TBMPHeader = packed record
5496 bfOffBits: Cardinal;
5499 TBMPInfo = packed record
5505 biCompression: Cardinal;
5506 biSizeImage: Cardinal;
5507 biXPelsPerMeter: Longint;
5508 biYPelsPerMeter: Longint;
5509 biClrUsed: Cardinal;
5510 biClrImportant: Cardinal;
5513 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5514 function TglBitmapData.LoadBMP(const aStream: TStream): Boolean;
5516 //////////////////////////////////////////////////////////////////////////////////////////////////
5517 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapRec4ul): TglBitmapFormat;
5522 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
5523 FillChar(aMask{%H-}, SizeOf(aMask), 0);
5526 case aInfo.biCompression of
5528 BMP_COMP_RLE8: begin
5529 raise EglBitmap.Create('RLE compression is not supported');
5531 BMP_COMP_BITFIELDS: begin
5532 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
5533 for i := 0 to 2 do begin
5534 aStream.Read(tmp{%H-}, SizeOf(tmp));
5535 aMask.arr[i] := tmp;
5538 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
5542 //get suitable format
5543 case aInfo.biBitCount of
5544 8: result := tfLuminance8ub1;
5545 16: result := tfX1RGB5us1;
5546 24: result := tfBGR8ub3;
5547 32: result := tfXRGB8ui1;
5551 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
5554 fd: TFormatDescriptor;
5555 ColorTable: TbmpColorTable;
5558 if (aInfo.biBitCount >= 16) then
5560 aFormat := tfLuminance8ub1;
5561 c := aInfo.biClrUsed;
5563 c := 1 shl aInfo.biBitCount;
5564 SetLength(ColorTable, c);
5565 for i := 0 to c-1 do begin
5566 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
5567 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
5568 aFormat := tfRGB8ub3;
5571 fd := TFormatDescriptor.Get(aFormat);
5572 result := TbmpColorTableFormat.Create;
5573 result.ColorTable := ColorTable;
5574 result.SetCustomValues(aFormat, aInfo.biBitCount, fd.Precision, fd.Shift);
5577 //////////////////////////////////////////////////////////////////////////////////////////////////
5578 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapRec4ul; const aInfo: TBMPInfo): TbmpBitfieldFormat;
5580 fd: TFormatDescriptor;
5583 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
5585 // find suitable format ...
5586 fd := TFormatDescriptor.GetFromMask(aMask);
5587 if (fd.Format <> tfEmpty) then begin
5588 aFormat := fd.Format;
5592 // or create custom bitfield format
5593 result := TbmpBitfieldFormat.Create;
5594 result.SetCustomValues(aInfo.biBitCount, aMask);
5601 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
5602 PaddingBuff: Cardinal;
5603 LineBuf, ImageData, TmpData: PByte;
5604 SourceMD, DestMD: Pointer;
5605 BmpFormat: TglBitmapFormat;
5608 Mask: TglBitmapRec4ul;
5613 SpecialFormat: TFormatDescriptor;
5614 FormatDesc: TFormatDescriptor;
5616 //////////////////////////////////////////////////////////////////////////////////////////////////
5617 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
5620 Pixel: TglBitmapPixelData;
5622 aStream.Read(aLineBuf^, rbLineSize);
5623 SpecialFormat.PreparePixel(Pixel);
5624 for i := 0 to Info.biWidth-1 do begin
5625 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
5626 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
5627 FormatDesc.Map(Pixel, aData, DestMD);
5633 BmpFormat := tfEmpty;
5634 SpecialFormat := nil;
5640 StartPos := aStream.Position;
5641 aStream.Read(Header{%H-}, SizeOf(Header));
5643 if Header.bfType = BMP_MAGIC then begin
5645 BmpFormat := ReadInfo(Info, Mask);
5646 SpecialFormat := ReadColorTable(BmpFormat, Info);
5647 if not Assigned(SpecialFormat) then
5648 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
5649 aStream.Position := StartPos + Header.bfOffBits;
5651 if (BmpFormat <> tfEmpty) then begin
5652 FormatDesc := TFormatDescriptor.Get(BmpFormat);
5653 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
5654 wbLineSize := Trunc(Info.biWidth * FormatDesc.BytesPerPixel);
5655 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
5658 DestMD := FormatDesc.CreateMappingData;
5659 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
5660 GetMem(ImageData, ImageSize);
5661 if Assigned(SpecialFormat) then begin
5662 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
5663 SourceMD := SpecialFormat.CreateMappingData;
5668 FillChar(ImageData^, ImageSize, $FF);
5669 TmpData := ImageData;
5670 if (Info.biHeight > 0) then
5671 Inc(TmpData, wbLineSize * (Info.biHeight-1));
5672 for i := 0 to Abs(Info.biHeight)-1 do begin
5673 if Assigned(SpecialFormat) then
5674 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
5676 aStream.Read(TmpData^, wbLineSize); //else only read data
5677 if (Info.biHeight > 0) then
5678 dec(TmpData, wbLineSize)
5680 inc(TmpData, wbLineSize);
5681 aStream.Read(PaddingBuff{%H-}, Padding);
5683 SetData(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight));
5686 if Assigned(LineBuf) then
5688 if Assigned(SourceMD) then
5689 SpecialFormat.FreeMappingData(SourceMD);
5690 FormatDesc.FreeMappingData(DestMD);
5693 if Assigned(ImageData) then
5698 raise EglBitmap.Create('LoadBMP - No suitable format found');
5700 aStream.Position := StartPos;
5704 FreeAndNil(SpecialFormat);
5707 else aStream.Position := StartPos;
5710 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5711 procedure TglBitmapData.SaveBMP(const aStream: TStream);
5715 Converter: TFormatDescriptor;
5716 FormatDesc: TFormatDescriptor;
5717 SourceFD, DestFD: Pointer;
5718 pData, srcData, dstData, ConvertBuffer: pByte;
5720 Pixel: TglBitmapPixelData;
5721 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
5722 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
5724 PaddingBuff: Cardinal;
5726 function GetLineWidth : Integer;
5728 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
5732 if not (ftBMP in FormatGetSupportedFiles(Format)) then
5733 raise EglBitmapUnsupportedFormat.Create(Format);
5736 FormatDesc := TFormatDescriptor.Get(Format);
5737 ImageSize := FormatDesc.GetSize(Dimension);
5739 FillChar(Header{%H-}, SizeOf(Header), 0);
5740 Header.bfType := BMP_MAGIC;
5741 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
5742 Header.bfReserved1 := 0;
5743 Header.bfReserved2 := 0;
5744 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
5746 FillChar(Info{%H-}, SizeOf(Info), 0);
5747 Info.biSize := SizeOf(Info);
5748 Info.biWidth := Width;
5749 Info.biHeight := Height;
5751 Info.biCompression := BMP_COMP_RGB;
5752 Info.biSizeImage := ImageSize;
5756 tfAlpha4ub1, tfAlpha8ub1, tfLuminance4ub1, tfLuminance8ub1, tfR3G3B2ub1:
5758 Info.biBitCount := 8;
5759 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
5760 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
5761 Converter := TbmpColorTableFormat.Create;
5762 with (Converter as TbmpColorTableFormat) do begin
5763 SetCustomValues(fFormat, 8, FormatDesc.Precision, FormatDesc.Shift);
5768 tfLuminance4Alpha4ub2, tfLuminance6Alpha2ub2, tfLuminance8Alpha8ub2,
5769 tfRGBX4us1, tfXRGB4us1, tfRGB5X1us1, tfX1RGB5us1, tfR5G6B5us1, tfRGB5A1us1, tfA1RGB5us1, tfRGBA4us1, tfARGB4us1,
5770 tfBGRX4us1, tfXBGR4us1, tfBGR5X1us1, tfX1BGR5us1, tfB5G6R5us1, tfBGR5A1us1, tfA1BGR5us1, tfBGRA4us1, tfABGR4us1:
5772 Info.biBitCount := 16;
5773 Info.biCompression := BMP_COMP_BITFIELDS;
5776 tfBGR8ub3, tfRGB8ub3:
5778 Info.biBitCount := 24;
5779 if (Format = tfRGB8ub3) then
5780 Converter := TfdBGR8ub3.Create; //use BGR8 Format Descriptor to Swap RGB Values
5783 tfRGBX8ui1, tfXRGB8ui1, tfRGB10X2ui1, tfX2RGB10ui1, tfRGBA8ui1, tfARGB8ui1, tfRGBA8ub4, tfRGB10A2ui1, tfA2RGB10ui1,
5784 tfBGRX8ui1, tfXBGR8ui1, tfBGR10X2ui1, tfX2BGR10ui1, tfBGRA8ui1, tfABGR8ui1, tfBGRA8ub4, tfBGR10A2ui1, tfA2BGR10ui1:
5786 Info.biBitCount := 32;
5787 Info.biCompression := BMP_COMP_BITFIELDS;
5790 raise EglBitmapUnsupportedFormat.Create(Format);
5792 Info.biXPelsPerMeter := 2835;
5793 Info.biYPelsPerMeter := 2835;
5796 if Info.biCompression = BMP_COMP_BITFIELDS then begin
5797 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
5798 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
5800 RedMask := FormatDesc.Mask.r;
5801 GreenMask := FormatDesc.Mask.g;
5802 BlueMask := FormatDesc.Mask.b;
5803 AlphaMask := FormatDesc.Mask.a;
5807 aStream.Write(Header, SizeOf(Header));
5808 aStream.Write(Info, SizeOf(Info));
5811 if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
5812 with (Converter as TbmpColorTableFormat) do
5813 aStream.Write(ColorTable[0].b,
5814 SizeOf(TbmpColorTableEnty) * Length(ColorTable));
5817 if Info.biCompression = BMP_COMP_BITFIELDS then begin
5818 aStream.Write(RedMask, SizeOf(Cardinal));
5819 aStream.Write(GreenMask, SizeOf(Cardinal));
5820 aStream.Write(BlueMask, SizeOf(Cardinal));
5821 aStream.Write(AlphaMask, SizeOf(Cardinal));
5825 rbLineSize := Round(Info.biWidth * FormatDesc.BytesPerPixel);
5826 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
5827 Padding := GetLineWidth - wbLineSize;
5831 inc(pData, (Height-1) * rbLineSize);
5833 // prepare row buffer. But only for RGB because RGBA supports color masks
5834 // so it's possible to change color within the image.
5835 if Assigned(Converter) then begin
5836 FormatDesc.PreparePixel(Pixel);
5837 GetMem(ConvertBuffer, wbLineSize);
5838 SourceFD := FormatDesc.CreateMappingData;
5839 DestFD := Converter.CreateMappingData;
5841 ConvertBuffer := nil;
5844 for LineIdx := 0 to Height - 1 do begin
5846 if Assigned(Converter) then begin
5848 dstData := ConvertBuffer;
5849 for PixelIdx := 0 to Info.biWidth-1 do begin
5850 FormatDesc.Unmap(srcData, Pixel, SourceFD);
5851 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
5852 Converter.Map(Pixel, dstData, DestFD);
5854 aStream.Write(ConvertBuffer^, wbLineSize);
5856 aStream.Write(pData^, rbLineSize);
5858 dec(pData, rbLineSize);
5859 if (Padding > 0) then
5860 aStream.Write(PaddingBuff, Padding);
5863 // destroy row buffer
5864 if Assigned(ConvertBuffer) then begin
5865 FormatDesc.FreeMappingData(SourceFD);
5866 Converter.FreeMappingData(DestFD);
5867 FreeMem(ConvertBuffer);
5871 if Assigned(Converter) then
5876 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5877 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5878 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5880 TTGAHeader = packed record
5884 //ColorMapSpec: Array[0..4] of Byte;
5885 ColorMapStart: Word;
5886 ColorMapLength: Word;
5887 ColorMapEntrySize: Byte;
5897 TGA_UNCOMPRESSED_RGB = 2;
5898 TGA_UNCOMPRESSED_GRAY = 3;
5899 TGA_COMPRESSED_RGB = 10;
5900 TGA_COMPRESSED_GRAY = 11;
5902 TGA_NONE_COLOR_TABLE = 0;
5904 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5905 function TglBitmapData.LoadTGA(const aStream: TStream): Boolean;
5908 ImageData: System.PByte;
5909 StartPosition: Int64;
5910 PixelSize, LineSize: Integer;
5911 tgaFormat: TglBitmapFormat;
5912 FormatDesc: TFormatDescriptor;
5913 Counter: packed record
5915 low, high, dir: Integer;
5922 ////////////////////////////////////////////////////////////////////////////////////////
5923 procedure ReadUncompressed;
5926 buf, tmp1, tmp2: System.PByte;
5929 if (Counter.X.dir < 0) then
5930 GetMem(buf, LineSize);
5932 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
5934 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
5935 if (Counter.X.dir < 0) then begin //flip X
5936 aStream.Read(buf^, LineSize);
5938 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
5939 for i := 0 to Header.Width-1 do begin //for all pixels in line
5940 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
5945 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
5948 aStream.Read(tmp1^, LineSize);
5949 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
5952 if Assigned(buf) then
5957 ////////////////////////////////////////////////////////////////////////////////////////
5958 procedure ReadCompressed;
5960 /////////////////////////////////////////////////////////////////
5962 TmpData: System.PByte;
5963 LinePixelsRead: Integer;
5964 procedure CheckLine;
5966 if (LinePixelsRead >= Header.Width) then begin
5967 LinePixelsRead := 0;
5968 inc(Counter.Y.low, Counter.Y.dir); //next line index
5969 TmpData := ImageData;
5970 inc(TmpData, Counter.Y.low * LineSize); //set line
5971 if (Counter.X.dir < 0) then //if x flipped then
5972 inc(TmpData, LineSize - PixelSize); //set last pixel
5976 /////////////////////////////////////////////////////////////////
5979 CacheSize, CachePos: Integer;
5980 procedure CachedRead(out Buffer; Count: Integer);
5984 if (CachePos + Count > CacheSize) then begin
5985 //if buffer overflow save non read bytes
5987 if (CacheSize - CachePos > 0) then begin
5988 BytesRead := CacheSize - CachePos;
5989 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
5990 inc(CachePos, BytesRead);
5993 //load cache from file
5994 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
5995 aStream.Read(Cache^, CacheSize);
5998 //read rest of requested bytes
5999 if (Count - BytesRead > 0) then begin
6000 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
6001 inc(CachePos, Count - BytesRead);
6004 //if no buffer overflow just read the data
6005 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
6006 inc(CachePos, Count);
6010 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
6015 inc(aBuffer, Counter.X.dir);
6018 PWord(aBuffer)^ := PWord(aData)^;
6019 inc(aBuffer, 2 * Counter.X.dir);
6022 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
6023 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
6024 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
6025 inc(aBuffer, 3 * Counter.X.dir);
6028 PCardinal(aBuffer)^ := PCardinal(aData)^;
6029 inc(aBuffer, 4 * Counter.X.dir);
6035 TotalPixelsToRead, TotalPixelsRead: Integer;
6037 buf: array [0..3] of Byte; //1 pixel is max 32bit long
6038 PixelRepeat: Boolean;
6039 PixelsToRead, PixelCount: Integer;
6044 TotalPixelsToRead := Header.Width * Header.Height;
6045 TotalPixelsRead := 0;
6046 LinePixelsRead := 0;
6048 GetMem(Cache, CACHE_SIZE);
6050 TmpData := ImageData;
6051 inc(TmpData, Counter.Y.low * LineSize); //set line
6052 if (Counter.X.dir < 0) then //if x flipped then
6053 inc(TmpData, LineSize - PixelSize); //set last pixel
6057 CachedRead(Temp, 1);
6058 PixelRepeat := (Temp and $80) > 0;
6059 PixelsToRead := (Temp and $7F) + 1;
6060 inc(TotalPixelsRead, PixelsToRead);
6063 CachedRead(buf[0], PixelSize);
6064 while (PixelsToRead > 0) do begin
6066 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
6067 while (PixelCount > 0) do begin
6068 if not PixelRepeat then
6069 CachedRead(buf[0], PixelSize);
6070 PixelToBuffer(@buf[0], TmpData);
6071 inc(LinePixelsRead);
6076 until (TotalPixelsRead >= TotalPixelsToRead);
6082 function IsGrayFormat: Boolean;
6084 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
6090 // reading header to test file and set cursor back to begin
6091 StartPosition := aStream.Position;
6092 aStream.Read(Header{%H-}, SizeOf(Header));
6094 // no colormapped files
6095 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
6096 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
6099 if Header.ImageID <> 0 then // skip image ID
6100 aStream.Position := aStream.Position + Header.ImageID;
6102 tgaFormat := tfEmpty;
6104 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
6105 0: tgaFormat := tfLuminance8ub1;
6106 8: tgaFormat := tfAlpha8ub1;
6109 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
6110 0: tgaFormat := tfLuminance16us1;
6111 8: tgaFormat := tfLuminance8Alpha8ub2;
6112 end else case (Header.ImageDesc and $F) of
6113 0: tgaFormat := tfX1RGB5us1;
6114 1: tgaFormat := tfA1RGB5us1;
6115 4: tgaFormat := tfARGB4us1;
6118 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6119 0: tgaFormat := tfBGR8ub3;
6122 32: if IsGrayFormat then case (Header.ImageDesc and $F) of
6123 0: tgaFormat := tfDepth32ui1;
6124 end else case (Header.ImageDesc and $F) of
6125 0: tgaFormat := tfX2RGB10ui1;
6126 2: tgaFormat := tfA2RGB10ui1;
6127 8: tgaFormat := tfARGB8ui1;
6131 if (tgaFormat = tfEmpty) then
6132 raise EglBitmap.Create('LoadTga - unsupported format');
6134 FormatDesc := TFormatDescriptor.Get(tgaFormat);
6135 PixelSize := FormatDesc.GetSize(1, 1);
6136 LineSize := FormatDesc.GetSize(Header.Width, 1);
6138 GetMem(ImageData, LineSize * Header.Height);
6141 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
6142 Counter.X.low := Header.Height-1;;
6143 Counter.X.high := 0;
6144 Counter.X.dir := -1;
6147 Counter.X.high := Header.Height-1;
6152 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
6154 Counter.Y.high := Header.Height-1;
6157 Counter.Y.low := Header.Height-1;;
6158 Counter.Y.high := 0;
6159 Counter.Y.dir := -1;
6163 case Header.ImageType of
6164 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
6166 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
6170 SetData(ImageData, tgaFormat, Header.Width, Header.Height);
6173 if Assigned(ImageData) then
6178 aStream.Position := StartPosition;
6181 else aStream.Position := StartPosition;
6184 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6185 procedure TglBitmapData.SaveTGA(const aStream: TStream);
6189 FormatDesc: TFormatDescriptor;
6191 if not (ftTGA in FormatGetSupportedFiles(Format)) then
6192 raise EglBitmapUnsupportedFormat.Create(Format);
6195 FormatDesc := TFormatDescriptor.Get(Format);
6196 FillChar(Header{%H-}, SizeOf(Header), 0);
6197 Header.ImageDesc := CountSetBits(FormatDesc.Range.a) and $F;
6198 Header.Bpp := FormatDesc.BitsPerPixel;
6199 Header.Width := Width;
6200 Header.Height := Height;
6201 Header.ImageDesc := Header.ImageDesc or $20; //flip y
6202 if FormatDesc.IsGrayscale or (not FormatDesc.IsGrayscale and not FormatDesc.HasRed and FormatDesc.HasAlpha) then
6203 Header.ImageType := TGA_UNCOMPRESSED_GRAY
6205 Header.ImageType := TGA_UNCOMPRESSED_RGB;
6206 aStream.Write(Header, SizeOf(Header));
6209 Size := FormatDesc.GetSize(Dimension);
6210 aStream.Write(Data^, Size);
6213 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6214 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6217 DDS_MAGIC: Cardinal = $20534444;
6219 // DDS_header.dwFlags
6220 DDSD_CAPS = $00000001;
6221 DDSD_HEIGHT = $00000002;
6222 DDSD_WIDTH = $00000004;
6223 DDSD_PIXELFORMAT = $00001000;
6225 // DDS_header.sPixelFormat.dwFlags
6226 DDPF_ALPHAPIXELS = $00000001;
6227 DDPF_ALPHA = $00000002;
6228 DDPF_FOURCC = $00000004;
6229 DDPF_RGB = $00000040;
6230 DDPF_LUMINANCE = $00020000;
6232 // DDS_header.sCaps.dwCaps1
6233 DDSCAPS_TEXTURE = $00001000;
6235 // DDS_header.sCaps.dwCaps2
6236 DDSCAPS2_CUBEMAP = $00000200;
6238 D3DFMT_DXT1 = $31545844;
6239 D3DFMT_DXT3 = $33545844;
6240 D3DFMT_DXT5 = $35545844;
6243 TDDSPixelFormat = packed record
6247 dwRGBBitCount: Cardinal;
6248 dwRBitMask: Cardinal;
6249 dwGBitMask: Cardinal;
6250 dwBBitMask: Cardinal;
6251 dwABitMask: Cardinal;
6254 TDDSCaps = packed record
6258 dwReserved: Cardinal;
6261 TDDSHeader = packed record
6266 dwPitchOrLinearSize: Cardinal;
6268 dwMipMapCount: Cardinal;
6269 dwReserved: array[0..10] of Cardinal;
6270 PixelFormat: TDDSPixelFormat;
6272 dwReserved2: Cardinal;
6275 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6276 function TglBitmapData.LoadDDS(const aStream: TStream): Boolean;
6279 Converter: TbmpBitfieldFormat;
6281 function GetDDSFormat: TglBitmapFormat;
6283 fd: TFormatDescriptor;
6285 Mask: TglBitmapRec4ul;
6286 Range: TglBitmapRec4ui;
6290 with Header.PixelFormat do begin
6292 if ((dwFlags and DDPF_FOURCC) > 0) then begin
6293 case Header.PixelFormat.dwFourCC of
6294 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
6295 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
6296 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
6298 end else if ((dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE or DDPF_ALPHA)) > 0) then begin
6300 if ((dwFlags and DDPF_LUMINANCE) = 0) then begin
6301 Mask.r := dwRBitMask;
6302 Mask.g := dwGBitMask;
6303 Mask.b := dwBBitMask;
6305 Mask.r := dwRBitMask;
6306 Mask.g := dwRBitMask;
6307 Mask.b := dwRBitMask;
6309 if (dwFlags and DDPF_ALPHAPIXELS > 0) then
6310 Mask.a := dwABitMask
6314 //find matching format
6315 fd := TFormatDescriptor.GetFromMask(Mask, dwRGBBitCount);
6316 result := fd.Format;
6317 if (result <> tfEmpty) then
6320 //find format with same Range
6322 Range.arr[i] := (2 shl CountSetBits(Mask.arr[i])) - 1;
6323 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6324 fd := TFormatDescriptor.Get(result);
6327 if (fd.Range.arr[i] <> Range.arr[i]) then begin
6335 //no format with same range found -> use default
6336 if (result = tfEmpty) then begin
6337 if (dwABitMask > 0) then
6338 result := tfRGBA8ui1
6340 result := tfRGB8ub3;
6343 Converter := TbmpBitfieldFormat.Create;
6344 Converter.SetCustomValues(dwRGBBitCount, glBitmapRec4ul(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask));
6351 x, y, LineSize, RowSize, Magic: Cardinal;
6352 NewImage, TmpData, RowData, SrcData: System.PByte;
6353 SourceMD, DestMD: Pointer;
6354 Pixel: TglBitmapPixelData;
6355 ddsFormat: TglBitmapFormat;
6356 FormatDesc: TFormatDescriptor;
6361 StreamPos := aStream.Position;
6364 aStream.Read(Magic{%H-}, sizeof(Magic));
6365 if (Magic <> DDS_MAGIC) then begin
6366 aStream.Position := StreamPos;
6371 aStream.Read(Header{%H-}, sizeof(Header));
6372 if (Header.dwSize <> SizeOf(Header)) or
6373 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
6374 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
6376 aStream.Position := StreamPos;
6380 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
6381 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
6383 ddsFormat := GetDDSFormat;
6385 if (ddsFormat = tfEmpty) then
6386 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
6388 FormatDesc := TFormatDescriptor.Get(ddsFormat);
6389 LineSize := Trunc(Header.dwWidth * FormatDesc.BytesPerPixel);
6390 GetMem(NewImage, Header.dwHeight * LineSize);
6392 TmpData := NewImage;
6395 if Assigned(Converter) then begin
6396 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
6397 GetMem(RowData, RowSize);
6398 SourceMD := Converter.CreateMappingData;
6399 DestMD := FormatDesc.CreateMappingData;
6401 for y := 0 to Header.dwHeight-1 do begin
6402 TmpData := NewImage;
6403 inc(TmpData, y * LineSize);
6405 aStream.Read(SrcData^, RowSize);
6406 for x := 0 to Header.dwWidth-1 do begin
6407 Converter.Unmap(SrcData, Pixel, SourceMD);
6408 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
6409 FormatDesc.Map(Pixel, TmpData, DestMD);
6413 Converter.FreeMappingData(SourceMD);
6414 FormatDesc.FreeMappingData(DestMD);
6420 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
6421 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
6422 for Y := 0 to Header.dwHeight-1 do begin
6423 aStream.Read(TmpData^, RowSize);
6424 Inc(TmpData, LineSize);
6429 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
6430 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
6431 for Y := 0 to Header.dwHeight-1 do begin
6432 aStream.Read(TmpData^, RowSize);
6433 Inc(TmpData, LineSize);
6436 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
6438 SetData(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
6441 if Assigned(NewImage) then
6446 FreeAndNil(Converter);
6450 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6451 procedure TglBitmapData.SaveDDS(const aStream: TStream);
6454 FormatDesc: TFormatDescriptor;
6456 if not (ftDDS in FormatGetSupportedFiles(Format)) then
6457 raise EglBitmapUnsupportedFormat.Create(Format);
6459 FormatDesc := TFormatDescriptor.Get(Format);
6462 FillChar(Header{%H-}, SizeOf(Header), 0);
6463 Header.dwSize := SizeOf(Header);
6464 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
6466 Header.dwWidth := Max(1, Width);
6467 Header.dwHeight := Max(1, Height);
6470 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
6473 Header.PixelFormat.dwSize := sizeof(Header);
6474 if (FormatDesc.IsCompressed) then begin
6475 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
6477 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
6478 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
6479 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
6481 end else if not FormatDesc.HasColor and FormatDesc.HasAlpha then begin
6482 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
6483 Header.PixelFormat.dwRGBBitCount := FormatDesc.BitsPerPixel;
6484 Header.PixelFormat.dwABitMask := FormatDesc.Mask.a;
6485 end else if FormatDesc.IsGrayscale then begin
6486 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
6487 Header.PixelFormat.dwRGBBitCount := FormatDesc.BitsPerPixel;
6488 Header.PixelFormat.dwRBitMask := FormatDesc.Mask.r;
6489 Header.PixelFormat.dwABitMask := FormatDesc.Mask.a;
6491 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
6492 Header.PixelFormat.dwRGBBitCount := FormatDesc.BitsPerPixel;
6493 Header.PixelFormat.dwRBitMask := FormatDesc.Mask.r;
6494 Header.PixelFormat.dwGBitMask := FormatDesc.Mask.g;
6495 Header.PixelFormat.dwBBitMask := FormatDesc.Mask.b;
6496 Header.PixelFormat.dwABitMask := FormatDesc.Mask.a;
6499 if (FormatDesc.HasAlpha) then
6500 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
6502 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
6503 aStream.Write(Header, SizeOf(Header));
6504 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
6507 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6508 function TglBitmapData.FlipHorz: Boolean;
6510 fd: TglBitmapFormatDescriptor;
6511 Col, RowSize, PixelSize: Integer;
6512 pTempDest, pDest, pSource: PByte;
6515 fd := FormatDescriptor;
6516 PixelSize := Ceil(fd.BytesPerPixel);
6517 RowSize := fd.GetSize(Width, 1);
6518 if Assigned(Data) and not fd.IsCompressed then begin
6520 GetMem(pDest, RowSize);
6523 Inc(pTempDest, RowSize);
6524 for Col := 0 to Width-1 do begin
6525 dec(pTempDest, PixelSize); //dec before, because ptr is behind last byte of data
6526 Move(pSource^, pTempDest^, PixelSize);
6527 Inc(pSource, PixelSize);
6529 SetData(pDest, Format, Width);
6532 if Assigned(pDest) then
6539 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6540 function TglBitmapData.FlipVert: Boolean;
6542 fd: TglBitmapFormatDescriptor;
6543 Row, RowSize, PixelSize: Integer;
6544 TempDestData, DestData, SourceData: PByte;
6547 fd := FormatDescriptor;
6548 PixelSize := Ceil(fd.BytesPerPixel);
6549 RowSize := fd.GetSize(Width, 1);
6550 if Assigned(Data) then begin
6552 GetMem(DestData, Height * RowSize);
6554 TempDestData := DestData;
6555 Inc(TempDestData, Width * (Height -1) * PixelSize);
6556 for Row := 0 to Height -1 do begin
6557 Move(SourceData^, TempDestData^, RowSize);
6558 Dec(TempDestData, RowSize);
6559 Inc(SourceData, RowSize);
6561 SetData(DestData, Format, Width, Height);
6564 if Assigned(DestData) then
6571 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6572 procedure TglBitmapData.LoadFromFile(const aFilename: String);
6576 if not FileExists(aFilename) then
6577 raise EglBitmap.Create('file does not exist: ' + aFilename);
6578 fs := TFileStream.Create(aFilename, fmOpenRead);
6582 fFilename := aFilename;
6588 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6589 procedure TglBitmapData.LoadFromStream(const aStream: TStream);
6591 {$IFDEF GLB_SUPPORT_PNG_READ}
6592 if not LoadPNG(aStream) then
6594 {$IFDEF GLB_SUPPORT_JPEG_READ}
6595 if not LoadJPEG(aStream) then
6597 if not LoadDDS(aStream) then
6598 if not LoadTGA(aStream) then
6599 if not LoadBMP(aStream) then
6600 if not LoadRAW(aStream) then
6601 raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
6604 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6605 procedure TglBitmapData.LoadFromFunc(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat;
6606 const aFunc: TglBitmapFunction; const aArgs: Pointer);
6611 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
6612 GetMem(tmpData, size);
6614 FillChar(tmpData^, size, #$FF);
6615 SetData(tmpData, aFormat, aSize.X, aSize.Y);
6617 if Assigned(tmpData) then
6621 Convert(Self, aFunc, false, aFormat, aArgs);
6624 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6625 procedure TglBitmapData.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
6627 rs: TResourceStream;
6629 PrepareResType(aResource, aResType);
6630 rs := TResourceStream.Create(aInstance, aResource, aResType);
6638 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6639 procedure TglBitmapData.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
6641 rs: TResourceStream;
6643 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
6651 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6652 procedure TglBitmapData.SaveToFile(const aFilename: String; const aFileType: TglBitmapFileType);
6656 fs := TFileStream.Create(aFileName, fmCreate);
6659 SaveToStream(fs, aFileType);
6665 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6666 procedure TglBitmapData.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
6669 {$IFDEF GLB_SUPPORT_PNG_WRITE}
6670 ftPNG: SavePNG(aStream);
6672 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6673 ftJPEG: SaveJPEG(aStream);
6675 ftDDS: SaveDDS(aStream);
6676 ftTGA: SaveTGA(aStream);
6677 ftBMP: SaveBMP(aStream);
6678 ftRAW: SaveRAW(aStream);
6682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6683 function TglBitmapData.Convert(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
6685 result := Convert(Self, aFunc, aCreateTemp, Format, aArgs);
6688 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6689 function TglBitmapData.Convert(const aSource: TglBitmapData; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
6690 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
6692 DestData, TmpData, SourceData: pByte;
6693 TempHeight, TempWidth: Integer;
6694 SourceFD, DestFD: TFormatDescriptor;
6695 SourceMD, DestMD: Pointer;
6697 FuncRec: TglBitmapFunctionRec;
6699 Assert(Assigned(Data));
6700 Assert(Assigned(aSource));
6701 Assert(Assigned(aSource.Data));
6704 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
6705 SourceFD := TFormatDescriptor.Get(aSource.Format);
6706 DestFD := TFormatDescriptor.Get(aFormat);
6708 if (SourceFD.IsCompressed) then
6709 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
6710 if (DestFD.IsCompressed) then
6711 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
6713 // inkompatible Formats so CreateTemp
6714 if (SourceFD.BitsPerPixel <> DestFD.BitsPerPixel) then
6715 aCreateTemp := true;
6718 TempHeight := Max(1, aSource.Height);
6719 TempWidth := Max(1, aSource.Width);
6721 FuncRec.Sender := Self;
6722 FuncRec.Args := aArgs;
6725 if aCreateTemp then begin
6726 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
6727 DestData := TmpData;
6732 SourceFD.PreparePixel(FuncRec.Source);
6733 DestFD.PreparePixel (FuncRec.Dest);
6735 SourceMD := SourceFD.CreateMappingData;
6736 DestMD := DestFD.CreateMappingData;
6738 FuncRec.Size := aSource.Dimension;
6739 FuncRec.Position.Fields := FuncRec.Size.Fields;
6742 SourceData := aSource.Data;
6743 FuncRec.Position.Y := 0;
6744 while FuncRec.Position.Y < TempHeight do begin
6745 FuncRec.Position.X := 0;
6746 while FuncRec.Position.X < TempWidth do begin
6747 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
6749 DestFD.Map(FuncRec.Dest, DestData, DestMD);
6750 inc(FuncRec.Position.X);
6752 inc(FuncRec.Position.Y);
6755 // Updating Image or InternalFormat
6757 SetData(TmpData, aFormat, aSource.Width, aSource.Height)
6758 else if (aFormat <> fFormat) then
6763 SourceFD.FreeMappingData(SourceMD);
6764 DestFD.FreeMappingData(DestMD);
6767 if aCreateTemp and Assigned(TmpData) then
6774 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6775 function TglBitmapData.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
6777 SourceFD, DestFD: TFormatDescriptor;
6778 SourcePD, DestPD: TglBitmapPixelData;
6779 ShiftData: TShiftData;
6781 function DataIsIdentical: Boolean;
6783 result := SourceFD.MaskMatch(DestFD.Mask);
6786 function CanCopyDirect: Boolean;
6789 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
6790 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
6791 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
6792 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
6795 function CanShift: Boolean;
6798 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
6799 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
6800 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
6801 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
6804 function GetShift(aSource, aDest: Cardinal) : ShortInt;
6807 while (aSource > aDest) and (aSource > 0) do begin
6809 aSource := aSource shr 1;
6814 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
6815 SourceFD := TFormatDescriptor.Get(Format);
6816 DestFD := TFormatDescriptor.Get(aFormat);
6818 if DataIsIdentical then begin
6824 SourceFD.PreparePixel(SourcePD);
6825 DestFD.PreparePixel (DestPD);
6827 if CanCopyDirect then
6828 result := Convert(Self, glBitmapConvertCopyFunc, false, aFormat)
6829 else if CanShift then begin
6830 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
6831 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
6832 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
6833 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
6834 result := Convert(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
6836 result := Convert(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
6842 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6843 function TglBitmapData.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
6845 Row, RowSize: Integer;
6846 SourceData, TmpData: PByte;
6848 FormatDesc: TFormatDescriptor;
6850 function GetRowPointer(Row: Integer): pByte;
6852 result := aSurface.pixels;
6853 Inc(result, Row * RowSize);
6859 FormatDesc := TFormatDescriptor.Get(Format);
6860 if FormatDesc.IsCompressed then
6861 raise EglBitmapUnsupportedFormat.Create(Format);
6863 if Assigned(Data) then begin
6864 case Trunc(FormatDesc.PixelSize) of
6870 raise EglBitmapUnsupportedFormat.Create(Format);
6873 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
6874 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
6876 RowSize := FormatDesc.GetSize(FileWidth, 1);
6878 for Row := 0 to FileHeight-1 do begin
6879 TmpData := GetRowPointer(Row);
6880 if Assigned(TmpData) then begin
6881 Move(SourceData^, TmpData^, RowSize);
6882 inc(SourceData, RowSize);
6889 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6890 function TglBitmapData.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
6892 pSource, pData, pTempData: PByte;
6893 Row, RowSize, TempWidth, TempHeight: Integer;
6894 IntFormat: TglBitmapFormat;
6895 fd: TFormatDescriptor;
6896 Mask: TglBitmapMask;
6898 function GetRowPointer(Row: Integer): pByte;
6900 result := aSurface^.pixels;
6901 Inc(result, Row * RowSize);
6906 if (Assigned(aSurface)) then begin
6907 with aSurface^.format^ do begin
6912 IntFormat := TFormatDescriptor.GetFromMask(Mask).Format;
6913 if (IntFormat = tfEmpty) then
6914 raise EglBitmap.Create('AssignFromSurface - Invalid Pixelformat.');
6917 fd := TFormatDescriptor.Get(IntFormat);
6918 TempWidth := aSurface^.w;
6919 TempHeight := aSurface^.h;
6920 RowSize := fd.GetSize(TempWidth, 1);
6921 GetMem(pData, TempHeight * RowSize);
6924 for Row := 0 to TempHeight -1 do begin
6925 pSource := GetRowPointer(Row);
6926 if (Assigned(pSource)) then begin
6927 Move(pSource^, pTempData^, RowSize);
6928 Inc(pTempData, RowSize);
6931 SetData(pData, IntFormat, TempWidth, TempHeight);
6934 if Assigned(pData) then
6941 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6942 function TglBitmapData.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
6944 Row, Col, AlphaInterleave: Integer;
6945 pSource, pDest: PByte;
6947 function GetRowPointer(Row: Integer): pByte;
6949 result := aSurface.pixels;
6950 Inc(result, Row * Width);
6955 if Assigned(Data) then begin
6956 if Format in [tfAlpha8ub1, tfLuminance8Alpha8ub2, tfBGRA8ub4, tfRGBA8ub4] then begin
6957 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
6959 AlphaInterleave := 0;
6961 tfLuminance8Alpha8ub2:
6962 AlphaInterleave := 1;
6963 tfBGRA8ub4, tfRGBA8ub4:
6964 AlphaInterleave := 3;
6968 for Row := 0 to Height -1 do begin
6969 pDest := GetRowPointer(Row);
6970 if Assigned(pDest) then begin
6971 for Col := 0 to Width -1 do begin
6972 Inc(pSource, AlphaInterleave);
6984 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6985 function TglBitmapData.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
6989 bmp := TglBitmap2D.Create;
6991 bmp.AssignFromSurface(aSurface);
6992 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7001 function CreateGrayPalette: HPALETTE;
7006 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
7008 Pal.palVersion := $300;
7009 Pal.palNumEntries := 256;
7011 for Idx := 0 to Pal.palNumEntries - 1 do begin
7012 Pal.palPalEntry[Idx].peRed := Idx;
7013 Pal.palPalEntry[Idx].peGreen := Idx;
7014 Pal.palPalEntry[Idx].peBlue := Idx;
7015 Pal.palPalEntry[Idx].peFlags := 0;
7017 Result := CreatePalette(Pal^);
7021 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7022 function TglBitmapData.AssignToBitmap(const aBitmap: TBitmap): Boolean;
7024 Row, RowSize: Integer;
7025 pSource, pData: PByte;
7028 if Assigned(Data) then begin
7029 if Assigned(aBitmap) then begin
7030 aBitmap.Width := Width;
7031 aBitmap.Height := Height;
7034 tfAlpha8ub1, tfLuminance8ub1: begin
7035 aBitmap.PixelFormat := pf8bit;
7036 aBitmap.Palette := CreateGrayPalette;
7039 aBitmap.PixelFormat := pf15bit;
7041 aBitmap.PixelFormat := pf16bit;
7042 tfRGB8ub3, tfBGR8ub3:
7043 aBitmap.PixelFormat := pf24bit;
7044 tfRGBA8ub4, tfBGRA8ub4:
7045 aBitmap.PixelFormat := pf32bit;
7047 raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.');
7050 RowSize := FormatDescriptor.GetSize(Width, 1);
7052 for Row := 0 to Height-1 do begin
7053 pData := aBitmap.Scanline[Row];
7054 Move(pSource^, pData^, RowSize);
7055 Inc(pSource, RowSize);
7056 if (Format in [tfRGB8ub3, tfRGBA8ub4]) then // swap RGB(A) to BGR(A)
7057 SwapRGB(pData, Width, Format = tfRGBA8ub4);
7064 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7065 function TglBitmapData.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
7067 pSource, pData, pTempData: PByte;
7068 Row, RowSize, TempWidth, TempHeight: Integer;
7069 IntFormat: TglBitmapFormat;
7073 if (Assigned(aBitmap)) then begin
7074 case aBitmap.PixelFormat of
7076 IntFormat := tfLuminance8ub1;
7078 IntFormat := tfRGB5A1us1;
7080 IntFormat := tfR5G6B5us1;
7082 IntFormat := tfBGR8ub3;
7084 IntFormat := tfBGRA8ub4;
7086 raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.');
7089 TempWidth := aBitmap.Width;
7090 TempHeight := aBitmap.Height;
7091 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
7092 GetMem(pData, TempHeight * RowSize);
7095 for Row := 0 to TempHeight -1 do begin
7096 pSource := aBitmap.Scanline[Row];
7097 if (Assigned(pSource)) then begin
7098 Move(pSource^, pTempData^, RowSize);
7099 Inc(pTempData, RowSize);
7102 SetData(pData, IntFormat, TempWidth, TempHeight);
7105 if Assigned(pData) then
7112 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7113 function TglBitmapData.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
7115 Row, Col, AlphaInterleave: Integer;
7116 pSource, pDest: PByte;
7120 if Assigned(Data) then begin
7121 if (Format in [tfAlpha8ub1, tfLuminance8Alpha8ub2, tfRGBA8ub4, tfBGRA8ub4]) then begin
7122 if Assigned(aBitmap) then begin
7123 aBitmap.PixelFormat := pf8bit;
7124 aBitmap.Palette := CreateGrayPalette;
7125 aBitmap.Width := Width;
7126 aBitmap.Height := Height;
7129 tfLuminance8Alpha8ub2:
7130 AlphaInterleave := 1;
7131 tfRGBA8ub4, tfBGRA8ub4:
7132 AlphaInterleave := 3;
7134 AlphaInterleave := 0;
7140 for Row := 0 to Height -1 do begin
7141 pDest := aBitmap.Scanline[Row];
7142 if Assigned(pDest) then begin
7143 for Col := 0 to Width -1 do begin
7144 Inc(pSource, AlphaInterleave);
7157 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7158 function TglBitmapData.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7160 data: TglBitmapData;
7162 data := TglBitmapData.Create;
7164 data.AssignFromBitmap(aBitmap);
7165 result := AddAlphaFromDataObj(data, aFunc, aArgs);
7172 {$IFDEF GLB_LAZARUS}
7173 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7174 function TglBitmapData.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
7176 rid: TRawImageDescription;
7177 FormatDesc: TFormatDescriptor;
7179 if not Assigned(Data) then
7180 raise EglBitmap.Create('no pixel data assigned. load data before save');
7183 if not Assigned(aImage) or (Format = tfEmpty) then
7185 FormatDesc := TFormatDescriptor.Get(Format);
7186 if FormatDesc.IsCompressed then
7189 FillChar(rid{%H-}, SizeOf(rid), 0);
7190 if FormatDesc.IsGrayscale then
7191 rid.Format := ricfGray
7193 rid.Format := ricfRGBA;
7196 rid.Height := Height;
7197 rid.Depth := FormatDesc.BitsPerPixel;
7198 rid.BitOrder := riboBitsInOrder;
7199 rid.ByteOrder := riboLSBFirst;
7200 rid.LineOrder := riloTopToBottom;
7201 rid.LineEnd := rileTight;
7202 rid.BitsPerPixel := FormatDesc.BitsPerPixel;
7203 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
7204 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
7205 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
7206 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
7207 rid.RedShift := FormatDesc.Shift.r;
7208 rid.GreenShift := FormatDesc.Shift.g;
7209 rid.BlueShift := FormatDesc.Shift.b;
7210 rid.AlphaShift := FormatDesc.Shift.a;
7212 rid.MaskBitsPerPixel := 0;
7213 rid.PaletteColorCount := 0;
7215 aImage.DataDescription := rid;
7218 if not Assigned(aImage.PixelData) then
7219 raise EglBitmap.Create('error while creating LazIntfImage');
7220 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
7225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7226 function TglBitmapData.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
7229 FormatDesc: TFormatDescriptor;
7233 Mask: TglBitmapRec4ul;
7235 procedure CopyConvert;
7237 bfFormat: TbmpBitfieldFormat;
7238 pSourceLine, pDestLine: PByte;
7239 pSourceMD, pDestMD: Pointer;
7240 Shift, Prec: TglBitmapRec4ub;
7242 pixel: TglBitmapPixelData;
7244 bfFormat := TbmpBitfieldFormat.Create;
7245 with aImage.DataDescription do begin
7247 Prec.g := GreenPrec;
7249 Prec.a := AlphaPrec;
7250 Shift.r := RedShift;
7251 Shift.g := GreenShift;
7252 Shift.b := BlueShift;
7253 Shift.a := AlphaShift;
7254 bfFormat.SetCustomValues(BitsPerPixel, Prec, Shift);
7256 pSourceMD := bfFormat.CreateMappingData;
7257 pDestMD := FormatDesc.CreateMappingData;
7259 for y := 0 to aImage.Height-1 do begin
7260 pSourceLine := aImage.PixelData + y {%H-}* aImage.DataDescription.BytesPerLine;
7261 pDestLine := ImageData + y * Round(FormatDesc.BytesPerPixel * aImage.Width);
7262 for x := 0 to aImage.Width-1 do begin
7263 bfFormat.Unmap(pSourceLine, pixel, pSourceMD);
7264 FormatDesc.Map(pixel, pDestLine, pDestMD);
7268 FormatDesc.FreeMappingData(pDestMD);
7269 bfFormat.FreeMappingData(pSourceMD);
7276 if not Assigned(aImage) then
7279 with aImage.DataDescription do begin
7280 Mask.r := (QWord(1 shl RedPrec )-1) shl RedShift;
7281 Mask.g := (QWord(1 shl GreenPrec)-1) shl GreenShift;
7282 Mask.b := (QWord(1 shl BluePrec )-1) shl BlueShift;
7283 Mask.a := (QWord(1 shl AlphaPrec)-1) shl AlphaShift;
7285 FormatDesc := TFormatDescriptor.GetFromMask(Mask);
7286 f := FormatDesc.Format;
7287 if (f = tfEmpty) then
7291 (FormatDesc.BitsPerPixel = aImage.DataDescription.Depth) and
7292 (aImage.DataDescription.BitsPerPixel = aImage.DataDescription.Depth);
7294 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
7295 ImageData := GetMem(ImageSize);
7298 Move(aImage.PixelData^, ImageData^, ImageSize)
7301 SetData(ImageData, f, aImage.Width, aImage.Height);
7303 if Assigned(ImageData) then
7311 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7312 function TglBitmapData.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
7314 rid: TRawImageDescription;
7315 FormatDesc: TFormatDescriptor;
7316 Pixel: TglBitmapPixelData;
7322 if not Assigned(aImage) or (Format = tfEmpty) then
7324 FormatDesc := TFormatDescriptor.Get(Format);
7325 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
7328 FillChar(rid{%H-}, SizeOf(rid), 0);
7329 rid.Format := ricfGray;
7331 rid.Height := Height;
7332 rid.Depth := CountSetBits(FormatDesc.Range.a);
7333 rid.BitOrder := riboBitsInOrder;
7334 rid.ByteOrder := riboLSBFirst;
7335 rid.LineOrder := riloTopToBottom;
7336 rid.LineEnd := rileTight;
7337 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
7338 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
7343 rid.GreenShift := 0;
7345 rid.AlphaShift := 0;
7347 rid.MaskBitsPerPixel := 0;
7348 rid.PaletteColorCount := 0;
7350 aImage.DataDescription := rid;
7353 srcMD := FormatDesc.CreateMappingData;
7355 FormatDesc.PreparePixel(Pixel);
7357 dst := aImage.PixelData;
7358 for y := 0 to Height-1 do
7359 for x := 0 to Width-1 do begin
7360 FormatDesc.Unmap(src, Pixel, srcMD);
7361 case rid.BitsPerPixel of
7363 dst^ := Pixel.Data.a;
7367 PWord(dst)^ := Pixel.Data.a;
7371 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
7372 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
7373 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
7377 PCardinal(dst)^ := Pixel.Data.a;
7381 raise EglBitmapUnsupportedFormat.Create(Format);
7385 FormatDesc.FreeMappingData(srcMD);
7390 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7391 function TglBitmapData.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7393 data: TglBitmapData;
7395 data := TglBitmapData.Create;
7397 data.AssignFromLazIntfImage(aImage);
7398 result := AddAlphaFromDataObj(data, aFunc, aArgs);
7405 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7406 function TglBitmapData.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
7407 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7409 rs: TResourceStream;
7411 PrepareResType(aResource, aResType);
7412 rs := TResourceStream.Create(aInstance, aResource, aResType);
7414 result := AddAlphaFromStream(rs, aFunc, aArgs);
7420 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7421 function TglBitmapData.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
7422 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7424 rs: TResourceStream;
7426 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
7428 result := AddAlphaFromStream(rs, aFunc, aArgs);
7434 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7435 function TglBitmapData.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7437 if TFormatDescriptor.Get(Format).IsCompressed then
7438 raise EglBitmapUnsupportedFormat.Create(Format);
7439 result := Convert(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
7442 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7443 function TglBitmapData.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7447 FS := TFileStream.Create(aFileName, fmOpenRead);
7449 result := AddAlphaFromStream(FS, aFunc, aArgs);
7455 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7456 function TglBitmapData.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7458 data: TglBitmapData;
7460 data := TglBitmapData.Create(aStream);
7462 result := AddAlphaFromDataObj(data, aFunc, aArgs);
7468 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7469 function TglBitmapData.AddAlphaFromDataObj(const aDataObj: TglBitmapData; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
7471 DestData, DestData2, SourceData: pByte;
7472 TempHeight, TempWidth: Integer;
7473 SourceFD, DestFD: TFormatDescriptor;
7474 SourceMD, DestMD, DestMD2: Pointer;
7476 FuncRec: TglBitmapFunctionRec;
7480 Assert(Assigned(Data));
7481 Assert(Assigned(aDataObj));
7482 Assert(Assigned(aDataObj.Data));
7484 if ((aDataObj.Width = Width) and (aDataObj.Height = Height)) then begin
7485 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
7487 SourceFD := TFormatDescriptor.Get(aDataObj.Format);
7488 DestFD := TFormatDescriptor.Get(Format);
7490 if not Assigned(aFunc) then begin
7491 aFunc := glBitmapAlphaFunc;
7492 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
7494 FuncRec.Args := aArgs;
7497 TempWidth := aDataObj.Width;
7498 TempHeight := aDataObj.Height;
7499 if (TempWidth <= 0) or (TempHeight <= 0) then
7502 FuncRec.Sender := Self;
7503 FuncRec.Size := Dimension;
7504 FuncRec.Position.Fields := FuncRec.Size.Fields;
7508 SourceData := aDataObj.Data;
7511 SourceFD.PreparePixel(FuncRec.Source);
7512 DestFD.PreparePixel (FuncRec.Dest);
7514 SourceMD := SourceFD.CreateMappingData;
7515 DestMD := DestFD.CreateMappingData;
7516 DestMD2 := DestFD.CreateMappingData;
7518 FuncRec.Position.Y := 0;
7519 while FuncRec.Position.Y < TempHeight do begin
7520 FuncRec.Position.X := 0;
7521 while FuncRec.Position.X < TempWidth do begin
7522 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
7523 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
7525 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
7526 inc(FuncRec.Position.X);
7528 inc(FuncRec.Position.Y);
7531 SourceFD.FreeMappingData(SourceMD);
7532 DestFD.FreeMappingData(DestMD);
7533 DestFD.FreeMappingData(DestMD2);
7538 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7539 function TglBitmapData.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
7541 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
7544 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7545 function TglBitmapData.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
7547 PixelData: TglBitmapPixelData;
7549 TFormatDescriptor.GetAlpha(Format).PreparePixel(PixelData);
7550 result := AddAlphaFromColorKeyFloat(
7551 aRed / PixelData.Range.r,
7552 aGreen / PixelData.Range.g,
7553 aBlue / PixelData.Range.b,
7554 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
7557 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7558 function TglBitmapData.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
7560 values: array[0..2] of Single;
7563 PixelData: TglBitmapPixelData;
7565 TFormatDescriptor.GetAlpha(Format).PreparePixel(PixelData);
7566 with PixelData do begin
7568 values[1] := aGreen;
7571 for i := 0 to 2 do begin
7572 tmp := Trunc(Range.arr[i] * aDeviation);
7573 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
7574 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
7579 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
7582 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7583 function TglBitmapData.AddAlphaFromValue(const aAlpha: Byte): Boolean;
7585 result := AddAlphaFromValueFloat(aAlpha / $FF);
7588 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7589 function TglBitmapData.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
7591 PixelData: TglBitmapPixelData;
7593 TFormatDescriptor.GetAlpha(Format).PreparePixel(PixelData);
7594 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
7597 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7598 function TglBitmapData.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
7600 PixelData: TglBitmapPixelData;
7602 TFormatDescriptor.GetAlpha(Format).PreparePixel(PixelData);
7604 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
7605 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
7608 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7609 function TglBitmapData.RemoveAlpha: Boolean;
7611 FormatDesc: TFormatDescriptor;
7614 FormatDesc := TFormatDescriptor.Get(Format);
7615 if Assigned(Data) then begin
7616 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
7617 raise EglBitmapUnsupportedFormat.Create(Format);
7618 result := ConvertTo(FormatDesc.WithoutAlpha);
7622 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7623 procedure TglBitmapData.FillWithColor(const aRed, aGreen, aBlue: Byte;
7624 const aAlpha: Byte);
7626 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
7629 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7630 procedure TglBitmapData.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
7632 PixelData: TglBitmapPixelData;
7634 TFormatDescriptor.GetAlpha(Format).PreparePixel(PixelData);
7636 aRed / PixelData.Range.r,
7637 aGreen / PixelData.Range.g,
7638 aBlue / PixelData.Range.b,
7639 aAlpha / PixelData.Range.a);
7642 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7643 procedure TglBitmapData.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
7645 PixelData: TglBitmapPixelData;
7647 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
7648 with PixelData do begin
7649 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
7650 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
7651 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
7652 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
7654 Convert(glBitmapFillWithColorFunc, false, @PixelData);
7657 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7658 procedure TglBitmapData.SetData(const aData: PByte; const aFormat: TglBitmapFormat; const aWidth: Integer; const aHeight: Integer);
7660 if (Data <> aData) then begin
7661 if (Assigned(Data)) then
7666 if Assigned(fData) then begin
7667 FillChar(fDimension, SizeOf(fDimension), 0);
7668 if aWidth <> -1 then begin
7669 fDimension.Fields := fDimension.Fields + [ffX];
7670 fDimension.X := aWidth;
7673 if aHeight <> -1 then begin
7674 fDimension.Fields := fDimension.Fields + [ffY];
7675 fDimension.Y := aHeight;
7685 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7686 function TglBitmapData.Clone: TglBitmapData;
7688 Temp: TglBitmapData;
7693 Temp := (ClassType.Create as TglBitmapData);
7695 // copy texture data if assigned
7696 if Assigned(Data) then begin
7697 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
7698 GetMem(TempPtr, Size);
7700 Move(Data^, TempPtr^, Size);
7701 Temp.SetData(TempPtr, Format, Width, Height);
7703 if Assigned(TempPtr) then
7709 Temp.SetData(TempPtr, Format, Width, Height);
7713 Temp.fFormat := Format;
7721 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7722 procedure TglBitmapData.Invert(const aRed, aGreen, aBlue, aAlpha: Boolean);
7727 (Byte(aRed) and 1) or
7728 ((Byte(aGreen) and 1) shl 1) or
7729 ((Byte(aBlue) and 1) shl 2) or
7730 ((Byte(aAlpha) and 1) shl 3);
7732 Convert(glBitmapInvertFunc, false, {%H-}Pointer(mask));
7735 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7737 TMatrixItem = record
7742 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
7743 TglBitmapToNormalMapRec = Record
7745 Heights: array of Single;
7746 MatrixU : array of TMatrixItem;
7747 MatrixV : array of TMatrixItem;
7751 ONE_OVER_255 = 1 / 255;
7753 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7754 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
7758 with FuncRec do begin
7760 Source.Data.r * LUMINANCE_WEIGHT_R +
7761 Source.Data.g * LUMINANCE_WEIGHT_G +
7762 Source.Data.b * LUMINANCE_WEIGHT_B;
7763 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
7767 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7768 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
7771 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
7774 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7775 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
7777 TVec = Array[0..2] of Single;
7784 function GetHeight(X, Y: Integer): Single;
7786 with FuncRec do begin
7787 X := Max(0, Min(Size.X -1, X));
7788 Y := Max(0, Min(Size.Y -1, Y));
7789 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
7794 with FuncRec do begin
7795 with PglBitmapToNormalMapRec(Args)^ do begin
7797 for Idx := Low(MatrixU) to High(MatrixU) do
7798 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
7801 for Idx := Low(MatrixU) to High(MatrixU) do
7802 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
7804 Vec[0] := -du * Scale;
7805 Vec[1] := -dv * Scale;
7810 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
7811 if Len <> 0 then begin
7812 Vec[0] := Vec[0] * Len;
7813 Vec[1] := Vec[1] * Len;
7814 Vec[2] := Vec[2] * Len;
7818 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
7819 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
7820 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
7824 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7825 procedure TglBitmapData.GenerateNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
7827 Rec: TglBitmapToNormalMapRec;
7829 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
7831 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
7832 Matrix[Index].X := X;
7833 Matrix[Index].Y := Y;
7834 Matrix[Index].W := W;
7839 if TFormatDescriptor.Get(Format).IsCompressed then
7840 raise EglBitmapUnsupportedFormat.Create(Format);
7842 if aScale > 100 then
7844 else if aScale < -100 then
7847 Rec.Scale := aScale;
7849 SetLength(Rec.Heights, Width * Height);
7853 SetLength(Rec.MatrixU, 2);
7854 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
7855 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
7857 SetLength(Rec.MatrixV, 2);
7858 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
7859 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
7863 SetLength(Rec.MatrixU, 6);
7864 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
7865 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
7866 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
7867 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
7868 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
7869 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
7871 SetLength(Rec.MatrixV, 6);
7872 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
7873 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
7874 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
7875 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
7876 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
7877 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
7881 SetLength(Rec.MatrixU, 6);
7882 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
7883 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
7884 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
7885 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
7886 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
7887 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
7889 SetLength(Rec.MatrixV, 6);
7890 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
7891 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
7892 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
7893 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
7894 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
7895 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
7899 SetLength(Rec.MatrixU, 20);
7900 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
7901 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
7902 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
7903 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
7904 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
7905 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
7906 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
7907 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
7908 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
7909 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
7910 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
7911 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
7912 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
7913 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
7914 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
7915 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
7916 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
7917 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
7918 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
7919 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
7921 SetLength(Rec.MatrixV, 20);
7922 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
7923 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
7924 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
7925 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
7926 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
7927 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
7928 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
7929 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
7930 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
7931 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
7932 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
7933 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
7934 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
7935 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
7936 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
7937 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
7938 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
7939 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
7940 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
7941 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
7946 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
7947 Convert(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
7949 Convert(glBitmapToNormalMapPrepareFunc, false, @Rec);
7950 Convert(glBitmapToNormalMapFunc, false, @Rec);
7952 SetLength(Rec.Heights, 0);
7956 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7957 constructor TglBitmapData.Create;
7960 fFormat := glBitmapDefaultFormat;
7963 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7964 constructor TglBitmapData.Create(const aFileName: String);
7967 LoadFromFile(aFileName);
7970 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7971 constructor TglBitmapData.Create(const aStream: TStream);
7974 LoadFromStream(aStream);
7977 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7978 constructor TglBitmapData.Create(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat; aData: PByte);
7983 if not Assigned(aData) then begin
7984 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
7985 GetMem(aData, ImageSize);
7987 FillChar(aData^, ImageSize, #$FF);
7988 SetData(aData, aFormat, aSize.X, aSize.Y);
7990 if Assigned(aData) then
7995 SetData(aData, aFormat, aSize.X, aSize.Y);
7999 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8000 constructor TglBitmapData.Create(const aSize: TglBitmapSize; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer);
8003 LoadFromFunc(aSize, aFormat, aFunc, aArgs);
8006 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8007 constructor TglBitmapData.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
8010 LoadFromResource(aInstance, aResource, aResType);
8013 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8014 constructor TglBitmapData.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
8017 LoadFromResourceID(aInstance, aResourceID, aResType);
8020 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8021 destructor TglBitmapData.Destroy;
8023 SetData(nil, tfEmpty);
8027 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8028 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8029 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8030 function TglBitmap.GetWidth: Integer;
8032 if (ffX in fDimension.Fields) then
8033 result := fDimension.X
8038 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8039 function TglBitmap.GetHeight: Integer;
8041 if (ffY in fDimension.Fields) then
8042 result := fDimension.Y
8047 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8048 procedure TglBitmap.SetCustomData(const aValue: Pointer);
8050 if fCustomData = aValue then
8052 fCustomData := aValue;
8055 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8056 procedure TglBitmap.SetCustomName(const aValue: String);
8058 if fCustomName = aValue then
8060 fCustomName := aValue;
8063 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8064 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
8066 if fCustomNameW = aValue then
8068 fCustomNameW := aValue;
8071 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8072 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
8074 if fDeleteTextureOnFree = aValue then
8076 fDeleteTextureOnFree := aValue;
8079 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8080 procedure TglBitmap.SetID(const aValue: Cardinal);
8082 if fID = aValue then
8087 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8088 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
8090 if fMipMap = aValue then
8095 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8096 procedure TglBitmap.SetTarget(const aValue: Cardinal);
8098 if fTarget = aValue then
8103 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8104 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
8105 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_EXT)}
8107 MaxAnisotropic: Integer;
8110 fAnisotropic := aValue;
8111 if (ID > 0) then begin
8112 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_EXT)}
8113 if GL_EXT_texture_filter_anisotropic then begin
8114 if fAnisotropic > 0 then begin
8116 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
8117 if aValue > MaxAnisotropic then
8118 fAnisotropic := MaxAnisotropic;
8119 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
8130 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8131 procedure TglBitmap.CreateID;
8134 glDeleteTextures(1, @fID);
8135 glGenTextures(1, @fID);
8139 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8140 procedure TglBitmap.SetupParameters({$IFNDEF OPENGL_ES}out aBuildWithGlu: Boolean{$ENDIF});
8142 // Set Up Parameters
8143 SetWrap(fWrapS, fWrapT, fWrapR);
8144 SetFilter(fFilterMin, fFilterMag);
8145 SetAnisotropic(fAnisotropic);
8148 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
8149 if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
8150 SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
8154 // Mip Maps Generation Mode
8155 aBuildWithGlu := false;
8156 if (MipMap = mmMipmap) then begin
8157 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
8158 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
8160 aBuildWithGlu := true;
8161 end else if (MipMap = mmMipmapGlu) then
8162 aBuildWithGlu := true;
8164 if (MipMap = mmMipmap) then
8165 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE);
8169 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8170 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8171 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8172 procedure TglBitmap.AfterConstruction;
8174 inherited AfterConstruction;
8179 fIsResident := false;
8182 fMipMap := glBitmapDefaultMipmap;
8183 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
8185 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
8186 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
8188 glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
8192 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8193 procedure TglBitmap.BeforeDestruction;
8195 if (fID > 0) and fDeleteTextureOnFree then
8196 glDeleteTextures(1, @fID);
8197 inherited BeforeDestruction;
8201 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8202 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
8204 fBorderColor[0] := aRed;
8205 fBorderColor[1] := aGreen;
8206 fBorderColor[2] := aBlue;
8207 fBorderColor[3] := aAlpha;
8208 if (ID > 0) then begin
8210 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
8215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8216 procedure TglBitmap.SetFilter(const aMin, aMag: GLenum);
8221 fFilterMin := GL_NEAREST;
8223 fFilterMin := GL_LINEAR;
8224 GL_NEAREST_MIPMAP_NEAREST:
8225 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
8226 GL_LINEAR_MIPMAP_NEAREST:
8227 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
8228 GL_NEAREST_MIPMAP_LINEAR:
8229 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
8230 GL_LINEAR_MIPMAP_LINEAR:
8231 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
8233 raise EglBitmap.Create('SetFilter - Unknow MIN filter.');
8239 fFilterMag := GL_NEAREST;
8241 fFilterMag := GL_LINEAR;
8243 raise EglBitmap.Create('SetFilter - Unknow MAG filter.');
8247 if (ID > 0) then begin
8249 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
8251 if (MipMap = mmNone) {$IFNDEF OPENGL_ES}or (Target = GL_TEXTURE_RECTANGLE){$ENDIF} then begin
8253 GL_NEAREST, GL_LINEAR:
8254 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
8255 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
8256 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8257 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
8258 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8261 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
8265 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8266 procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum);
8268 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
8273 aTarget := GL_CLAMP;
8277 aTarget := GL_REPEAT;
8279 GL_CLAMP_TO_EDGE: begin
8281 if not GL_VERSION_1_2 and not GL_EXT_texture_edge_clamp then
8285 aTarget := GL_CLAMP_TO_EDGE;
8289 GL_CLAMP_TO_BORDER: begin
8290 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
8291 aTarget := GL_CLAMP_TO_BORDER
8293 aTarget := GL_CLAMP;
8297 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
8298 GL_MIRRORED_REPEAT: begin
8300 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
8302 if GL_VERSION_2_0 then
8304 aTarget := GL_MIRRORED_REPEAT
8306 raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
8310 raise EglBitmap.Create('SetWrap - Unknow Texturewrap');
8315 CheckAndSetWrap(S, fWrapS);
8316 CheckAndSetWrap(T, fWrapT);
8317 CheckAndSetWrap(R, fWrapR);
8319 if (ID > 0) then begin
8321 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
8322 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
8323 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
8324 {$IFDEF OPENGL_ES} if GL_VERSION_3_0 then{$ENDIF}
8325 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
8330 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
8331 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8332 procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum);
8334 procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer);
8336 if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or
8337 (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then
8338 fSwizzle[aIndex] := aValue
8340 raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value');
8345 if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
8346 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
8348 if not GL_VERSION_3_0 then
8349 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
8351 CheckAndSetValue(r, 0);
8352 CheckAndSetValue(g, 1);
8353 CheckAndSetValue(b, 2);
8354 CheckAndSetValue(a, 3);
8356 if (ID > 0) then begin
8359 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, PGLint(@fSwizzle[0]));
8361 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_R, PGLint(@fSwizzle[0]));
8362 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_G, PGLint(@fSwizzle[1]));
8363 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_B, PGLint(@fSwizzle[2]));
8364 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_A, PGLint(@fSwizzle[3]));
8370 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8371 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
8373 if aEnableTextureUnit then
8376 glBindTexture(Target, ID);
8379 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8380 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
8382 if aDisableTextureUnit then
8384 glBindTexture(Target, 0);
8387 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8388 procedure TglBitmap.UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean);
8392 w := aDataObj.Width;
8393 h := aDataObj.Height;
8394 fDimension.Fields := [];
8396 fDimension.Fields := fDimension.Fields + [ffX];
8398 fDimension.Fields := fDimension.Fields + [ffY];
8404 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8405 function TglBitmap.DownloadData(const aDataObj: TglBitmapData): Boolean;
8408 TempWidth, TempHeight: Integer;
8409 TempIntFormat: GLint;
8410 IntFormat: TglBitmapFormat;
8411 FormatDesc: TFormatDescriptor;
8417 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
8418 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
8419 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
8421 FormatDesc := (TglBitmapFormatDescriptor.GetByFormat(TempIntFormat) as TFormatDescriptor);
8422 IntFormat := FormatDesc.Format;
8424 // Getting data from OpenGL
8425 FormatDesc := TFormatDescriptor.Get(IntFormat);
8426 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
8428 if FormatDesc.IsCompressed then begin
8429 if not Assigned(glGetCompressedTexImage) then
8430 raise EglBitmap.Create('compressed formats not supported by video adapter');
8431 glGetCompressedTexImage(Target, 0, Temp)
8433 glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8434 aDataObj.SetData(Temp, IntFormat, TempWidth, TempHeight);
8437 if Assigned(Temp) then
8444 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8445 constructor TglBitmap.Create;
8447 if (ClassType = TglBitmap) then
8448 raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
8452 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8453 constructor TglBitmap.Create(const aData: TglBitmapData);
8460 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8461 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8462 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8463 procedure TglBitmap1D.UploadDataIntern(const aDataObj: TglBitmapData; const aBuildWithGlu: Boolean);
8465 fd: TglBitmapFormatDescriptor;
8468 fd := aDataObj.FormatDescriptor;
8469 if (fd.glFormat = 0) or (fd.glInternalFormat = 0) or (fd.glDataFormat = 0) then
8470 raise EglBitmap.Create('format is not supported by video adapter, please convert before uploading data');
8472 if fd.IsCompressed then begin
8473 if not Assigned(glCompressedTexImage1D) then
8474 raise EglBitmap.Create('compressed formats not supported by video adapter');
8475 glCompressedTexImage1D(Target, 0, fd.glInternalFormat, aDataObj.Width, 0, fd.GetSize(aDataObj.Width, 1), aDataObj.Data)
8476 end else if aBuildWithGlu then
8477 gluBuild1DMipmaps(Target, fd.glInternalFormat, aDataObj.Width, fd.glFormat, fd.glDataFormat, aDataObj.Data)
8479 glTexImage1D(Target, 0, fd.glInternalFormat, aDataObj.Width, 0, fd.glFormat, fd.glDataFormat, aDataObj.Data);
8482 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8483 procedure TglBitmap1D.AfterConstruction;
8486 Target := GL_TEXTURE_1D;
8489 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8490 procedure TglBitmap1D.UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean);
8492 BuildWithGlu, TexRec: Boolean;
8495 if not Assigned(aDataObj) then
8498 // Check Texture Size
8499 if (aCheckSize) then begin
8500 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8502 if (aDataObj.Width > TexSize) then
8503 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8505 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
8506 (Target = GL_TEXTURE_RECTANGLE);
8507 if not (IsPowerOfTwo(aDataObj.Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8508 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8513 SetupParameters(BuildWithGlu);
8514 UploadDataIntern(aDataObj, BuildWithGlu);
8515 glAreTexturesResident(1, @fID, @fIsResident);
8517 inherited UploadData(aDataObj, aCheckSize);
8521 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8522 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8523 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8524 procedure TglBitmap2D.UploadDataIntern(const aDataObj: TglBitmapData; const aTarget: GLenum; const aBuildWithGlu: Boolean);
8526 fd: TglBitmapFormatDescriptor;
8528 fd := aDataObj.FormatDescriptor;
8529 if (fd.glFormat = 0) or (fd.glInternalFormat = 0) or (fd.glDataFormat = 0) then
8530 raise EglBitmap.Create('format is not supported by video adapter, please convert before uploading data');
8532 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
8534 if fd.IsCompressed then begin
8535 if not Assigned(glCompressedTexImage2D) then
8536 raise EglBitmap.Create('compressed formats not supported by video adapter');
8537 glCompressedTexImage2D(aTarget, 0, fd.glInternalFormat, aDataObj.Width, aDataObj.Height, 0, fd.GetSize(fDimension), aDataObj.Data)
8539 end else if aBuildWithGlu then begin
8540 gluBuild2DMipmaps(aTarget, fd.ChannelCount, aDataObj.Width, aDataObj.Height, fd.glFormat, fd.glDataFormat, aDataObj.Data)
8543 glTexImage2D(aTarget, 0, fd.glInternalFormat, aDataObj.Width, aDataObj.Height, 0, fd.glFormat, fd.glDataFormat, aDataObj.Data);
8547 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8548 procedure TglBitmap2D.AfterConstruction;
8551 Target := GL_TEXTURE_2D;
8554 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8555 procedure TglBitmap2D.UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean);
8558 BuildWithGlu, TexRec: Boolean;
8563 if not Assigned(aDataObj) then
8566 // Check Texture Size
8567 if (aCheckSize) then begin
8568 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8570 if ((aDataObj.Width > TexSize) or (aDataObj.Height > TexSize)) then
8571 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8573 PotTex := IsPowerOfTwo(aDataObj.Width) and IsPowerOfTwo(aDataObj.Height);
8574 {$IF NOT DEFINED(OPENGL_ES)}
8575 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
8576 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8577 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8578 {$ELSEIF DEFINED(OPENGL_ES_EXT)}
8579 if not PotTex and not GL_OES_texture_npot then
8580 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8583 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8589 SetupParameters({$IFNDEF OPENGL_ES}BuildWithGlu{$ENDIF});
8590 UploadDataIntern(aDataObj, Target{$IFNDEF OPENGL_ES}, BuildWithGlu{$ENDIF});
8592 glAreTexturesResident(1, @fID, @fIsResident);
8595 inherited UploadData(aDataObj, aCheckSize);
8598 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8599 class procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat; const aDataObj: TglBitmapData);
8602 Size, w, h: Integer;
8603 FormatDesc: TFormatDescriptor;
8605 FormatDesc := TFormatDescriptor.Get(aFormat);
8606 if FormatDesc.IsCompressed then
8607 raise EglBitmapUnsupportedFormat.Create(aFormat);
8609 w := aRight - aLeft;
8610 h := aBottom - aTop;
8611 Size := FormatDesc.GetSize(w, h);
8614 glPixelStorei(GL_PACK_ALIGNMENT, 1);
8615 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8616 aDataObj.SetData(Temp, aFormat, w, h);
8619 if Assigned(Temp) then
8625 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
8626 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8627 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8628 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8629 procedure TglBitmapCubeMap.AfterConstruction;
8634 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8635 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8637 if not (GL_VERSION_2_0) then
8638 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8642 Target := GL_TEXTURE_CUBE_MAP;
8644 fGenMode := GL_REFLECTION_MAP;
8648 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8649 procedure TglBitmapCubeMap.UploadData(const aDataObj: TglBitmapData; const aCheckSize: Boolean);
8651 Assert(false, 'TglBitmapCubeMap.UploadData - Don''t call UploadData directly, use UploadCubeMap instead');
8654 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8655 procedure TglBitmapCubeMap.UploadCubeMap(const aDataObj: TglBitmapData; const aCubeTarget: Cardinal; const aCheckSize: Boolean);
8658 BuildWithGlu: Boolean;
8662 if (aCheckSize) then begin
8663 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8665 if (aDataObj.Width > TexSize) or (aDataObj.Height > TexSize) then
8666 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenerateCubeMap - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8668 {$IF NOT DEFINED(OPENGL_ES)}
8669 if not ((IsPowerOfTwo(aDataObj.Width) and IsPowerOfTwo(aDataObj.Height)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8670 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenerateCubeMap - Cubemaps dosn''t support non power of two texture.');
8671 {$ELSEIF DEFINED(OPENGL_ES_EXT)}
8672 if not (IsPowerOfTwo(aDataObj.Width) and IsPowerOfTwo(aDataObj.Height)) and not GL_OES_texture_npot then
8673 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenerateCubeMap - Cubemaps dosn''t support non power of two texture.');
8675 if not (IsPowerOfTwo(aDataObj.Width) and IsPowerOfTwo(aDataObj.Height)) then
8676 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenerateCubeMap - Cubemaps dosn''t support non power of two texture.');
8682 SetupParameters({$IFNDEF OPENGL_ES}BuildWithGlu{$ENDIF});
8683 UploadDataIntern(aDataObj, aCubeTarget{$IFNDEF OPENGL_ES}, BuildWithGlu{$ENDIF});
8685 inherited UploadData(aDataObj, aCheckSize);
8688 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8689 procedure TglBitmapCubeMap.Bind({$IFNDEF OPENGL_ES}const aEnableTexCoordsGen: Boolean;{$ENDIF} const aEnableTextureUnit: Boolean);
8691 inherited Bind (aEnableTextureUnit);
8693 if aEnableTexCoordsGen then begin
8694 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8695 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8696 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8697 glEnable(GL_TEXTURE_GEN_S);
8698 glEnable(GL_TEXTURE_GEN_T);
8699 glEnable(GL_TEXTURE_GEN_R);
8704 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8705 procedure TglBitmapCubeMap.Unbind({$IFNDEF OPENGL_ES}const aDisableTexCoordsGen: Boolean;{$ENDIF} const aDisableTextureUnit: Boolean);
8707 inherited Unbind(aDisableTextureUnit);
8709 if aDisableTexCoordsGen then begin
8710 glDisable(GL_TEXTURE_GEN_S);
8711 glDisable(GL_TEXTURE_GEN_T);
8712 glDisable(GL_TEXTURE_GEN_R);
8718 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_2_0)}
8719 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8720 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8721 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8723 TVec = Array[0..2] of Single;
8724 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8726 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8727 TglBitmapNormalMapRec = record
8729 Func: TglBitmapNormalMapGetVectorFunc;
8732 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8733 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8735 aVec[0] := aHalfSize;
8736 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8737 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8740 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8741 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8743 aVec[0] := - aHalfSize;
8744 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8745 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8748 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8749 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8751 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8752 aVec[1] := aHalfSize;
8753 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8756 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8757 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8759 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8760 aVec[1] := - aHalfSize;
8761 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8764 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8765 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8767 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8768 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8769 aVec[2] := aHalfSize;
8772 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8773 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8775 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8776 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8777 aVec[2] := - aHalfSize;
8780 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8781 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8787 with FuncRec do begin
8788 with PglBitmapNormalMapRec(Args)^ do begin
8789 Func(Vec, Position, HalfSize);
8792 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8793 if Len <> 0 then begin
8794 Vec[0] := Vec[0] * Len;
8795 Vec[1] := Vec[1] * Len;
8796 Vec[2] := Vec[2] * Len;
8799 // Scale Vector and AddVectro
8800 Vec[0] := Vec[0] * 0.5 + 0.5;
8801 Vec[1] := Vec[1] * 0.5 + 0.5;
8802 Vec[2] := Vec[2] * 0.5 + 0.5;
8807 Dest.Data.arr[i] := Round(Vec[i] * 255);
8811 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8812 procedure TglBitmapNormalMap.AfterConstruction;
8816 fGenMode := GL_NORMAL_MAP;
8820 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8821 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aCheckSize: Boolean);
8823 Rec: TglBitmapNormalMapRec;
8824 SizeRec: TglBitmapSize;
8825 DataObj: TglBitmapData;
8827 Rec.HalfSize := aSize div 2;
8829 SizeRec.Fields := [ffX, ffY];
8833 DataObj := TglBitmapData.Create;
8836 Rec.Func := glBitmapNormalMapPosX;
8837 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8838 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_POSITIVE_X, aCheckSize);
8841 Rec.Func := glBitmapNormalMapNegX;
8842 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8843 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aCheckSize);
8846 Rec.Func := glBitmapNormalMapPosY;
8847 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8848 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aCheckSize);
8851 Rec.Func := glBitmapNormalMapNegY;
8852 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8853 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aCheckSize);
8856 Rec.Func := glBitmapNormalMapPosZ;
8857 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8858 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aCheckSize);
8861 Rec.Func := glBitmapNormalMapNegZ;
8862 DataObj.LoadFromFunc(SizeRec, tfBGR8ub3, glBitmapNormalMapFunc, @Rec);
8863 UploadCubeMap(DataObj, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aCheckSize);
8865 FreeAndNil(DataObj);
8871 glBitmapSetDefaultFormat (tfEmpty);
8872 glBitmapSetDefaultMipmap (mmMipmap);
8873 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8874 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8875 {$IF NOT DEFINED(OPENGL_ES) OR DEFINED(OPENGL_ES_3_0)}
8876 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8879 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8880 glBitmapSetDefaultDeleteTextureOnFree (true);
8882 TFormatDescriptor.Init;
8885 TFormatDescriptor.Finalize;