1 {***********************************************************
2 glBitmap by Steffen Xonna aka Lossy eX (2003-2008)
3 http://www.opengl24.de/index.php?cat=header&file=glbitmap
4 ------------------------------------------------------------
5 The contents of this file are used with permission, subject to
6 the Mozilla Public License Version 1.1 (the "License"); you may
7 not use this file except in compliance with the License. You may
8 obtain a copy of the License at
9 http://www.mozilla.org/MPL/MPL-1.1.html
10 ------------------------------------------------------------
12 ------------------------------------------------------------
15 - The define GLB_DELPHI dosn't check versions anymore. If you say you are using delphi
16 then it's your problem if that isn't true. This prevents the unit for incompatibility
17 with newer versions of Delphi.
18 - Problems with D2009+ resolved (Thanks noeska and all i forgot)
19 - GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson)
21 - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson)
22 - Additional Datapointer for functioninterface now has the name CustomData
24 - AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson)
25 - If you load an texture from an file the property Filename will be set to the name of the file
26 - Three new properties to attach custom data to the Texture objects
27 - CustomName (free for use string)
28 - CustomNameW (free for use widestring)
29 - CustomDataPointer (free for use pointer to attach other objects or complex structures)
31 - RLE TGAs loaded much faster
33 - fixed some problem with reading RLE TGAs.
35 - function clone now only copys data if it's assigned and now it also copies the ID
36 - it seems that lazarus dont like comments in comments.
38 - It's possible to set the id of the texture
39 - define GLB_NO_NATIVE_GL deactivated by default
41 - Now supports the following libraries
45 - Linux compatibillity via free pascal compatibility (delphi sources optional)
46 - BMPs now loaded manuel
48 - Property DataPtr now has the name Data
49 - Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR
50 - Unused Depth removed
51 - Function FreeData to freeing image data added
53 - ImageID flag of TGAs was ignored. (Thanks Zwoetzen)
55 - Function SetBorderColor implemented (only used by opengl if wrap is set to GL_CLAMP_TO_BORDER)
56 - Function AddAlphaFromValue implemented to use an fixed Value as Alphachannel
57 - Function ReadOpenGLExtension is now only intern
59 - pngimage now disabled by default like all other versions.
61 - Setting up an anisotropic filter of 0 isnt allowed by nvidia (Thanks Ogridi)
63 - Fixed some Problem with Delphi 5
64 - Now uses the newest version of pngimage. Makes saving pngs much easier.
66 - Property IsCompressed and Size removed. Not really supported by Spec (Thanks Ogridi)
68 - Internal Format ifDepth8 added
69 - function GrabScreen now supports all uncompressed formats
71 - AddAlphaFromglBitmap implemented
73 - LoadFromResource and LoadFromResourceId now needs an Instance and an ResourceType (for ID)
75 - Width, Height and Depth internal changed to TglBitmapPixelPosition.
76 property Width, Height, Depth are still existing and new property Dimension are avail
78 - Added native OpenGL Support. Breaking the dglOpenGL "barrier".
80 - Added function GrabScreen to class TglBitmap2D
82 - Added support to Save images
83 - Added function Clone to Clone Instance
85 - Functions now works with Cardinals for each channel. Up to 32 Bits per channel.
87 - Several speed optimizations
89 - Internal structure change. Loading of TGA, PNG and DDS improved.
90 Data, format and size will now set directly with SetDataPtr.
91 - AddFunc now works with all Types of Images and Formats
92 - Some Funtions moved to Baseclass TglBitmap
94 - Added Support to decompress DXT3 and DXT5 compressed Images.
95 - Added Mapping to convert data from one format into an other.
97 - Added method ConvertTo in Class TglBitmap2D. Method allows to convert every
98 supported Input format (supported by GetPixel) into any uncompresed Format
99 - Added Support to decompress DXT1 compressed Images.
100 - SwapColors replaced by ConvertTo
102 - Added Support for compressed DDSs
103 - Added new internal formats (DXT1, DXT3, DXT5)
105 - Parameter Components renamed to InternalFormat
107 - Some AllocMem replaced with GetMem (little speed change)
108 - better exception handling. Better protection from memory leaks.
110 - Added support for Direct Draw Surfaces (.DDS) (uncompressed images only)
111 - Added new internal formats (RGB8, RGBA8, RGBA4, RGB5A1, RGB10A2, R5G6B5)
113 - Added support for Grayscale textures
114 - Added internal formats (Alpha, Luminance, LuminanceAlpha, BGR8, BGRA8)
116 - Added support for GL_VERSION_2_0
117 - Added support for GL_EXT_texture_filter_anisotropic
119 - Function FillWithColor fills the Image with one Color
120 - Function LoadNormalMap added
122 - ToNormalMap allows to Create an NormalMap from the Alphachannel
123 - ToNormalMap now supports Sobel (nmSobel) function.
125 - support for RLE Compressed RGB TGAs added
127 - Class TglBitmapNormalMap added to support Normalmap generation
128 - Added function ToNormalMap in class TglBitmap2D to genereate normal maps from textures.
129 3 Filters are supported. (4 Samples, 3x3 and 5x5)
131 - Method LoadCubeMapClass removed
132 - LoadCubeMap returnvalue is now the Texture paramter. Such as LoadTextures
133 - virtual abstract method GenTexture in class TglBitmap now is protected
135 - now support DescriptionFlag in LoadTga. Allows vertical flipped images to be loaded as normal
137 - little enhancement for IsPowerOfTwo
138 - TglBitmap1D.GenTexture now tests NPOT Textures
140 - some little name changes. All properties or function with Texture in name are
141 now without texture in name. We have allways texture so we dosn't name it.
143 - GenTexture now tests if texture is NPOT and NPOT-Texture are supported or
144 TextureTarget is GL_TEXTURE_RECTANGLE. Else it raised an exception.
146 - added support for GL_ARB_texture_rectangle, GL_EXT_texture_rectangle and GL_NV_texture_rectangle
148 - Function Unbind added
149 - call of SetFilter or SetTextureWrap if TextureID exists results in setting properties to opengl texture.
151 - class TglBitmapCubeMap added (allows to Create Cubemaps)
153 - Added Support for PNG Images. (http://pngdelphi.sourceforge.net/)
154 To Enable png's use the define pngimage
156 - New Functioninterface added
157 - Function GetPixel added
159 - Property BuildMipMaps renamed to MipMap
161 - property Name removed.
162 - BuildMipMaps is now a set of 3 values. None, GluBuildMipmaps and SGIS_generate_mipmap
164 - property name added. Only used in glForms!
166 - property FreeDataAfterGenTexture is now available as default (default = true)
167 - BuildMipmaps now implemented in TglBitmap1D (i've forgotten it)
168 - function MoveMemory replaced with function Move (little speed change)
169 - several calculations stored in variables (little speed change)
171 - property BuildMipsMaps added (default = true)
172 if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps
173 - property FreeDataAfterGenTexture added (default = true)
174 if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated.
175 - parameter DisableOtherTextureUnits of Bind removed
176 - parameter FreeDataAfterGeneration of GenTextures removed
178 - TglBitmap dosn't delete data if class was destroyed (fixed)
180 - Bind now enables TextureUnits (by params)
181 - GenTextures can leave data (by param)
182 - LoadTextures now optimal
184 - Performance optimization in AddFunc
185 - procedure Bind moved to subclasses
186 - Added new Class TglBitmap1D to support real OpenGL 1D Textures
188 - Texturefilter and texturewrap now also as defaults
189 Minfilter = GL_LINEAR_MIPMAP_LINEAR
190 Magfilter = GL_LINEAR
191 Wrap(str) = GL_CLAMP_TO_EDGE
192 - Added new format tfCompressed to create a compressed texture.
193 - propertys IsCompressed, TextureSize and IsResident added
194 IsCompressed and TextureSize only contains data from level 0
196 - Added function AddFunc to add PerPixelEffects to Image
197 - LoadFromFunc now based on AddFunc
198 - Invert now based on AddFunc
199 - SwapColors now based on AddFunc
201 - Added function FlipHorz
203 - Added function LaodFromFunc to create images with function
204 - Added function FlipVert
205 - Added internal format RGB(A) if GL_EXT_bgra or OpenGL 1.2 isn't supported
207 - Added Alphafunctions to calculate alpha per function
208 - Added Alpha from ColorKey using alphafunctions
210 - First full functionally Version of glBitmap
211 - Support for 24Bit and 32Bit TGA Pictures added
213 - begin of programming
214 ***********************************************************}
217 {.$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
218 // Please uncomment the defines below to configure the glBitmap to your preferences.
219 // If you have configured the unit you can uncomment the warning above.
221 // ###### Start of preferences ################################################
223 {$DEFINE GLB_NO_NATIVE_GL}
224 // To enable the dglOpenGL.pas Header
225 // With native GL then bindings are staticlly declared to support other headers
226 // or use the glBitmap inside of DLLs (minimize codesize).
230 // To enable the support for SDL_surfaces
232 {.$DEFINE GLB_DELPHI}
233 // To enable the support for TBitmap from Delphi (not lazarus)
236 // *** image libs ***
238 {.$DEFINE GLB_SDL_IMAGE}
239 // To enable the support of SDL_image to load files. (READ ONLY)
240 // If you enable SDL_image all other libraries will be ignored!
243 {.$DEFINE GLB_PNGIMAGE}
244 // to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/
245 // if you enable pngimage the libPNG will be ignored
247 {.$DEFINE GLB_LIB_PNG}
248 // to use the libPNG http://www.libpng.org/
249 // You will need an aditional header.
250 // http://www.opengl24.de/index.php?cat=header&file=libpng
252 {.$DEFINE GLB_DELPHI_JPEG}
253 // if you enable delphi jpegs the libJPEG will be ignored
255 {.$DEFINE GLB_LIB_JPEG}
256 // to use the libJPEG http://www.ijg.org/
257 // You will need an aditional header.
258 // http://www.opengl24.de/index.php?cat=header&file=libjpeg
260 // ###### End of preferences ##################################################
263 // ###### PRIVATE. Do not change anything. ####################################
264 // *** old defines for compatibility ***
265 {$IFDEF NO_NATIVE_GL}
266 {$DEFINE GLB_NO_NATIVE_GL}
269 {$definde GLB_PNGIMAGE}
272 // *** Delphi Versions ***
286 // *** checking define combinations ***
287 {$IFDEF GLB_SDL_IMAGE}
289 {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
292 {$IFDEF GLB_PNGIMAGE}
293 {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
294 {$undef GLB_PNGIMAGE}
296 {$IFDEF GLB_DELPHI_JPEG}
297 {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
298 {$undef GLB_DELPHI_JPEG}
301 {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
304 {$IFDEF GLB_LIB_JPEG}
305 {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
306 {$undef GLB_LIB_JPEG}
309 {$DEFINE GLB_SUPPORT_PNG_READ}
310 {$DEFINE GLB_SUPPORT_JPEG_READ}
313 {$IFDEF GLB_PNGIMAGE}
315 {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'}
319 {$DEFINE GLB_SUPPORT_PNG_READ}
320 {$DEFINE GLB_SUPPORT_PNG_WRITE}
324 {$DEFINE GLB_SUPPORT_PNG_READ}
325 {$DEFINE GLB_SUPPORT_PNG_WRITE}
328 {$IFDEF GLB_DELPHI_JPEG}
329 {$IFDEF GLB_LIB_JPEG}
330 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
331 {$undef GLB_LIB_JPEG}
334 {$DEFINE GLB_SUPPORT_JPEG_READ}
335 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
338 {$IFDEF GLB_LIB_JPEG}
339 {$DEFINE GLB_SUPPORT_JPEG_READ}
340 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
343 // *** general options ***
354 {$IFDEF GLB_NO_NATIVE_GL} dglOpenGL, {$ENDIF}
356 {$IFDEF GLB_SDL} SDL, {$ENDIF}
357 {$IFDEF GLB_DELPHI} Dialogs, Windows, Graphics, {$ENDIF}
359 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
361 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
362 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
364 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
365 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
374 TRGBQuad = packed record
383 {$IFNDEF GLB_NO_NATIVE_GL}
384 // Native OpenGL Implementation
386 PByteBool = ^ByteBool;
396 GL_EXTENSIONS = $1F03;
401 GL_TEXTURE_1D = $0DE0;
402 GL_TEXTURE_2D = $0DE1;
404 GL_MAX_TEXTURE_SIZE = $0D33;
405 GL_PACK_ALIGNMENT = $0D05;
406 GL_UNPACK_ALIGNMENT = $0CF5;
419 GL_LUMINANCE4 = $803F;
420 GL_LUMINANCE8 = $8040;
421 GL_LUMINANCE4_ALPHA4 = $8043;
422 GL_LUMINANCE8_ALPHA8 = $8045;
423 GL_DEPTH_COMPONENT = $1902;
425 GL_UNSIGNED_BYTE = $1401;
427 GL_LUMINANCE = $1909;
428 GL_LUMINANCE_ALPHA = $190A;
430 GL_TEXTURE_WIDTH = $1000;
431 GL_TEXTURE_HEIGHT = $1001;
432 GL_TEXTURE_INTERNAL_FORMAT = $1003;
433 GL_TEXTURE_RED_SIZE = $805C;
434 GL_TEXTURE_GREEN_SIZE = $805D;
435 GL_TEXTURE_BLUE_SIZE = $805E;
436 GL_TEXTURE_ALPHA_SIZE = $805F;
437 GL_TEXTURE_LUMINANCE_SIZE = $8060;
440 GL_UNSIGNED_SHORT_5_6_5 = $8363;
441 GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
442 GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
443 GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
444 GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
449 GL_NEAREST_MIPMAP_NEAREST = $2700;
450 GL_LINEAR_MIPMAP_NEAREST = $2701;
451 GL_NEAREST_MIPMAP_LINEAR = $2702;
452 GL_LINEAR_MIPMAP_LINEAR = $2703;
453 GL_TEXTURE_MAG_FILTER = $2800;
454 GL_TEXTURE_MIN_FILTER = $2801;
457 GL_TEXTURE_WRAP_S = $2802;
458 GL_TEXTURE_WRAP_T = $2803;
461 GL_CLAMP_TO_EDGE = $812F;
462 GL_CLAMP_TO_BORDER = $812D;
463 GL_TEXTURE_WRAP_R = $8072;
465 GL_MIRRORED_REPEAT = $8370;
468 GL_TEXTURE_BORDER_COLOR = $1004;
471 GL_NORMAL_MAP = $8511;
472 GL_REFLECTION_MAP = $8512;
476 GL_TEXTURE_GEN_MODE = $2500;
477 GL_TEXTURE_GEN_S = $0C60;
478 GL_TEXTURE_GEN_T = $0C61;
479 GL_TEXTURE_GEN_R = $0C62;
482 GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C;
483 GL_TEXTURE_CUBE_MAP = $8513;
484 GL_TEXTURE_BINDING_CUBE_MAP = $8514;
485 GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515;
486 GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516;
487 GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517;
488 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518;
489 GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519;
490 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A;
492 GL_TEXTURE_RECTANGLE_ARB = $84F5;
494 // GL_SGIS_generate_mipmap
495 GL_GENERATE_MIPMAP = $8191;
497 // GL_EXT_texture_compression_s3tc
498 GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
499 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
500 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
501 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
503 // GL_EXT_texture_filter_anisotropic
504 GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
505 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
507 // GL_ARB_texture_compression
508 GL_COMPRESSED_RGB = $84ED;
509 GL_COMPRESSED_RGBA = $84EE;
510 GL_COMPRESSED_ALPHA = $84E9;
511 GL_COMPRESSED_LUMINANCE = $84EA;
512 GL_COMPRESSED_LUMINANCE_ALPHA = $84EB;
521 GL_ARB_texture_border_clamp,
522 GL_ARB_texture_cube_map,
523 GL_ARB_texture_compression,
524 GL_ARB_texture_non_power_of_two,
525 GL_ARB_texture_rectangle,
526 GL_ARB_texture_mirrored_repeat,
528 GL_EXT_texture_edge_clamp,
529 GL_EXT_texture_cube_map,
530 GL_EXT_texture_compression_s3tc,
531 GL_EXT_texture_filter_anisotropic,
532 GL_EXT_texture_rectangle,
533 GL_NV_texture_rectangle,
534 GL_IBM_texture_mirrored_repeat,
535 GL_SGIS_generate_mipmap: Boolean;
539 libglu = 'libGLU.so.1';
540 libopengl = 'libGL.so.1';
542 libglu = 'glu32.dll';
543 libopengl = 'opengl32.dll';
547 function glXGetProcAddress(ProcName: PAnsiChar): Pointer; cdecl; external libopengl;
549 function wglGetProcAddress(ProcName: PAnsiChar): Pointer; stdcall; external libopengl;
552 function glGetString(name: Cardinal): PAnsiChar; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
554 procedure glEnable(cap: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
555 procedure glDisable(cap: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
556 procedure glGetIntegerv(pname: Cardinal; params: PInteger); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
558 procedure glTexImage1D(target: Cardinal; level, internalformat, width, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
559 procedure glTexImage2D(target: Cardinal; level, internalformat, width, height, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
561 procedure glGenTextures(n: Integer; Textures: PCardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
562 procedure glBindTexture(target: Cardinal; Texture: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
563 procedure glDeleteTextures(n: Integer; const textures: PCardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
565 procedure glReadPixels(x, y: Integer; width, height: Integer; format, atype: Cardinal; pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
566 procedure glPixelStorei(pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
567 procedure glGetTexImage(target: Cardinal; level: Integer; format: Cardinal; _type: Cardinal; pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
569 function glAreTexturesResident(n: Integer; const Textures: PCardinal; residences: PByteBool): ByteBool; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
570 procedure glTexParameteri(target: Cardinal; pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
571 procedure glTexParameterfv(target: Cardinal; pname: Cardinal; const params: PSingle); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
572 procedure glGetTexLevelParameteriv(target: Cardinal; level: Integer; pname: Cardinal; params: PInteger); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
573 procedure glTexGeni(coord, pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
575 function gluBuild1DMipmaps(Target: Cardinal; Components, Width: Integer; Format, atype: Cardinal; Data: Pointer): Integer; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libglu;
576 function gluBuild2DMipmaps(Target: Cardinal; Components, Width, Height: Integer; Format, aType: Cardinal; Data: Pointer): Integer; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libglu;
579 glCompressedTexImage2D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width, height: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF}
580 glCompressedTexImage1D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF}
581 glGetCompressedTexImage : procedure(target: Cardinal; level: Integer; img: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF}
586 ////////////////////////////////////////////////////////////////////////////////////////////////////
587 EglBitmapException = class(Exception);
588 EglBitmapSizeToLargeException = class(EglBitmapException);
589 EglBitmapNonPowerOfTwoException = class(EglBitmapException);
590 EglBitmapUnsupportedFormatFormat = class(EglBitmapException);
592 ////////////////////////////////////////////////////////////////////////////////////////////////////
594 tfEmpty = 0, //must be smallest value!
610 tfLuminance12Alpha12,
611 tfLuminance16Alpha16,
655 TglBitmapFileType = (
656 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
657 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
661 TglBitmapFileTypes = set of TglBitmapFileType;
668 TglBitmapNormalMapFunc = (
674 ////////////////////////////////////////////////////////////////////////////////////////////////////
675 TglBitmapColorRec = packed record
677 0: (r, g, b, a: Cardinal);
678 1: (arr: array[0..3] of Cardinal);
681 TglBitmapPixelData = packed record
682 Data, Range: TglBitmapColorRec;
683 Format: TglBitmapFormat;
685 PglBitmapPixelData = ^TglBitmapPixelData;
687 ////////////////////////////////////////////////////////////////////////////////////////////////////
688 TglBitmapPixelPositionFields = set of (ffX, ffY);
689 TglBitmapPixelPosition = record
690 Fields : TglBitmapPixelPositionFields;
695 ////////////////////////////////////////////////////////////////////////////////////////////////////
697 TglBitmapFunctionRec = record
699 Size: TglBitmapPixelPosition;
700 Position: TglBitmapPixelPosition;
701 Source: TglBitmapPixelData;
702 Dest: TglBitmapPixelData;
705 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
707 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
712 fAnisotropic: Integer;
713 fDeleteTextureOnFree: Boolean;
714 fFreeDataAfterGenTexture: Boolean;
716 fIsResident: Boolean;
717 fBorderColor: array[0..3] of Single;
719 fDimension: TglBitmapPixelPosition;
720 fMipMap: TglBitmapMipMap;
721 fFormat: TglBitmapFormat;
728 fFilterMin: Cardinal;
729 fFilterMag: Cardinal;
739 fCustomNameW: WideString;
740 fCustomData: Pointer;
743 function GetWidth: Integer; virtual;
744 function GetHeight: Integer; virtual;
746 function GetFileWidth: Integer; virtual;
747 function GetFileHeight: Integer; virtual;
750 procedure SetCustomData(const aValue: Pointer);
751 procedure SetCustomName(const aValue: String);
752 procedure SetCustomNameW(const aValue: WideString);
753 procedure SetDeleteTextureOnFree(const aValue: Boolean);
754 procedure SetFormat(const aValue: TglBitmapFormat);
755 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
756 procedure SetID(const aValue: Cardinal);
757 procedure SetMipMap(const aValue: TglBitmapMipMap);
758 procedure SetTarget(const aValue: Cardinal);
759 procedure SetAnisotropic(const aValue: Integer);
762 procedure SetupParameters(var aBuildWithGlu: Boolean);
763 procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
764 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual;
765 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
767 function FlipHorz: Boolean; virtual;
768 function FlipVert: Boolean; virtual;
770 property Width: Integer read GetWidth;
771 property Height: Integer read GetHeight;
773 property FileWidth: Integer read GetFileWidth;
774 property FileHeight: Integer read GetFileHeight;
777 property ID: Cardinal read fID write SetID;
778 property Target: Cardinal read fTarget write SetTarget;
779 property Format: TglBitmapFormat read fFormat write SetFormat;
780 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
781 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
783 property Filename: String read fFilename;
784 property CustomName: String read fCustomName write SetCustomName;
785 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
786 property CustomData: Pointer read fCustomData write SetCustomData;
788 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
789 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
791 property Dimension: TglBitmapPixelPosition read fDimension;
792 property Data: PByte read fData;
793 property IsResident: Boolean read fIsResident;
795 procedure AfterConstruction; override;
796 procedure BeforeDestruction; override;
799 procedure LoadFromFile(const aFilename: String);
800 procedure LoadFromStream(const aStream: TStream); virtual;
801 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
802 const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0);
804 procedure LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
805 procedure LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
809 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
810 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
813 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt = 0): Boolean; overload;
814 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
815 const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0): Boolean; overload;
819 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
820 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
821 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
822 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
823 const aArgs: PtrInt = 0): Boolean;
827 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
828 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
829 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
830 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
831 const aArgs: PtrInt = 0): Boolean;
832 function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil;
833 const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
834 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
835 const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
838 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0): Boolean; virtual;
839 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
840 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
841 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
843 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
844 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
845 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
847 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
848 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
849 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
851 function RemoveAlpha: Boolean; virtual;
854 function Clone: TglBitmap;
855 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
856 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
857 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
861 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
862 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
863 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
866 procedure SetFilter(const aMin, aMag: Cardinal);
868 const S: Cardinal = GL_CLAMP_TO_EDGE;
869 const T: Cardinal = GL_CLAMP_TO_EDGE;
870 const R: Cardinal = GL_CLAMP_TO_EDGE);
872 procedure GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData); virtual;
873 procedure SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData); virtual;
875 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
876 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
879 constructor Create; overload;
880 constructor Create(const aFileName: String); overload;
881 constructor Create(const aStream: TStream); overload;
882 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload;
883 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0); overload;
885 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
886 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
889 {$IFDEF GLB_SUPPORT_PNG_READ}
890 function LoadPNG(const aStream: TStream): Boolean; virtual;
891 procedure SavePNG(const aStream: TStream); virtual;
893 {$IFDEF GLB_SUPPORT_JPEG_READ}
894 function LoadJPEG(const aStream: TStream): Boolean; virtual;
895 procedure SaveJPEG(const aStream: TStream); virtual;
897 function LoadBMP(const aStream: TStream): Boolean; virtual;
898 procedure SaveBMP(const aStream: TStream); virtual;
900 function LoadTGA(const aStream: TStream): Boolean; virtual;
901 procedure SaveTGA(const aStream: TStream); virtual;
903 function LoadDDS(const aStream: TStream): Boolean; virtual;
904 procedure SaveDDS(const aStream: TStream); virtual;
907 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
908 TglBitmap2D = class(TglBitmap)
911 fLines: array of PByte;
914 procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
915 procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
916 procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
917 procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
918 procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
919 procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
922 function GetScanline(const aIndex: Integer): Pointer;
923 procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
924 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
925 procedure UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
929 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
931 procedure AfterConstruction; override;
933 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
934 procedure GetDataFromTexture;
935 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
937 function FlipHorz: Boolean; override;
938 function FlipVert: Boolean; override;
940 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
941 const aScale: Single = 2; const aUseAlpha: Boolean = false);
945 TglBitmapCubeMap = class(TglBitmap2D)
950 procedure GenTexture(TestTextureSize: Boolean = true); reintroduce;
952 procedure AfterConstruction; override;
954 procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true);
956 procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = true); reintroduce; virtual;
957 procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = true); reintroduce; virtual;
961 TglBitmapNormalMap = class(TglBitmapCubeMap)
963 procedure AfterConstruction; override;
965 procedure GenerateNormalMap(Size: Integer = 32; TestTextureSize: Boolean = true);
969 TglBitmap1D = class(TglBitmap)
971 procedure GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
973 procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override;
974 procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
979 procedure AfterConstruction; override;
982 function FlipHorz: Boolean; override;
985 procedure GenTexture(TestTextureSize: Boolean = true); override;
990 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
992 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
993 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
994 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
995 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
996 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
997 procedure glBitmapSetDefaultWrap(
998 const S: Cardinal = GL_CLAMP_TO_EDGE;
999 const T: Cardinal = GL_CLAMP_TO_EDGE;
1000 const R: Cardinal = GL_CLAMP_TO_EDGE);
1002 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1003 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1004 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1005 function glBitmapGetDefaultFormat: TglBitmapFormat;
1006 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1007 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1009 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1010 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1011 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1014 glBitmapDefaultDeleteTextureOnFree: Boolean;
1015 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1016 glBitmapDefaultFormat: TglBitmapFormat;
1017 glBitmapDefaultMipmap: TglBitmapMipMap;
1018 glBitmapDefaultFilterMin: Cardinal;
1019 glBitmapDefaultFilterMag: Cardinal;
1020 glBitmapDefaultWrapS: Cardinal;
1021 glBitmapDefaultWrapT: Cardinal;
1022 glBitmapDefaultWrapR: Cardinal;
1025 function CreateGrayPalette: HPALETTE;
1032 function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
1033 function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
1034 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
1035 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
1036 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
1043 ////////////////////////////////////////////////////////////////////////////////////////////////////
1044 TShiftRec = packed record
1046 0: (r, g, b, a: Byte);
1047 1: (arr: array[0..3] of Byte);
1050 TFormatDescriptor = class(TObject)
1052 function GetRedMask: UInt64;
1053 function GetGreenMask: UInt64;
1054 function GetBlueMask: UInt64;
1055 function GetAlphaMask: UInt64;
1057 fFormat: TglBitmapFormat;
1058 fWithAlpha: TglBitmapFormat;
1059 fWithoutAlpha: TglBitmapFormat;
1060 fRGBInverted: TglBitmapFormat;
1061 fUncompressed: TglBitmapFormat;
1063 fIsCompressed: Boolean;
1065 fRange: TglBitmapColorRec;
1068 fglFormat: Cardinal;
1069 fglInternalFormat: Cardinal;
1070 fglDataFormat: Cardinal;
1072 function GetComponents: Integer; virtual;
1074 property Format: TglBitmapFormat read fFormat;
1075 property WithAlpha: TglBitmapFormat read fWithAlpha;
1076 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1077 property RGBInverted: TglBitmapFormat read fRGBInverted;
1078 property Components: Integer read GetComponents;
1079 property PixelSize: Single read fPixelSize;
1080 property IsCompressed: Boolean read fIsCompressed;
1082 property glFormat: Cardinal read fglFormat;
1083 property glInternalFormat: Cardinal read fglInternalFormat;
1084 property glDataFormat: Cardinal read fglDataFormat;
1086 property Range: TglBitmapColorRec read fRange;
1087 property Shift: TShiftRec read fShift;
1089 property RedMask: UInt64 read GetRedMask;
1090 property GreenMask: UInt64 read GetGreenMask;
1091 property BlueMask: UInt64 read GetBlueMask;
1092 property AlphaMask: UInt64 read GetAlphaMask;
1094 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1095 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1097 function GetSize(const aSize: TglBitmapPixelPosition): Integer; virtual; overload;
1098 function GetSize(const aWidth, aHeight: Integer): Integer; virtual; overload;
1100 function CreateMappingData: Pointer; virtual;
1101 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1103 function IsEmpty: Boolean; virtual;
1104 function HasAlpha: Boolean; virtual;
1105 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual;
1107 procedure PreparePixel(var aPixel: TglBitmapPixelData); virtual;
1109 constructor Create; virtual;
1111 class procedure Init;
1112 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1113 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1114 class procedure Clear;
1115 class procedure Finalize;
1117 TFormatDescriptorClass = class of TFormatDescriptor;
1119 TfdEmpty = class(TFormatDescriptor);
1121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1122 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1123 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1124 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1125 constructor Create; override;
1128 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1129 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1130 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1131 constructor Create; override;
1134 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1135 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1136 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1137 constructor Create; override;
1140 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1141 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1142 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1143 constructor Create; override;
1146 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1147 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1148 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1149 constructor Create; override;
1152 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1153 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1154 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1155 constructor Create; override;
1158 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1159 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1160 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1161 constructor Create; override;
1164 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1165 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1166 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1167 constructor Create; override;
1170 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1171 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1172 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1173 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1174 constructor Create; override;
1177 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1178 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1179 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1180 constructor Create; override;
1183 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1184 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1185 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1186 constructor Create; override;
1189 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1190 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1191 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1192 constructor Create; override;
1195 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1196 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1197 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1198 constructor Create; override;
1201 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1202 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1203 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1204 constructor Create; override;
1207 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1208 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1209 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1210 constructor Create; override;
1213 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1214 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1215 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1216 constructor Create; override;
1219 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1220 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1221 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1222 constructor Create; override;
1225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1226 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1227 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1228 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1229 constructor Create; override;
1232 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1233 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1234 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1235 constructor Create; override;
1238 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1239 TfdAlpha4 = class(TfdAlpha_UB1)
1240 constructor Create; override;
1243 TfdAlpha8 = class(TfdAlpha_UB1)
1244 constructor Create; override;
1247 TfdAlpha12 = class(TfdAlpha_US1)
1248 constructor Create; override;
1251 TfdAlpha16 = class(TfdAlpha_US1)
1252 constructor Create; override;
1255 TfdLuminance4 = class(TfdLuminance_UB1)
1256 constructor Create; override;
1259 TfdLuminance8 = class(TfdLuminance_UB1)
1260 constructor Create; override;
1263 TfdLuminance12 = class(TfdLuminance_US1)
1264 constructor Create; override;
1267 TfdLuminance16 = class(TfdLuminance_US1)
1268 constructor Create; override;
1271 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1272 constructor Create; override;
1275 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1276 constructor Create; override;
1279 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1280 constructor Create; override;
1283 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1284 constructor Create; override;
1287 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1288 constructor Create; override;
1291 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1292 constructor Create; override;
1295 TfdR3G3B2 = class(TfdUniversal_UB1)
1296 constructor Create; override;
1299 TfdRGB4 = class(TfdUniversal_US1)
1300 constructor Create; override;
1303 TfdR5G6B5 = class(TfdUniversal_US1)
1304 constructor Create; override;
1307 TfdRGB5 = class(TfdUniversal_US1)
1308 constructor Create; override;
1311 TfdRGB8 = class(TfdRGB_UB3)
1312 constructor Create; override;
1315 TfdRGB10 = class(TfdUniversal_UI1)
1316 constructor Create; override;
1319 TfdRGB12 = class(TfdRGB_US3)
1320 constructor Create; override;
1323 TfdRGB16 = class(TfdRGB_US3)
1324 constructor Create; override;
1327 TfdRGBA2 = class(TfdRGBA_UB4)
1328 constructor Create; override;
1331 TfdRGBA4 = class(TfdUniversal_US1)
1332 constructor Create; override;
1335 TfdRGB5A1 = class(TfdUniversal_US1)
1336 constructor Create; override;
1339 TfdRGBA8 = class(TfdRGBA_UB4)
1340 constructor Create; override;
1343 TfdRGB10A2 = class(TfdUniversal_UI1)
1344 constructor Create; override;
1347 TfdRGBA12 = class(TfdRGBA_US4)
1348 constructor Create; override;
1351 TfdRGBA16 = class(TfdRGBA_US4)
1352 constructor Create; override;
1355 TfdBGR4 = class(TfdUniversal_US1)
1356 constructor Create; override;
1359 TfdB5G6R5 = class(TfdUniversal_US1)
1360 constructor Create; override;
1363 TfdBGR5 = class(TfdUniversal_US1)
1364 constructor Create; override;
1367 TfdBGR8 = class(TfdBGR_UB3)
1368 constructor Create; override;
1371 TfdBGR10 = class(TfdUniversal_UI1)
1372 constructor Create; override;
1375 TfdBGR12 = class(TfdBGR_US3)
1376 constructor Create; override;
1379 TfdBGR16 = class(TfdBGR_US3)
1380 constructor Create; override;
1383 TfdBGRA2 = class(TfdBGRA_UB4)
1384 constructor Create; override;
1387 TfdBGRA4 = class(TfdUniversal_US1)
1388 constructor Create; override;
1391 TfdBGR5A1 = class(TfdUniversal_US1)
1392 constructor Create; override;
1395 TfdBGRA8 = class(TfdBGRA_UB4)
1396 constructor Create; override;
1399 TfdBGR10A2 = class(TfdUniversal_UI1)
1400 constructor Create; override;
1403 TfdBGRA12 = class(TfdBGRA_US4)
1404 constructor Create; override;
1407 TfdBGRA16 = class(TfdBGRA_US4)
1408 constructor Create; override;
1411 TfdDepth16 = class(TfdDepth_US1)
1412 constructor Create; override;
1415 TfdDepth24 = class(TfdDepth_UI1)
1416 constructor Create; override;
1419 TfdDepth32 = class(TfdDepth_UI1)
1420 constructor Create; override;
1423 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1424 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1425 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1426 constructor Create; override;
1429 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1430 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1431 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1432 constructor Create; override;
1435 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1436 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1437 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1438 constructor Create; override;
1441 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1442 TbmpBitfieldFormat = class(TFormatDescriptor)
1444 procedure SetRedMask (const aValue: UInt64);
1445 procedure SetGreenMask(const aValue: UInt64);
1446 procedure SetBlueMask (const aValue: UInt64);
1447 procedure SetAlphaMask(const aValue: UInt64);
1449 procedure Update(aMask: UInt64; out aRange: Cardinal; out aShift: Byte);
1451 property RedMask: UInt64 read GetRedMask write SetRedMask;
1452 property GreenMask: UInt64 read GetGreenMask write SetGreenMask;
1453 property BlueMask: UInt64 read GetBlueMask write SetBlueMask;
1454 property AlphaMask: UInt64 read GetAlphaMask write SetAlphaMask;
1456 property PixelSize: Single read fPixelSize write fPixelSize;
1458 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1459 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1462 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1463 TbmpColorTableEnty = packed record
1466 TbmpColorTable = array of TbmpColorTableEnty;
1467 TbmpColorTableFormat = class(TFormatDescriptor)
1469 fColorTable: TbmpColorTable;
1471 property PixelSize: Single read fPixelSize write fPixelSize;
1472 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1473 property Range: TglBitmapColorRec read fRange write fRange;
1474 property Shift: TShiftRec read fShift write fShift;
1475 property Format: TglBitmapFormat read fFormat write fFormat;
1477 procedure CreateColorTable;
1479 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1480 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1481 destructor Destroy; override;
1485 LUMINANCE_WEIGHT_R = 0.30;
1486 LUMINANCE_WEIGHT_G = 0.59;
1487 LUMINANCE_WEIGHT_B = 0.11;
1489 ALPHA_WEIGHT_R = 0.30;
1490 ALPHA_WEIGHT_G = 0.59;
1491 ALPHA_WEIGHT_B = 0.11;
1493 DEPTH_WEIGHT_R = 0.333333333;
1494 DEPTH_WEIGHT_G = 0.333333333;
1495 DEPTH_WEIGHT_B = 0.333333333;
1497 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1499 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1512 TfdLuminance4Alpha4,
1513 TfdLuminance6Alpha2,
1514 TfdLuminance8Alpha8,
1515 TfdLuminance12Alpha4,
1516 TfdLuminance12Alpha12,
1517 TfdLuminance16Alpha16,
1562 FormatDescriptorCS: TCriticalSection;
1563 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1565 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1566 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1568 result.Fields := [];
1571 result.Fields := result.Fields + [ffX];
1573 result.Fields := result.Fields + [ffY];
1575 result.X := Max(0, X);
1576 result.Y := Max(0, Y);
1579 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1580 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1588 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1589 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1594 for i := 0 to high(r1.arr) do
1595 if (r1.arr[i] <> r2.arr[i]) then
1600 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1601 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1609 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1610 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1617 tfR3G3B2, tfLuminance8,
1620 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1621 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1627 tfRGB10, tfRGB10A2, tfRGBA8,
1628 tfBGR10, tfBGR10A2, tfBGRA8]) then
1629 result := result + [ftBMP];
1633 tfLuminance8, tfAlpha8,
1636 tfLuminance16, tfLuminance8Alpha8,
1637 tfRGB5, tfRGB5A1, tfRGBA4,
1638 tfBGR5, tfBGR5A1, tfBGRA4,
1644 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1645 result := result + [ftTGA];
1649 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1650 tfR3G3B2, tfRGBA2, tfBGRA2,
1653 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1654 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1655 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1661 tfLuminance16Alpha16,
1666 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1667 result := result + [ftDDS];
1670 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1672 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1673 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1674 tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
1675 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1676 tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
1677 tfDepth16, tfDepth24, tfDepth32]
1679 result := result + [ftPNG];
1682 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1684 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1685 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1686 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1687 tfDepth16, tfDepth24, tfDepth32]
1689 result := result + [ftJPEG];
1693 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1694 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1695 tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
1696 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1697 tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
1698 tfDepth16, tfDepth24, tfDepth32]
1700 result := result + [ftDDS, ftTGA, ftBMP];
1704 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1705 function IsPowerOfTwo(aNumber: Integer): Boolean;
1707 while (aNumber and 1) = 0 do
1708 aNumber := aNumber shr 1;
1709 result := aNumber = 1;
1712 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1713 function GetTopMostBit(aBitSet: UInt64): Integer;
1716 while aBitSet > 0 do begin
1718 aBitSet := aBitSet shr 1;
1722 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1723 function CountSetBits(aBitSet: UInt64): Integer;
1726 while aBitSet > 0 do begin
1727 if (aBitSet and 1) = 1 then
1729 aBitSet := aBitSet shr 1;
1733 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1734 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1737 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1738 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1739 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1742 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1745 DEPTH_WEIGHT_R * aPixel.Data.r +
1746 DEPTH_WEIGHT_G * aPixel.Data.g +
1747 DEPTH_WEIGHT_B * aPixel.Data.b);
1750 //TODO check _ARB functions and constants
1753 {$IFNDEF GLB_NO_NATIVE_GL}
1754 procedure ReadOpenGLExtensions;
1760 MajorVersion, MinorVersion: Integer;
1763 procedure TrimVersionString(Buffer: AnsiString; var Major, Minor: Integer);
1770 Separator := Pos(AnsiString('.'), Buffer);
1772 if (Separator > 1) and (Separator < Length(Buffer)) and
1773 (Buffer[Separator - 1] in ['0'..'9']) and
1774 (Buffer[Separator + 1] in ['0'..'9']) then begin
1777 while (Separator > 0) and (Buffer[Separator] in ['0'..'9']) do
1780 Delete(Buffer, 1, Separator);
1781 Separator := Pos(AnsiString('.'), Buffer) + 1;
1783 while (Separator <= Length(Buffer)) and (AnsiChar(Buffer[Separator]) in ['0'..'9']) do
1786 Delete(Buffer, Separator, 255);
1787 Separator := Pos(AnsiString('.'), Buffer);
1789 Major := StrToInt(Copy(String(Buffer), 1, Separator - 1));
1790 Minor := StrToInt(Copy(String(Buffer), Separator + 1, 1));
1795 function CheckExtension(const Extension: AnsiString): Boolean;
1799 ExtPos := Pos(Extension, Buffer);
1800 result := ExtPos > 0;
1803 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
1807 function glLoad (aFunc: pAnsiChar): pointer;
1810 result := glXGetProcAddress(aFunc);
1812 result := wglGetProcAddress(aFunc);
1819 Context := wglGetCurrentContext;
1821 if Context <> gLastContext then begin
1822 gLastContext := Context;
1826 Buffer := glGetString(GL_VERSION);
1827 TrimVersionString(Buffer, MajorVersion, MinorVersion);
1829 GL_VERSION_1_2 := false;
1830 GL_VERSION_1_3 := false;
1831 GL_VERSION_1_4 := false;
1832 GL_VERSION_2_0 := false;
1834 if MajorVersion = 1 then begin
1835 if MinorVersion >= 1 then begin
1836 if MinorVersion >= 2 then
1837 GL_VERSION_1_2 := true;
1839 if MinorVersion >= 3 then
1840 GL_VERSION_1_3 := true;
1842 if MinorVersion >= 4 then
1843 GL_VERSION_1_4 := true;
1847 if MajorVersion >= 2 then begin
1848 GL_VERSION_1_2 := true;
1849 GL_VERSION_1_3 := true;
1850 GL_VERSION_1_4 := true;
1851 GL_VERSION_2_0 := true;
1855 Buffer := glGetString(GL_EXTENSIONS);
1856 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
1857 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
1858 GL_ARB_texture_compression := CheckExtension('GL_ARB_texture_compression');
1859 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
1860 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
1861 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
1862 GL_EXT_bgra := CheckExtension('GL_EXT_bgra');
1863 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
1864 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
1865 GL_EXT_texture_compression_s3tc := CheckExtension('GL_EXT_texture_compression_s3tc');
1866 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
1867 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
1868 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
1869 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
1870 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
1873 if GL_VERSION_1_3 then begin
1875 glCompressedTexImage1D := glLoad('glCompressedTexImage1D');
1876 glCompressedTexImage2D := glLoad('glCompressedTexImage2D');
1877 glGetCompressedTexImage := glLoad('glGetCompressedTexImage');
1881 // Try loading Extension
1882 glCompressedTexImage1D := glLoad('glCompressedTexImage1DARB');
1883 glCompressedTexImage2D := glLoad('glCompressedTexImage2DARB');
1884 glGetCompressedTexImage := glLoad('glGetCompressedTexImageARB');
1895 function CreateGrayPalette: HPALETTE;
1900 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
1902 Pal.palVersion := $300;
1903 Pal.palNumEntries := 256;
1906 {$DEFINE GLB_TEMPRANGECHECK}
1910 for Idx := 0 to 256 - 1 do begin
1911 Pal.palPalEntry[Idx].peRed := Idx;
1912 Pal.palPalEntry[Idx].peGreen := Idx;
1913 Pal.palPalEntry[Idx].peBlue := Idx;
1914 Pal.palPalEntry[Idx].peFlags := 0;
1917 {$IFDEF GLB_TEMPRANGECHECK}
1918 {$UNDEF GLB_TEMPRANGECHECK}
1922 result := CreatePalette(Pal^);
1929 (* TODO GLB_SDL_IMAGE
1930 {$IFDEF GLB_SDL_IMAGE}
1931 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
1933 result := TStream(context^.unknown.data1).Seek(offset, whence);
1936 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
1938 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
1941 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
1943 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
1946 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
1951 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
1953 result := SDL_AllocRW;
1955 if result = nil then
1956 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
1958 result^.seek := glBitmapRWseek;
1959 result^.read := glBitmapRWread;
1960 result^.write := glBitmapRWwrite;
1961 result^.close := glBitmapRWclose;
1962 result^.unknown.data1 := Stream;
1968 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
1970 glBitmap: TglBitmap2D;
1976 if Instance = 0 then
1977 Instance := HInstance;
1979 if (LoadFromRes) then
1980 glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName)
1983 glBitmap := TglBitmap2D.Create(FileName);
1986 glBitmap.DeleteTextureOnFree := false;
1987 glBitmap.FreeDataAfterGenTexture := false;
1988 glBitmap.GenTexture(true);
1989 if (glBitmap.ID > 0) then begin
1990 Texture := glBitmap.ID;
1998 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
2000 CM: TglBitmapCubeMap;
2005 if Instance = 0 then
2006 Instance := HInstance;
2009 CM := TglBitmapCubeMap.Create;
2011 CM.DeleteTextureOnFree := false;
2015 if (LoadFromRes) then
2016 CM.LoadFromResource(Instance, PositiveX)
2019 CM.LoadFromFile(PositiveX);
2020 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
2023 if (LoadFromRes) then
2024 CM.LoadFromResource(Instance, NegativeX)
2027 CM.LoadFromFile(NegativeX);
2028 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
2031 if (LoadFromRes) then
2032 CM.LoadFromResource(Instance, PositiveY)
2035 CM.LoadFromFile(PositiveY);
2036 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
2039 if (LoadFromRes) then
2040 CM.LoadFromResource(Instance, NegativeY)
2043 CM.LoadFromFile(NegativeY);
2044 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
2047 if (LoadFromRes) then
2048 CM.LoadFromResource(Instance, PositiveZ)
2051 CM.LoadFromFile(PositiveZ);
2052 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
2055 if (LoadFromRes) then
2056 CM.LoadFromResource(Instance, NegativeZ)
2059 CM.LoadFromFile(NegativeZ);
2060 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
2069 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
2071 NM: TglBitmapNormalMap;
2075 NM := TglBitmapNormalMap.Create;
2077 NM.DeleteTextureOnFree := false;
2078 NM.GenerateNormalMap(Size);
2088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2089 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2091 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2094 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2095 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2097 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2100 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2101 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2103 glBitmapDefaultMipmap := aValue;
2106 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2107 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2109 glBitmapDefaultFormat := aFormat;
2112 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2113 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2115 glBitmapDefaultFilterMin := aMin;
2116 glBitmapDefaultFilterMag := aMag;
2119 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2120 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2122 glBitmapDefaultWrapS := S;
2123 glBitmapDefaultWrapT := T;
2124 glBitmapDefaultWrapR := R;
2127 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2128 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2130 result := glBitmapDefaultDeleteTextureOnFree;
2133 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2134 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2136 result := glBitmapDefaultFreeDataAfterGenTextures;
2139 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2140 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2142 result := glBitmapDefaultMipmap;
2145 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2146 function glBitmapGetDefaultFormat: TglBitmapFormat;
2148 result := glBitmapDefaultFormat;
2151 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2152 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
2154 aMin := glBitmapDefaultFilterMin;
2155 aMag := glBitmapDefaultFilterMag;
2158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2159 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
2161 S := glBitmapDefaultWrapS;
2162 T := glBitmapDefaultWrapT;
2163 R := glBitmapDefaultWrapR;
2166 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2167 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2168 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2169 function TFormatDescriptor.GetRedMask: UInt64;
2171 result := fRange.r shl fShift.r;
2174 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2175 function TFormatDescriptor.GetGreenMask: UInt64;
2177 result := fRange.g shl fShift.g;
2180 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2181 function TFormatDescriptor.GetBlueMask: UInt64;
2183 result := fRange.b shl fShift.b;
2186 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2187 function TFormatDescriptor.GetAlphaMask: UInt64;
2189 result := fRange.a shl fShift.a;
2192 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2193 function TFormatDescriptor.GetComponents: Integer;
2199 if (fRange.arr[i] > 0) then
2203 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2204 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2208 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2209 w := Max(1, aSize.X);
2210 h := Max(1, aSize.Y);
2211 result := GetSize(w, h);
2216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2217 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2220 if (aWidth <= 0) or (aHeight <= 0) then
2222 result := Ceil(aWidth * aHeight * fPixelSize);
2225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2226 function TFormatDescriptor.CreateMappingData: Pointer;
2231 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2232 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2237 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2238 function TFormatDescriptor.IsEmpty: Boolean;
2240 result := (fFormat = tfEmpty);
2243 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2244 function TFormatDescriptor.HasAlpha: Boolean;
2246 result := (fRange.a > 0);
2249 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2250 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean;
2254 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2255 raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
2257 if (aRedMask <> RedMask) then
2259 if (aGreenMask <> GreenMask) then
2261 if (aBlueMask <> BlueMask) then
2263 if (aAlphaMask <> AlphaMask) then
2268 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2269 procedure TFormatDescriptor.PreparePixel(var aPixel: TglBitmapPixelData);
2271 FillChar(aPixel, SizeOf(aPixel), 0);
2272 aPixel.Data := fRange;
2273 aPixel.Range := fRange;
2274 aPixel.Format := fFormat;
2277 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2278 constructor TFormatDescriptor.Create;
2283 fWithAlpha := tfEmpty;
2284 fWithoutAlpha := tfEmpty;
2285 fRGBInverted := tfEmpty;
2286 fUncompressed := tfEmpty;
2288 fIsCompressed := false;
2291 fglInternalFormat := 0;
2294 FillChar(fRange, 0, SizeOf(fRange));
2295 FillChar(fShift, 0, SizeOf(fShift));
2298 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2299 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2300 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2301 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2303 aData^ := aPixel.Data.a;
2307 procedure TfdAlpha_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2312 aPixel.Data.a := aData^;
2316 constructor TfdAlpha_UB1.Create;
2321 fglFormat := GL_ALPHA;
2322 fglDataFormat := GL_UNSIGNED_BYTE;
2325 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2326 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2327 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2328 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2330 aData^ := LuminanceWeight(aPixel);
2334 procedure TfdLuminance_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2336 aPixel.Data.r := aData^;
2337 aPixel.Data.g := aData^;
2338 aPixel.Data.b := aData^;
2343 constructor TfdLuminance_UB1.Create;
2350 fglFormat := GL_LUMINANCE;
2351 fglDataFormat := GL_UNSIGNED_BYTE;
2354 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2355 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2356 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2357 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2363 if (fRange.arr[i] > 0) then
2364 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2368 procedure TfdUniversal_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2373 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2377 constructor TfdUniversal_UB1.Create;
2383 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2384 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2385 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2386 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2388 inherited Map(aPixel, aData, aMapData);
2389 aData^ := aPixel.Data.a;
2393 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2395 inherited Unmap(aData, aPixel, aMapData);
2396 aPixel.Data.a := aData^;
2400 constructor TfdLuminanceAlpha_UB2.Create;
2406 fglFormat := GL_LUMINANCE_ALPHA;
2407 fglDataFormat := GL_UNSIGNED_BYTE;
2410 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2411 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2412 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2413 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2415 aData^ := aPixel.Data.r;
2417 aData^ := aPixel.Data.g;
2419 aData^ := aPixel.Data.b;
2423 procedure TfdRGB_UB3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2425 aPixel.Data.r := aData^;
2427 aPixel.Data.g := aData^;
2429 aPixel.Data.b := aData^;
2434 constructor TfdRGB_UB3.Create;
2444 fglFormat := GL_RGB;
2445 fglDataFormat := GL_UNSIGNED_BYTE;
2448 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2449 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2450 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2451 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2453 aData^ := aPixel.Data.b;
2455 aData^ := aPixel.Data.g;
2457 aData^ := aPixel.Data.r;
2461 procedure TfdBGR_UB3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2463 aPixel.Data.b := aData^;
2465 aPixel.Data.g := aData^;
2467 aPixel.Data.r := aData^;
2472 constructor TfdBGR_UB3.Create;
2481 fglFormat := GL_BGR;
2482 fglDataFormat := GL_UNSIGNED_BYTE;
2485 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2486 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2487 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2488 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2490 inherited Map(aPixel, aData, aMapData);
2491 aData^ := aPixel.Data.a;
2495 procedure TfdRGBA_UB4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2497 inherited Unmap(aData, aPixel, aMapData);
2498 aPixel.Data.a := aData^;
2502 constructor TfdRGBA_UB4.Create;
2508 fglFormat := GL_RGBA;
2509 fglDataFormat := GL_UNSIGNED_BYTE;
2512 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2513 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2514 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2515 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2517 inherited Map(aPixel, aData, aMapData);
2518 aData^ := aPixel.Data.a;
2522 procedure TfdBGRA_UB4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2524 inherited Unmap(aData, aPixel, aMapData);
2525 aPixel.Data.a := aData^;
2529 constructor TfdBGRA_UB4.Create;
2535 fglFormat := GL_BGRA;
2536 fglDataFormat := GL_UNSIGNED_BYTE;
2539 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2540 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2541 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2542 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2544 PWord(aData)^ := aPixel.Data.a;
2548 procedure TfdAlpha_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2553 aPixel.Data.a := PWord(aData)^;
2557 constructor TfdAlpha_US1.Create;
2562 fglFormat := GL_ALPHA;
2563 fglDataFormat := GL_UNSIGNED_SHORT;
2566 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2567 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2568 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2569 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2571 PWord(aData)^ := LuminanceWeight(aPixel);
2575 procedure TfdLuminance_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2577 aPixel.Data.r := PWord(aData)^;
2578 aPixel.Data.g := PWord(aData)^;
2579 aPixel.Data.b := PWord(aData)^;
2584 constructor TfdLuminance_US1.Create;
2591 fglFormat := GL_LUMINANCE;
2592 fglDataFormat := GL_UNSIGNED_SHORT;
2595 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2596 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2597 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2598 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2604 if (fRange.arr[i] > 0) then
2605 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2609 procedure TfdUniversal_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2614 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2618 constructor TfdUniversal_US1.Create;
2624 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2625 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2626 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2627 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2629 PWord(aData)^ := DepthWeight(aPixel);
2633 procedure TfdDepth_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2635 aPixel.Data.r := PWord(aData)^;
2636 aPixel.Data.g := PWord(aData)^;
2637 aPixel.Data.b := PWord(aData)^;
2642 constructor TfdDepth_US1.Create;
2649 fglFormat := GL_DEPTH_COMPONENT;
2650 fglDataFormat := GL_UNSIGNED_SHORT;
2653 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2654 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2655 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2656 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2658 inherited Map(aPixel, aData, aMapData);
2659 PWord(aData)^ := aPixel.Data.a;
2663 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2665 inherited Unmap(aData, aPixel, aMapData);
2666 aPixel.Data.a := PWord(aData)^;
2670 constructor TfdLuminanceAlpha_US2.Create;
2676 fglFormat := GL_LUMINANCE_ALPHA;
2677 fglDataFormat := GL_UNSIGNED_SHORT;
2680 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2681 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2683 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2685 PWord(aData)^ := aPixel.Data.r;
2687 PWord(aData)^ := aPixel.Data.g;
2689 PWord(aData)^ := aPixel.Data.b;
2693 procedure TfdRGB_US3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2695 aPixel.Data.r := PWord(aData)^;
2697 aPixel.Data.g := PWord(aData)^;
2699 aPixel.Data.b := PWord(aData)^;
2704 constructor TfdRGB_US3.Create;
2714 fglFormat := GL_RGB;
2715 fglDataFormat := GL_UNSIGNED_SHORT;
2718 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2719 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2720 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2721 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2723 PWord(aData)^ := aPixel.Data.b;
2725 PWord(aData)^ := aPixel.Data.g;
2727 PWord(aData)^ := aPixel.Data.r;
2731 procedure TfdBGR_US3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2733 aPixel.Data.b := PWord(aData)^;
2735 aPixel.Data.g := PWord(aData)^;
2737 aPixel.Data.r := PWord(aData)^;
2742 constructor TfdBGR_US3.Create;
2752 fglFormat := GL_BGR;
2753 fglDataFormat := GL_UNSIGNED_SHORT;
2756 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2757 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2758 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2759 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2761 inherited Map(aPixel, aData, aMapData);
2762 PWord(aData)^ := aPixel.Data.a;
2766 procedure TfdRGBA_US4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2768 inherited Unmap(aData, aPixel, aMapData);
2769 aPixel.Data.a := PWord(aData)^;
2773 constructor TfdRGBA_US4.Create;
2779 fglFormat := GL_RGBA;
2780 fglDataFormat := GL_UNSIGNED_SHORT;
2783 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2784 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2785 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2786 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2788 inherited Map(aPixel, aData, aMapData);
2789 PWord(aData)^ := aPixel.Data.a;
2793 procedure TfdBGRA_US4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2795 inherited Unmap(aData, aPixel, aMapData);
2796 aPixel.Data.a := PWord(aData)^;
2800 constructor TfdBGRA_US4.Create;
2806 fglFormat := GL_BGRA;
2807 fglDataFormat := GL_UNSIGNED_SHORT;
2810 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2811 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2812 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2813 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2817 PCardinal(aData)^ := 0;
2819 if (fRange.arr[i] > 0) then
2820 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2824 procedure TfdUniversal_UI1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2829 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2833 constructor TfdUniversal_UI1.Create;
2839 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2840 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2841 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2842 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2844 PCardinal(aData)^ := DepthWeight(aPixel);
2848 procedure TfdDepth_UI1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2850 aPixel.Data.r := PCardinal(aData)^;
2851 aPixel.Data.g := PCardinal(aData)^;
2852 aPixel.Data.b := PCardinal(aData)^;
2857 constructor TfdDepth_UI1.Create;
2861 fRange.r := $FFFFFFFF;
2862 fRange.g := $FFFFFFFF;
2863 fRange.b := $FFFFFFFF;
2864 fglFormat := GL_DEPTH_COMPONENT;
2865 fglDataFormat := GL_UNSIGNED_INT;
2868 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2869 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2870 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2871 constructor TfdAlpha4.Create;
2874 fFormat := tfAlpha4;
2875 fWithAlpha := tfAlpha4;
2876 fglInternalFormat := GL_ALPHA4;
2879 constructor TfdAlpha8.Create;
2882 fFormat := tfAlpha8;
2883 fWithAlpha := tfAlpha8;
2884 fglInternalFormat := GL_ALPHA8;
2887 constructor TfdAlpha12.Create;
2890 fFormat := tfAlpha12;
2891 fWithAlpha := tfAlpha12;
2892 fglInternalFormat := GL_ALPHA12;
2895 constructor TfdAlpha16.Create;
2898 fFormat := tfAlpha16;
2899 fWithAlpha := tfAlpha16;
2900 fglInternalFormat := GL_ALPHA16;
2903 constructor TfdLuminance4.Create;
2906 fFormat := tfLuminance4;
2907 fWithAlpha := tfLuminance4Alpha4;
2908 fWithoutAlpha := tfLuminance4;
2909 fglInternalFormat := GL_LUMINANCE4;
2912 constructor TfdLuminance8.Create;
2915 fFormat := tfLuminance8;
2916 fWithAlpha := tfLuminance8Alpha8;
2917 fWithoutAlpha := tfLuminance8;
2918 fglInternalFormat := GL_LUMINANCE8;
2921 constructor TfdLuminance12.Create;
2924 fFormat := tfLuminance12;
2925 fWithAlpha := tfLuminance12Alpha12;
2926 fWithoutAlpha := tfLuminance12;
2927 fglInternalFormat := GL_LUMINANCE12;
2930 constructor TfdLuminance16.Create;
2933 fFormat := tfLuminance16;
2934 fWithAlpha := tfLuminance16Alpha16;
2935 fWithoutAlpha := tfLuminance16;
2936 fglInternalFormat := GL_LUMINANCE16;
2939 constructor TfdLuminance4Alpha4.Create;
2942 fFormat := tfLuminance4Alpha4;
2943 fWithAlpha := tfLuminance4Alpha4;
2944 fWithoutAlpha := tfLuminance4;
2945 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
2948 constructor TfdLuminance6Alpha2.Create;
2951 fFormat := tfLuminance6Alpha2;
2952 fWithAlpha := tfLuminance6Alpha2;
2953 fWithoutAlpha := tfLuminance8;
2954 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
2957 constructor TfdLuminance8Alpha8.Create;
2960 fFormat := tfLuminance8Alpha8;
2961 fWithAlpha := tfLuminance8Alpha8;
2962 fWithoutAlpha := tfLuminance8;
2963 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
2966 constructor TfdLuminance12Alpha4.Create;
2969 fFormat := tfLuminance12Alpha4;
2970 fWithAlpha := tfLuminance12Alpha4;
2971 fWithoutAlpha := tfLuminance12;
2972 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
2975 constructor TfdLuminance12Alpha12.Create;
2978 fFormat := tfLuminance12Alpha12;
2979 fWithAlpha := tfLuminance12Alpha12;
2980 fWithoutAlpha := tfLuminance12;
2981 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
2984 constructor TfdLuminance16Alpha16.Create;
2987 fFormat := tfLuminance16Alpha16;
2988 fWithAlpha := tfLuminance16Alpha16;
2989 fWithoutAlpha := tfLuminance16;
2990 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
2993 constructor TfdR3G3B2.Create;
2996 fFormat := tfR3G3B2;
2997 fWithAlpha := tfRGBA2;
2998 fWithoutAlpha := tfR3G3B2;
3005 fglFormat := GL_RGB;
3006 fglInternalFormat := GL_R3_G3_B2;
3007 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3010 constructor TfdRGB4.Create;
3014 fWithAlpha := tfRGBA4;
3015 fWithoutAlpha := tfRGB4;
3016 fRGBInverted := tfBGR4;
3023 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3024 fglInternalFormat := GL_RGB4;
3025 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3028 constructor TfdR5G6B5.Create;
3031 fFormat := tfR5G6B5;
3032 fWithAlpha := tfRGBA4;
3033 fWithoutAlpha := tfR5G6B5;
3034 fRGBInverted := tfB5G6R5;
3041 fglFormat := GL_RGB;
3042 fglInternalFormat := GL_RGB565;
3043 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3046 constructor TfdRGB5.Create;
3050 fWithAlpha := tfRGB5A1;
3051 fWithoutAlpha := tfRGB5;
3052 fRGBInverted := tfBGR5;
3059 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3060 fglInternalFormat := GL_RGB5;
3061 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3064 constructor TfdRGB8.Create;
3068 fWithAlpha := tfRGBA8;
3069 fWithoutAlpha := tfRGB8;
3070 fRGBInverted := tfBGR8;
3071 fglInternalFormat := GL_RGB8;
3074 constructor TfdRGB10.Create;
3078 fWithAlpha := tfRGB10A2;
3079 fWithoutAlpha := tfRGB10;
3080 fRGBInverted := tfBGR10;
3087 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3088 fglInternalFormat := GL_RGB10;
3089 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3092 constructor TfdRGB12.Create;
3096 fWithAlpha := tfRGBA12;
3097 fWithoutAlpha := tfRGB12;
3098 fRGBInverted := tfBGR12;
3099 fglInternalFormat := GL_RGB12;
3102 constructor TfdRGB16.Create;
3106 fWithAlpha := tfRGBA16;
3107 fWithoutAlpha := tfRGB16;
3108 fRGBInverted := tfBGR16;
3109 fglInternalFormat := GL_RGB16;
3112 constructor TfdRGBA2.Create;
3116 fWithAlpha := tfRGBA2;
3117 fWithoutAlpha := tfR3G3B2;
3118 fRGBInverted := tfBGRA2;
3119 fglInternalFormat := GL_RGBA2;
3122 constructor TfdRGBA4.Create;
3126 fWithAlpha := tfRGBA4;
3127 fWithoutAlpha := tfRGB4;
3128 fRGBInverted := tfBGRA4;
3137 fglFormat := GL_RGBA;
3138 fglInternalFormat := GL_RGBA4;
3139 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3142 constructor TfdRGB5A1.Create;
3145 fFormat := tfRGB5A1;
3146 fWithAlpha := tfRGB5A1;
3147 fWithoutAlpha := tfRGB5;
3148 fRGBInverted := tfBGR5A1;
3157 fglFormat := GL_RGBA;
3158 fglInternalFormat := GL_RGB5_A1;
3159 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3162 constructor TfdRGBA8.Create;
3166 fWithAlpha := tfRGBA8;
3167 fWithoutAlpha := tfRGB8;
3168 fRGBInverted := tfBGRA8;
3169 fglInternalFormat := GL_RGBA8;
3172 constructor TfdRGB10A2.Create;
3175 fFormat := tfRGB10A2;
3176 fWithAlpha := tfRGB10A2;
3177 fWithoutAlpha := tfRGB10;
3178 fRGBInverted := tfBGR10A2;
3187 fglFormat := GL_RGBA;
3188 fglInternalFormat := GL_RGB10_A2;
3189 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3192 constructor TfdRGBA12.Create;
3195 fFormat := tfRGBA12;
3196 fWithAlpha := tfRGBA12;
3197 fWithoutAlpha := tfRGB12;
3198 fRGBInverted := tfBGRA12;
3199 fglInternalFormat := GL_RGBA12;
3202 constructor TfdRGBA16.Create;
3205 fFormat := tfRGBA16;
3206 fWithAlpha := tfRGBA16;
3207 fWithoutAlpha := tfRGB16;
3208 fRGBInverted := tfBGRA16;
3209 fglInternalFormat := GL_RGBA16;
3212 constructor TfdBGR4.Create;
3217 fWithAlpha := tfBGRA4;
3218 fWithoutAlpha := tfBGR4;
3219 fRGBInverted := tfRGB4;
3228 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3229 fglInternalFormat := GL_RGB4;
3230 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3233 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3234 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3235 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3236 constructor TfdB5G6R5.Create;
3239 fFormat := tfB5G6R5;
3240 fWithAlpha := tfBGRA4;
3241 fWithoutAlpha := tfB5G6R5;
3242 fRGBInverted := tfR5G6B5;
3249 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3250 fglInternalFormat := GL_RGB8;
3251 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3254 constructor TfdBGR5.Create;
3259 fWithAlpha := tfBGR5A1;
3260 fWithoutAlpha := tfBGR5;
3261 fRGBInverted := tfRGB5;
3270 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3271 fglInternalFormat := GL_RGB5;
3272 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3275 constructor TfdBGR8.Create;
3279 fWithAlpha := tfBGRA8;
3280 fWithoutAlpha := tfBGR8;
3281 fRGBInverted := tfRGB8;
3282 fglInternalFormat := GL_RGB8;
3285 constructor TfdBGR10.Create;
3289 fWithAlpha := tfBGR10A2;
3290 fWithoutAlpha := tfBGR10;
3291 fRGBInverted := tfRGB10;
3300 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3301 fglInternalFormat := GL_RGB10;
3302 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3305 constructor TfdBGR12.Create;
3309 fWithAlpha := tfBGRA12;
3310 fWithoutAlpha := tfBGR12;
3311 fRGBInverted := tfRGB12;
3312 fglInternalFormat := GL_RGB12;
3315 constructor TfdBGR16.Create;
3319 fWithAlpha := tfBGRA16;
3320 fWithoutAlpha := tfBGR16;
3321 fRGBInverted := tfRGB16;
3322 fglInternalFormat := GL_RGB16;
3325 constructor TfdBGRA2.Create;
3329 fWithAlpha := tfBGRA4;
3330 fWithoutAlpha := tfBGR4;
3331 fRGBInverted := tfRGBA2;
3332 fglInternalFormat := GL_RGBA2;
3335 constructor TfdBGRA4.Create;
3339 fWithAlpha := tfBGRA4;
3340 fWithoutAlpha := tfBGR4;
3341 fRGBInverted := tfRGBA4;
3350 fglFormat := GL_BGRA;
3351 fglInternalFormat := GL_RGBA4;
3352 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3355 constructor TfdBGR5A1.Create;
3358 fFormat := tfBGR5A1;
3359 fWithAlpha := tfBGR5A1;
3360 fWithoutAlpha := tfBGR5;
3361 fRGBInverted := tfRGB5A1;
3370 fglFormat := GL_BGRA;
3371 fglInternalFormat := GL_RGB5_A1;
3372 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3375 constructor TfdBGRA8.Create;
3379 fWithAlpha := tfBGRA8;
3380 fWithoutAlpha := tfBGR8;
3381 fRGBInverted := tfRGBA8;
3382 fglInternalFormat := GL_RGBA8;
3385 constructor TfdBGR10A2.Create;
3388 fFormat := tfBGR10A2;
3389 fWithAlpha := tfBGR10A2;
3390 fWithoutAlpha := tfBGR10;
3391 fRGBInverted := tfRGB10A2;
3400 fglFormat := GL_BGRA;
3401 fglInternalFormat := GL_RGB10_A2;
3402 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3405 constructor TfdBGRA12.Create;
3408 fFormat := tfBGRA12;
3409 fWithAlpha := tfBGRA12;
3410 fWithoutAlpha := tfBGR12;
3411 fRGBInverted := tfRGBA12;
3412 fglInternalFormat := GL_RGBA12;
3415 constructor TfdBGRA16.Create;
3418 fFormat := tfBGRA16;
3419 fWithAlpha := tfBGRA16;
3420 fWithoutAlpha := tfBGR16;
3421 fRGBInverted := tfRGBA16;
3422 fglInternalFormat := GL_RGBA16;
3425 constructor TfdDepth16.Create;
3428 fFormat := tfDepth16;
3429 fWithAlpha := tfEmpty;
3430 fWithoutAlpha := tfDepth16;
3431 fglInternalFormat := GL_DEPTH_COMPONENT16;
3434 constructor TfdDepth24.Create;
3437 fFormat := tfDepth24;
3438 fWithAlpha := tfEmpty;
3439 fWithoutAlpha := tfDepth24;
3440 fglInternalFormat := GL_DEPTH_COMPONENT24;
3443 constructor TfdDepth32.Create;
3446 fFormat := tfDepth32;
3447 fWithAlpha := tfEmpty;
3448 fWithoutAlpha := tfDepth32;
3449 fglInternalFormat := GL_DEPTH_COMPONENT32;
3452 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3453 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3454 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3455 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3457 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3460 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
3462 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3465 constructor TfdS3tcDtx1RGBA.Create;
3468 fFormat := tfS3tcDtx1RGBA;
3469 fWithAlpha := tfS3tcDtx1RGBA;
3470 fUncompressed := tfRGB5A1;
3472 fIsCompressed := true;
3473 fglFormat := GL_COMPRESSED_RGBA;
3474 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3475 fglDataFormat := GL_UNSIGNED_BYTE;
3478 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3479 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3480 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3481 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3483 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3486 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
3488 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3491 constructor TfdS3tcDtx3RGBA.Create;
3494 fFormat := tfS3tcDtx3RGBA;
3495 fWithAlpha := tfS3tcDtx3RGBA;
3496 fUncompressed := tfRGBA8;
3498 fIsCompressed := true;
3499 fglFormat := GL_COMPRESSED_RGBA;
3500 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3501 fglDataFormat := GL_UNSIGNED_BYTE;
3504 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3505 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3506 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3507 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3509 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3512 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
3514 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3517 constructor TfdS3tcDtx5RGBA.Create;
3520 fFormat := tfS3tcDtx3RGBA;
3521 fWithAlpha := tfS3tcDtx3RGBA;
3522 fUncompressed := tfRGBA8;
3524 fIsCompressed := true;
3525 fglFormat := GL_COMPRESSED_RGBA;
3526 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3527 fglDataFormat := GL_UNSIGNED_BYTE;
3530 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3531 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3532 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3533 class procedure TFormatDescriptor.Init;
3535 if not Assigned(FormatDescriptorCS) then
3536 FormatDescriptorCS := TCriticalSection.Create;
3539 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3540 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3542 FormatDescriptorCS.Enter;
3544 result := FormatDescriptors[aFormat];
3545 if not Assigned(result) then begin
3546 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3547 FormatDescriptors[aFormat] := result;
3550 FormatDescriptorCS.Leave;
3554 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3555 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3557 result := Get(Get(aFormat).WithAlpha);
3560 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3561 class procedure TFormatDescriptor.Clear;
3565 FormatDescriptorCS.Enter;
3567 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3568 FreeAndNil(FormatDescriptors[f]);
3570 FormatDescriptorCS.Leave;
3574 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3575 class procedure TFormatDescriptor.Finalize;
3578 FreeAndNil(FormatDescriptorCS);
3581 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3582 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3583 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3584 procedure TbmpBitfieldFormat.SetRedMask(const aValue: UInt64);
3586 Update(aValue, fRange.r, fShift.r);
3589 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3590 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: UInt64);
3592 Update(aValue, fRange.g, fShift.g);
3595 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3596 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: UInt64);
3598 Update(aValue, fRange.b, fShift.b);
3601 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3602 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: UInt64);
3604 Update(aValue, fRange.a, fShift.a);
3607 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3608 procedure TbmpBitfieldFormat.Update(aMask: UInt64; out aRange: Cardinal; out
3615 while (aMask > 0) and ((aMask and 1) = 0) do begin
3617 aMask := aMask shr 1;
3620 while (aMask > 0) do begin
3621 aRange := aRange shl 1;
3622 aMask := aMask shr 1;
3626 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3629 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3630 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3638 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3639 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3640 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3641 ((aPixel.Data.a and fRange.a) shl fShift.a);
3642 s := Round(fPixelSize);
3645 2: PWord(aData)^ := data;
3646 4: PCardinal(aData)^ := data;
3647 8: PUInt64(aData)^ := data;
3649 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3654 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3655 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
3662 s := Round(fPixelSize);
3665 2: data := PWord(aData)^;
3666 4: data := PCardinal(aData)^;
3667 8: data := PUInt64(aData)^;
3669 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3672 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3676 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3677 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3678 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3679 procedure TbmpColorTableFormat.CreateColorTable;
3685 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3686 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3688 if (Format = tfLuminance4) then
3689 SetLength(fColorTable, 16)
3691 SetLength(fColorTable, 256);
3695 for i := 0 to High(fColorTable) do begin
3696 fColorTable[i].r := 16 * i;
3697 fColorTable[i].g := 16 * i;
3698 fColorTable[i].b := 16 * i;
3699 fColorTable[i].a := 0;
3704 for i := 0 to High(fColorTable) do begin
3705 fColorTable[i].r := i;
3706 fColorTable[i].g := i;
3707 fColorTable[i].b := i;
3708 fColorTable[i].a := 0;
3713 for i := 0 to High(fColorTable) do begin
3714 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3715 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3716 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3717 fColorTable[i].a := 0;
3723 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3724 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3728 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3729 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3733 if (aMapData = nil) then
3735 d := LuminanceWeight(aPixel) and Range.r;
3736 aData^ := aData^ or (d shl (4 - PtrInt(aMapData)));
3738 if (PtrInt(aMapData) >= 8) then begin
3745 aData^ := LuminanceWeight(aPixel) and Range.r;
3751 ((aPixel.Data.r and Range.r) shl Shift.r) or
3752 ((aPixel.Data.g and Range.g) shl Shift.g) or
3753 ((aPixel.Data.b and Range.b) shl Shift.b));
3759 procedure TbmpColorTableFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
3768 s := Trunc(fPixelSize);
3769 f := fPixelSize - s;
3770 bits := Round(8 * f);
3772 0: idx := (aData^ shr (8 - bits - PtrInt(aMapData))) and ((1 shl bits) - 1);
3774 2: idx := PWord(aData)^;
3775 4: idx := PCardinal(aData)^;
3776 8: idx := PUInt64(aData)^;
3778 raise EglBitmapException.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3780 if (idx >= Length(fColorTable)) then
3781 raise EglBitmapException.CreateFmt('invalid color index: %d', [idx]);
3782 with fColorTable[idx] do begin
3788 inc(aMapData, bits);
3789 if (PtrInt(aMapData) >= 8) then begin
3796 destructor TbmpColorTableFormat.Destroy;
3798 SetLength(fColorTable, 0);
3802 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3803 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3804 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3805 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
3807 with aFuncRec do begin
3808 if (Source.Range.r > 0) then
3809 Dest.Data.r := Source.Data.r;
3810 if (Source.Range.g > 0) then
3811 Dest.Data.g := Source.Data.g;
3812 if (Source.Range.b > 0) then
3813 Dest.Data.b := Source.Data.b;
3814 if (Source.Range.a > 0) then
3815 Dest.Data.a := Source.Data.a;
3819 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3820 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3824 with aFuncRec do begin
3826 if (Source.Range.arr[i] > 0) then
3827 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
3832 TShiftData = packed record
3834 0: (r, g, b, a: SmallInt);
3835 1: (arr: array[0..3] of SmallInt);
3837 PShiftData = ^TShiftData;
3839 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3840 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3846 if (Source.Range.arr[i] > 0) then
3847 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
3850 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3851 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
3853 with aFuncRec do begin
3854 Dest.Data.r := Source.Data.r;
3855 Dest.Data.g := Source.Data.g;
3856 Dest.Data.b := Source.Data.b;
3857 Dest.Data.a := Source.Data.a;
3858 if (Args and $1 > 0) then begin
3859 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
3860 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
3861 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
3863 if (Args and $2 > 0) then begin
3864 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
3869 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3870 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
3874 with aFuncRec do begin
3876 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
3880 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3881 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3885 with FuncRec do begin
3886 if (FuncRec.Args = 0) then begin //source has no alpha
3888 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
3889 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
3890 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
3891 Dest.Data.a := Round(Dest.Range.a * Temp);
3893 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
3897 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3898 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3900 PglBitmapPixelData = ^TglBitmapPixelData;
3902 with FuncRec do begin
3903 Dest.Data.r := Source.Data.r;
3904 Dest.Data.g := Source.Data.g;
3905 Dest.Data.b := Source.Data.b;
3907 with PglBitmapPixelData(Args)^ do
3908 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
3909 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
3910 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
3913 Dest.Data.a := Dest.Range.a;
3917 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3918 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3920 PglBitmapPixelData = ^TglBitmapPixelData;
3922 with FuncRec do begin
3923 Dest.Data.r := Source.Data.r;
3924 Dest.Data.g := Source.Data.g;
3925 Dest.Data.b := Source.Data.b;
3926 Dest.Data.a := PCardinal(Args)^;
3930 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3931 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
3934 TRGBPix = array [0..2] of byte;
3938 while aWidth > 0 do begin
3939 Temp := PRGBPix(aData)^[0];
3940 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
3941 PRGBPix(aData)^[2] := Temp;
3951 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3952 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3953 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3954 function TglBitmap.GetWidth: Integer;
3956 if (ffX in fDimension.Fields) then
3957 result := fDimension.X
3962 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3963 function TglBitmap.GetHeight: Integer;
3965 if (ffY in fDimension.Fields) then
3966 result := fDimension.Y
3971 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3972 function TglBitmap.GetFileWidth: Integer;
3974 result := Max(1, Width);
3977 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3978 function TglBitmap.GetFileHeight: Integer;
3980 result := Max(1, Height);
3983 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3984 procedure TglBitmap.SetCustomData(const aValue: Pointer);
3986 if fCustomData = aValue then
3988 fCustomData := aValue;
3991 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3992 procedure TglBitmap.SetCustomName(const aValue: String);
3994 if fCustomName = aValue then
3996 fCustomName := aValue;
3999 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4000 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4002 if fCustomNameW = aValue then
4004 fCustomNameW := aValue;
4007 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4008 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4010 if fDeleteTextureOnFree = aValue then
4012 fDeleteTextureOnFree := aValue;
4015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4016 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4018 if fFormat = aValue then
4020 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4021 raise EglBitmapUnsupportedFormatFormat.Create('SetInternalFormat - ' + UNSUPPORTED_FORMAT);
4022 SetDataPointer(Data, aValue, Width, Height);
4025 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4026 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4028 if fFreeDataAfterGenTexture = aValue then
4030 fFreeDataAfterGenTexture := aValue;
4033 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4034 procedure TglBitmap.SetID(const aValue: Cardinal);
4036 if fID = aValue then
4041 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4042 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4044 if fMipMap = aValue then
4049 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4050 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4052 if fTarget = aValue then
4057 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4058 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4060 MaxAnisotropic: Integer;
4062 fAnisotropic := aValue;
4063 if (ID > 0) then begin
4064 if GL_EXT_texture_filter_anisotropic then begin
4065 if fAnisotropic > 0 then begin
4067 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4068 if aValue > MaxAnisotropic then
4069 fAnisotropic := MaxAnisotropic;
4070 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4078 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4079 procedure TglBitmap.CreateID;
4082 glDeleteTextures(1, @fID);
4083 glGenTextures(1, @fID);
4087 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4088 procedure TglBitmap.SetupParameters(var aBuildWithGlu: Boolean);
4090 // Set Up Parameters
4091 SetWrap(fWrapS, fWrapT, fWrapR);
4092 SetFilter(fFilterMin, fFilterMag);
4093 SetAnisotropic(fAnisotropic);
4094 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4096 // Mip Maps Generation Mode
4097 aBuildWithGlu := false;
4098 if (MipMap = mmMipmap) then begin
4099 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4100 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4102 aBuildWithGlu := true;
4103 end else if (MipMap = mmMipmapGlu) then
4104 aBuildWithGlu := true;
4107 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4108 procedure TglBitmap.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
4109 const aWidth: Integer; const aHeight: Integer);
4113 if (Data <> aData) then begin
4114 if (Assigned(Data)) then
4119 FillChar(fDimension, SizeOf(fDimension), 0);
4120 if not Assigned(fData) then begin
4125 if aWidth <> -1 then begin
4126 fDimension.Fields := fDimension.Fields + [ffX];
4127 fDimension.X := aWidth;
4130 if aHeight <> -1 then begin
4131 fDimension.Fields := fDimension.Fields + [ffY];
4132 fDimension.Y := aHeight;
4135 s := TFormatDescriptor.Get(aFormat).PixelSize;
4137 fPixelSize := Ceil(s);
4138 fRowSize := Ceil(s * aWidth);
4142 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4143 function TglBitmap.FlipHorz: Boolean;
4148 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4149 function TglBitmap.FlipVert: Boolean;
4154 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4155 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4156 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4157 procedure TglBitmap.AfterConstruction;
4159 inherited AfterConstruction;
4163 fIsResident := false;
4165 fFormat := glBitmapGetDefaultFormat;
4166 fMipMap := glBitmapDefaultMipmap;
4167 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4168 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4170 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4171 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4174 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4175 procedure TglBitmap.BeforeDestruction;
4177 SetDataPointer(nil, tfEmpty);
4178 if (fID > 0) and fDeleteTextureOnFree then
4179 glDeleteTextures(1, @fID);
4180 inherited BeforeDestruction;
4183 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4184 procedure TglBitmap.LoadFromFile(const aFilename: String);
4188 if not FileExists(aFilename) then
4189 raise EglBitmapException.Create('file does not exist: ' + aFilename);
4190 fFilename := aFilename;
4191 fs := TFileStream.Create(fFilename, fmOpenRead);
4200 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4201 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4203 {$IFDEF GLB_SUPPORT_PNG_READ}
4204 if not LoadPNG(aStream) then
4206 {$IFDEF GLB_SUPPORT_JPEG_READ}
4207 if not LoadJPEG(aStream) then
4209 if not LoadDDS(aStream) then
4210 if not LoadTGA(aStream) then
4211 if not LoadBMP(aStream) then
4212 raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4216 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4217 const aFormat: TglBitmapFormat; const aArgs: PtrInt);
4222 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4223 GetMem(tmpData, size);
4225 FillChar(tmpData^, size, #$FF);
4226 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y);
4231 AddFunc(Self, aFunc, false, Format, aArgs);
4235 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4236 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
4238 rs: TResourceStream;
4243 if not Assigned(ResType) then begin
4244 TempPos := Pos('.', Resource);
4245 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
4246 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
4247 TempResType := PChar(ResTypeStr);
4249 TempResType := ResType
4251 rs := TResourceStream.Create(Instance, Resource, TempResType);
4259 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4260 procedure TglBitmap.LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4262 rs: TResourceStream;
4264 rs := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
4273 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4274 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4278 fs := TFileStream.Create(aFileName, fmCreate);
4281 SaveToStream(fs, aFileType);
4287 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4288 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4291 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4292 ftPNG: SavePng(aStream);
4294 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4295 ftJPEG: SaveJPEG(aStream);
4297 ftDDS: SaveDDS(aStream);
4298 ftTGA: SaveTGA(aStream);
4299 ftBMP: SaveBMP(aStream);
4303 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4304 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt): Boolean;
4306 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4309 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4310 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4311 const aFormat: TglBitmapFormat; const aArgs: PtrInt): Boolean;
4313 DestData, TmpData, SourceData: pByte;
4314 TempHeight, TempWidth: Integer;
4315 SourceFD, DestFD: TFormatDescriptor;
4316 SourceMD, DestMD: Pointer;
4318 FuncRec: TglBitmapFunctionRec;
4320 Assert(Assigned(Data));
4321 Assert(Assigned(aSource));
4322 Assert(Assigned(aSource.Data));
4325 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4326 SourceFD := TFormatDescriptor.Get(aSource.Format);
4327 DestFD := TFormatDescriptor.Get(aFormat);
4329 // inkompatible Formats so CreateTemp
4330 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4331 aCreateTemp := true;
4334 TempHeight := Max(1, aSource.Height);
4335 TempWidth := Max(1, aSource.Width);
4337 FuncRec.Sender := Self;
4338 FuncRec.Args := aArgs;
4341 if aCreateTemp then begin
4342 GetMem(TmpData, TFormatDescriptor.Get(aFormat).GetSize(TempWidth, TempHeight));
4343 DestData := TmpData;
4348 SourceFD.PreparePixel(FuncRec.Source);
4349 DestFD.PreparePixel (FuncRec.Dest);
4351 SourceMD := SourceFD.CreateMappingData;
4352 DestMD := DestFD.CreateMappingData;
4354 FuncRec.Size := aSource.Dimension;
4355 FuncRec.Position.Fields := FuncRec.Size.Fields;
4358 SourceData := aSource.Data;
4359 FuncRec.Position.Y := 0;
4360 while FuncRec.Position.Y < TempHeight do begin
4361 FuncRec.Position.X := 0;
4362 while FuncRec.Position.X < TempWidth do begin
4363 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4365 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4366 inc(FuncRec.Position.X);
4368 inc(FuncRec.Position.Y);
4371 // Updating Image or InternalFormat
4373 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height)
4374 else if (aFormat <> fFormat) then
4379 SourceFD.FreeMappingData(SourceMD);
4380 DestFD.FreeMappingData(DestMD);
4391 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4392 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4394 Row, RowSize: Integer;
4395 SourceData, TmpData: PByte;
4397 Pix: TglBitmapPixelData;
4398 FormatDesc: TglBitmapFormatDescriptor;
4400 function GetRowPointer(Row: Integer): pByte;
4402 result := Surface.pixels;
4403 Inc(result, Row * RowSize);
4410 if not FormatIsUncompressed(InternalFormat) then
4411 raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
4414 FormatDesc := FORMAT_DESCRIPTORS[Format];
4415 if Assigned(Data) then begin
4416 case Trunc(FormatDesc.GetSize) of
4422 raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
4424 FormatDesc.PreparePixel(Pix);
4425 with Pix.PixelDesc do
4426 Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4427 RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift);
4430 RowSize := Ceil(FileWidth * FormatDesc.GetSize);
4432 for Row := 0 to FileHeight -1 do begin
4433 TmpData := GetRowPointer(Row);
4434 if Assigned(TmpData) then begin
4435 Move(SourceData^, TmpData^, RowSize);
4436 inc(SourceData, RowSize);
4443 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4444 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4446 pSource, pData, pTempData: PByte;
4447 Row, RowSize, TempWidth, TempHeight: Integer;
4448 IntFormat, f: TglBitmapInternalFormat;
4449 FormatDesc: TglBitmapFormatDescriptor;
4451 function GetRowPointer(Row: Integer): pByte;
4453 result := Surface^.pixels;
4454 Inc(result, Row * RowSize);
4459 if (Assigned(Surface)) then begin
4460 with Surface^.format^ do begin
4461 IntFormat := tfEmpty;
4462 for f := Low(f) to High(f) do begin
4463 if FORMAT_DESCRIPTORS[f].MaskMatch(RMask, GMask, BMask, AMask) then begin
4468 if (IntFormat = tfEmpty) then
4469 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4472 FormatDesc := FORMAT_DESCRIPTORS[IntFormat];
4473 TempWidth := Surface^.w;
4474 TempHeight := Surface^.h;
4475 RowSize := Trunc(TempWidth * FormatDesc.GetSize);
4476 GetMem(pData, TempHeight * RowSize);
4479 for Row := 0 to TempHeight -1 do begin
4480 pSource := GetRowPointer(Row);
4481 if (Assigned(pSource)) then begin
4482 Move(pSource^, pTempData^, RowSize);
4483 Inc(pTempData, RowSize);
4486 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
4495 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4496 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4498 Row, Col, AlphaInterleave: Integer;
4499 pSource, pDest: PByte;
4501 function GetRowPointer(Row: Integer): pByte;
4503 result := aSurface.pixels;
4504 Inc(result, Row * Width);
4509 if Assigned(Data) then begin
4510 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4511 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4513 AlphaInterleave := 0;
4516 AlphaInterleave := 1;
4518 AlphaInterleave := 3;
4522 for Row := 0 to Height -1 do begin
4523 pDest := GetRowPointer(Row);
4524 if Assigned(pDest) then begin
4525 for Col := 0 to Width -1 do begin
4526 Inc(pSource, AlphaInterleave);
4538 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4539 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4543 bmp := TglBitmap2D.Create;
4545 bmp.AssignFromSurface(Surface);
4546 result := AddAlphaFromGlBitmap(bmp, Func, CustomData);
4554 //TODO rework & test
4555 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4556 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4559 pSource, pData: PByte;
4562 if Assigned(Data) then begin
4563 if Assigned(aBitmap) then begin
4564 aBitmap.Width := Width;
4565 aBitmap.Height := Height;
4568 tfAlpha8, ifLuminance, ifDepth8:
4570 Bitmap.PixelFormat := pf8bit;
4571 Bitmap.Palette := CreateGrayPalette;
4574 Bitmap.PixelFormat := pf15bit;
4576 Bitmap.PixelFormat := pf16bit;
4578 Bitmap.PixelFormat := pf24bit;
4580 Bitmap.PixelFormat := pf32bit;
4582 raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
4586 for Row := 0 to FileHeight -1 do begin
4587 pData := Bitmap.Scanline[Row];
4589 Move(pSource^, pData^, fRowSize);
4590 Inc(pSource, fRowSize);
4592 // swap RGB(A) to BGR(A)
4593 if InternalFormat in [ifRGB8, ifRGBA8] then
4594 SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8);
4602 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4603 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4605 pSource, pData, pTempData: PByte;
4606 Row, RowSize, TempWidth, TempHeight: Integer;
4607 IntFormat: TglBitmapInternalFormat;
4611 if (Assigned(Bitmap)) then begin
4612 case Bitmap.PixelFormat of
4614 IntFormat := ifLuminance;
4616 IntFormat := ifRGB5A1;
4618 IntFormat := ifR5G6B5;
4620 IntFormat := ifBGR8;
4622 IntFormat := ifBGRA8;
4624 raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
4627 TempWidth := Bitmap.Width;
4628 TempHeight := Bitmap.Height;
4630 RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
4632 GetMem(pData, TempHeight * RowSize);
4636 for Row := 0 to TempHeight -1 do begin
4637 pSource := Bitmap.Scanline[Row];
4639 if (Assigned(pSource)) then begin
4640 Move(pSource^, pTempData^, RowSize);
4641 Inc(pTempData, RowSize);
4645 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
4655 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4656 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4658 Row, Col, AlphaInterleave: Integer;
4659 pSource, pDest: PByte;
4663 if Assigned(Data) then begin
4664 if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin
4665 if Assigned(Bitmap) then begin
4666 Bitmap.PixelFormat := pf8bit;
4667 Bitmap.Palette := CreateGrayPalette;
4668 Bitmap.Width := Width;
4669 Bitmap.Height := Height;
4671 case InternalFormat of
4673 AlphaInterleave := 1;
4675 AlphaInterleave := 3;
4677 AlphaInterleave := 0;
4683 for Row := 0 to Height -1 do begin
4684 pDest := Bitmap.Scanline[Row];
4686 if Assigned(pDest) then begin
4687 for Col := 0 to Width -1 do begin
4688 Inc(pSource, AlphaInterleave);
4702 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4703 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4707 tex := TglBitmap2D.Create;
4709 tex.AssignFromBitmap(Bitmap);
4710 result := AddAlphaFromglBitmap(tex, Func, CustomData);
4716 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4717 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar;
4718 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4720 RS: TResourceStream;
4725 if Assigned(ResType) then
4726 TempResType := ResType
4729 TempPos := Pos('.', Resource);
4730 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
4731 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
4732 TempResType := PChar(ResTypeStr);
4735 RS := TResourceStream.Create(Instance, Resource, TempResType);
4737 result := AddAlphaFromStream(RS, Func, CustomData);
4743 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4744 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
4745 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4747 RS: TResourceStream;
4749 RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
4751 result := AddAlphaFromStream(RS, Func, CustomData);
4758 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4759 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4762 if not FormatIsUncompressed(InternalFormat) then
4763 raise EglBitmapUnsupportedFormatFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_FORMAT);
4765 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
4768 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4769 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4773 FS := TFileStream.Create(FileName, fmOpenRead);
4775 result := AddAlphaFromStream(FS, aFunc, aArgs);
4781 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4782 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4786 tex := TglBitmap2D.Create(aStream);
4788 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4794 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4795 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4797 DestData, DestData2, SourceData: pByte;
4798 TempHeight, TempWidth: Integer;
4799 SourceFD, DestFD: TFormatDescriptor;
4800 SourceMD, DestMD, DestMD2: Pointer;
4802 FuncRec: TglBitmapFunctionRec;
4806 Assert(Assigned(Data));
4807 Assert(Assigned(aBitmap));
4808 Assert(Assigned(aBitmap.Data));
4810 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
4811 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
4812 if not Assigned(aFunc) then
4813 aFunc := glBitmapAlphaFunc;
4815 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
4816 DestFD := TFormatDescriptor.Get(Format);
4819 TempHeight := aBitmap.FileHeight;
4820 TempWidth := aBitmap.FileWidth;
4822 FuncRec.Sender := Self;
4823 FuncRec.Args := aArgs;
4824 FuncRec.Size := Dimension;
4825 FuncRec.Position.Fields := FuncRec.Size.Fields;
4826 FuncRec.Args := PtrInt(SourceFD.HasAlpha) and 1;
4830 SourceData := aBitmap.Data;
4833 SourceFD.PreparePixel(FuncRec.Source);
4834 DestFD.PreparePixel (FuncRec.Dest);
4836 SourceMD := SourceFD.CreateMappingData;
4837 DestMD := DestFD.CreateMappingData;
4838 DestMD2 := DestFD.CreateMappingData;
4840 FuncRec.Position.Y := 0;
4841 while FuncRec.Position.Y < TempHeight do begin
4842 FuncRec.Position.X := 0;
4843 while FuncRec.Position.X < TempWidth do begin
4844 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4845 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
4847 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
4848 inc(FuncRec.Position.X);
4850 inc(FuncRec.Position.Y);
4853 SourceFD.FreeMappingData(SourceMD);
4854 DestFD.FreeMappingData(DestMD);
4855 DestFD.FreeMappingData(DestMD2);
4860 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4861 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
4863 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
4866 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4867 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
4869 PixelData: TglBitmapPixelData;
4871 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
4872 result := AddAlphaFromColorKeyFloat(
4873 aRed / PixelData.Range.r,
4874 aGreen / PixelData.Range.g,
4875 aBlue / PixelData.Range.b,
4876 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
4879 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4880 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
4882 values: array[0..2] of Single;
4885 PixelData: TglBitmapPixelData;
4887 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
4888 with PixelData do begin
4890 values[1] := aGreen;
4893 for i := 0 to 2 do begin
4894 tmp := Trunc(Range.arr[i] * aDeviation);
4895 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
4896 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
4901 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, PtrInt(@PixelData));
4904 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4905 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
4907 result := AddAlphaFromValueFloat(aAlpha / $FF);
4910 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4911 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
4913 PixelData: TglBitmapPixelData;
4915 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
4916 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
4919 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4920 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
4922 PixelData: TglBitmapPixelData;
4924 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
4926 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
4927 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, PtrInt(@PixelData.Data.a));
4930 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4931 function TglBitmap.RemoveAlpha: Boolean;
4933 FormatDesc: TFormatDescriptor;
4936 FormatDesc := TFormatDescriptor.Get(Format);
4937 if Assigned(Data) then begin
4938 if not ({FormatDesc.IsUncompressed or }FormatDesc.HasAlpha) then
4939 raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_FORMAT);
4940 result := ConvertTo(FormatDesc.WithoutAlpha);
4944 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4945 function TglBitmap.Clone: TglBitmap;
4952 Temp := (ClassType.Create as TglBitmap);
4954 // copy texture data if assigned
4955 if Assigned(Data) then begin
4956 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
4957 GetMem(TempPtr, Size);
4959 Move(Data^, TempPtr^, Size);
4960 Temp.SetDataPointer(TempPtr, Format, Width, Height);
4966 Temp.SetDataPointer(nil, Format, Width, Height);
4970 Temp.fTarget := Target;
4971 Temp.fFormat := Format;
4972 Temp.fMipMap := MipMap;
4973 Temp.fAnisotropic := Anisotropic;
4974 Temp.fBorderColor := fBorderColor;
4975 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
4976 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
4977 Temp.fFilterMin := fFilterMin;
4978 Temp.fFilterMag := fFilterMag;
4979 Temp.fWrapS := fWrapS;
4980 Temp.fWrapT := fWrapT;
4981 Temp.fWrapR := fWrapR;
4982 Temp.fFilename := fFilename;
4983 Temp.fCustomName := fCustomName;
4984 Temp.fCustomNameW := fCustomNameW;
4985 Temp.fCustomData := fCustomData;
4994 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4995 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
4997 SourceFD, DestFD: TFormatDescriptor;
4998 SourcePD, DestPD: TglBitmapPixelData;
4999 ShiftData: TShiftData;
5001 function CanCopyDirect: Boolean;
5004 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5005 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5006 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5007 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5010 function CanShift: Boolean;
5013 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5014 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5015 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5016 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5019 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5022 while (aSource > aDest) and (aSource > 0) do begin
5024 aSource := aSource shr 1;
5029 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5030 SourceFD := TFormatDescriptor.Get(Format);
5031 DestFD := TFormatDescriptor.Get(aFormat);
5033 SourceFD.PreparePixel(SourcePD);
5034 DestFD.PreparePixel (DestPD);
5036 if CanCopyDirect then
5037 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5038 else if CanShift then begin
5039 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5040 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5041 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5042 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5043 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, PtrInt(@ShiftData));
5045 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5050 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5051 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5053 if aUseRGB or aUseAlpha then
5054 AddFunc(glBitmapInvertFunc, false, ((PtrInt(aUseAlpha) and 1) shl 1) or (PtrInt(aUseRGB) and 1));
5057 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5058 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5060 fBorderColor[0] := aRed;
5061 fBorderColor[1] := aGreen;
5062 fBorderColor[2] := aBlue;
5063 fBorderColor[3] := aAlpha;
5064 if (ID > 0) then begin
5066 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5070 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5071 procedure TglBitmap.FreeData;
5073 SetDataPointer(nil, tfEmpty);
5076 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5077 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5078 const aAlpha: Byte);
5080 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5083 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5084 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5086 PixelData: TglBitmapPixelData;
5088 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5090 aRed / PixelData.Range.r,
5091 aGreen / PixelData.Range.g,
5092 aBlue / PixelData.Range.b,
5093 aAlpha / PixelData.Range.a);
5096 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5097 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5099 PixelData: TglBitmapPixelData;
5101 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5102 with PixelData do begin
5103 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5104 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5105 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5106 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5108 AddFunc(glBitmapFillWithColorFunc, false, PtrInt(@PixelData));
5111 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5112 procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal);
5117 fFilterMin := GL_NEAREST;
5119 fFilterMin := GL_LINEAR;
5120 GL_NEAREST_MIPMAP_NEAREST:
5121 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5122 GL_LINEAR_MIPMAP_NEAREST:
5123 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5124 GL_NEAREST_MIPMAP_LINEAR:
5125 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5126 GL_LINEAR_MIPMAP_LINEAR:
5127 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5129 raise EglBitmapException.Create('SetFilter - Unknow MIN filter.');
5135 fFilterMag := GL_NEAREST;
5137 fFilterMag := GL_LINEAR;
5139 raise EglBitmapException.Create('SetFilter - Unknow MAG filter.');
5143 if (ID > 0) then begin
5145 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5147 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5149 GL_NEAREST, GL_LINEAR:
5150 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5151 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5152 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5153 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5154 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5157 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5161 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5162 procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; const R: Cardinal);
5164 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5168 aTarget := GL_CLAMP;
5171 aTarget := GL_REPEAT;
5173 GL_CLAMP_TO_EDGE: begin
5174 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5175 aTarget := GL_CLAMP_TO_EDGE
5177 aTarget := GL_CLAMP;
5180 GL_CLAMP_TO_BORDER: begin
5181 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5182 aTarget := GL_CLAMP_TO_BORDER
5184 aTarget := GL_CLAMP;
5187 GL_MIRRORED_REPEAT: begin
5188 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5189 aTarget := GL_MIRRORED_REPEAT
5191 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5194 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).');
5199 CheckAndSetWrap(S, fWrapS);
5200 CheckAndSetWrap(T, fWrapT);
5201 CheckAndSetWrap(R, fWrapR);
5203 if (ID > 0) then begin
5205 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5206 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5207 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5211 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5212 procedure TglBitmap.GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData);
5215 if Assigned (fGetPixelFunc) then
5216 fGetPixelFunc(aPos, aPixel);
5220 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5221 procedure TglBitmap.SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData);
5224 if Assigned (fSetPixelFunc) then
5225 fSetPixelFuc(aPos, aPixel);
5229 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5230 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5232 if aEnableTextureUnit then
5235 glBindTexture(Target, ID);
5238 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5239 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5241 if aDisableTextureUnit then
5243 glBindTexture(Target, 0);
5246 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5247 constructor TglBitmap.Create;
5249 {$IFNDEF GLB_NO_NATIVE_GL}
5250 ReadOpenGLExtensions;
5252 if (ClassType = TglBitmap) then
5253 raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5257 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5258 constructor TglBitmap.Create(const aFileName: String);
5261 LoadFromFile(FileName);
5264 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5265 constructor TglBitmap.Create(const aStream: TStream);
5268 LoadFromStream(aStream);
5271 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5272 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
5278 TFormatDescriptor.Get(aFormat).GetSize(aSize);
5279 GetMem(Image, ImageSize);
5281 FillChar(Image^, ImageSize, #$FF);
5282 SetDataPointer(Image, aFormat, aSize.X, aSize.Y);
5289 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5290 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
5291 const aFunc: TglBitmapFunction; const aArgs: PtrInt);
5294 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5298 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5299 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5302 LoadFromResource(aInstance, aResource, aResType);
5305 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5306 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5309 LoadFromResourceID(aInstance, aResourceID, aResType);
5313 {$IFDEF GLB_SUPPORT_PNG_READ}
5314 {$IF DEFINED(GLB_SDL_IMAGE)}
5315 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5316 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5317 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5318 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5320 Surface: PSDL_Surface;
5324 RWops := glBitmapCreateRWops(aStream);
5326 if IMG_isPNG(RWops) > 0 then begin
5327 Surface := IMG_LoadPNG_RW(RWops);
5329 AssignFromSurface(Surface);
5332 SDL_FreeSurface(Surface);
5340 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5341 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5342 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5344 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5347 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5348 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5351 signature: array [0..7] of byte;
5353 png_info: png_infop;
5355 TempHeight, TempWidth: Integer;
5356 Format: TglBitmapInternalFormat;
5359 png_rows: array of pByte;
5360 Row, LineSize: Integer;
5364 if not init_libPNG then
5365 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5369 StreamPos := Stream.Position;
5370 Stream.Read(signature, 8);
5371 Stream.Position := StreamPos;
5373 if png_check_sig(@signature, 8) <> 0 then begin
5375 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5377 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5380 png_info := png_create_info_struct(png);
5381 if png_info = nil then begin
5382 png_destroy_read_struct(@png, nil, nil);
5383 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5386 // set read callback
5387 png_set_read_fn(png, stream, glBitmap_libPNG_read_func);
5389 // read informations
5390 png_read_info(png, png_info);
5393 TempHeight := png_get_image_height(png, png_info);
5394 TempWidth := png_get_image_width(png, png_info);
5397 case png_get_color_type(png, png_info) of
5398 PNG_COLOR_TYPE_GRAY:
5399 Format := tfLuminance8;
5400 PNG_COLOR_TYPE_GRAY_ALPHA:
5401 Format := tfLuminance8Alpha8;
5404 PNG_COLOR_TYPE_RGB_ALPHA:
5407 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5410 // cut upper 8 bit from 16 bit formats
5411 if png_get_bit_depth(png, png_info) > 8 then
5412 png_set_strip_16(png);
5414 // expand bitdepth smaller than 8
5415 if png_get_bit_depth(png, png_info) < 8 then
5416 png_set_expand(png);
5418 // allocating mem for scanlines
5419 LineSize := png_get_rowbytes(png, png_info);
5420 GetMem(png_data, TempHeight * LineSize);
5422 SetLength(png_rows, TempHeight);
5423 for Row := Low(png_rows) to High(png_rows) do begin
5424 png_rows[Row] := png_data;
5425 Inc(png_rows[Row], Row * LineSize);
5428 // read complete image into scanlines
5429 png_read_image(png, @png_rows[0]);
5432 png_read_end(png, png_info);
5434 // destroy read struct
5435 png_destroy_read_struct(@png, @png_info, nil);
5437 SetLength(png_rows, 0);
5440 SetDataPointer(png_data, Format, TempWidth, TempHeight);
5453 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5454 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5455 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5459 Header: Array[0..7] of Byte;
5460 Row, Col, PixSize, LineSize: Integer;
5461 NewImage, pSource, pDest, pAlpha: pByte;
5462 Format: TglBitmapInternalFormat;
5465 PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10);
5470 StreamPos := Stream.Position;
5471 Stream.Read(Header[0], SizeOf(Header));
5472 Stream.Position := StreamPos;
5474 {Test if the header matches}
5475 if Header = PngHeader then begin
5476 Png := TPNGObject.Create;
5478 Png.LoadFromStream(Stream);
5480 case Png.Header.ColorType of
5482 Format := ifLuminance;
5483 COLOR_GRAYSCALEALPHA:
5484 Format := ifLuminanceAlpha;
5490 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5493 PixSize := Trunc(FormatGetSize(Format));
5494 LineSize := Integer(Png.Header.Width) * PixSize;
5496 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5500 case Png.Header.ColorType of
5501 COLOR_RGB, COLOR_GRAYSCALE:
5503 for Row := 0 to Png.Height -1 do begin
5504 Move (Png.Scanline[Row]^, pDest^, LineSize);
5505 Inc(pDest, LineSize);
5508 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5510 PixSize := PixSize -1;
5512 for Row := 0 to Png.Height -1 do begin
5513 pSource := Png.Scanline[Row];
5514 pAlpha := pByte(Png.AlphaScanline[Row]);
5516 for Col := 0 to Png.Width -1 do begin
5517 Move (pSource^, pDest^, PixSize);
5518 Inc(pSource, PixSize);
5519 Inc(pDest, PixSize);
5528 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5531 SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height);
5546 {$IFDEF GLB_SUPPORT_PNG_WRITE}
5547 {$IFDEF GLB_LIB_PNG}
5548 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5549 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5551 TStream(png_get_io_ptr(png)).Write(buffer^, size);
5555 {$IF DEFINED(GLB_LIB_PNG)}
5556 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5557 procedure TglBitmap.SavePNG(const aStream: TStream);
5560 png_info: png_infop;
5561 png_rows: array of pByte;
5566 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
5567 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5569 if not init_libPNG then
5570 raise Exception.Create('SavePNG - unable to initialize libPNG.');
5573 case FInternalFormat of
5574 ifAlpha, ifLuminance, ifDepth8:
5575 ColorType := PNG_COLOR_TYPE_GRAY;
5577 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
5579 ColorType := PNG_COLOR_TYPE_RGB;
5581 ColorType := PNG_COLOR_TYPE_RGBA;
5583 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5585 LineSize := Trunc(FormatGetSize(FInternalFormat) * Width);
5587 // creating array for scanline
5588 SetLength(png_rows, Height);
5590 for Row := 0 to Height - 1 do begin
5591 png_rows[Row] := Data;
5592 Inc(png_rows[Row], Row * LineSize)
5596 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5598 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
5601 png_info := png_create_info_struct(png);
5602 if png_info = nil then begin
5603 png_destroy_write_struct(@png, nil);
5604 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
5607 // set read callback
5608 png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil);
5611 png_set_compression_level(png, 6);
5613 if InternalFormat in [ifBGR8, ifBGRA8] then
5616 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
5617 png_write_info(png, png_info);
5618 png_write_image(png, @png_rows[0]);
5619 png_write_end(png, png_info);
5620 png_destroy_write_struct(@png, @png_info);
5622 SetLength(png_rows, 0);
5629 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5630 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5631 procedure TglBitmap.SavePNG(const aStream: TStream);
5635 pSource, pDest: pByte;
5636 X, Y, PixSize: Integer;
5637 ColorType: Cardinal;
5643 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
5644 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5646 case FInternalFormat of
5647 ifAlpha, ifLuminance, ifDepth8: begin
5648 ColorType := COLOR_GRAYSCALE;
5652 ifLuminanceAlpha: begin
5653 ColorType := COLOR_GRAYSCALEALPHA;
5657 ifBGR8, ifRGB8: begin
5658 ColorType := COLOR_RGB;
5662 ifBGRA8, ifRGBA8: begin
5663 ColorType := COLOR_RGBALPHA;
5668 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5671 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
5675 for Y := 0 to Height -1 do begin
5676 pDest := png.ScanLine[Y];
5677 for X := 0 to Width -1 do begin
5678 Move(pSource^, pDest^, PixSize);
5679 Inc(pDest, PixSize);
5680 Inc(pSource, PixSize);
5682 png.AlphaScanline[Y]^[X] := pSource^;
5687 // convert RGB line to BGR
5688 if InternalFormat in [ifRGB8, ifRGBA8] then begin
5689 pTemp := png.ScanLine[Y];
5690 for X := 0 to Width -1 do begin
5691 Temp := pByteArray(pTemp)^[0];
5692 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
5693 pByteArray(pTemp)^[2] := Temp;
5700 Png.CompressionLevel := 6;
5701 Png.SaveToStream(Stream);
5709 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5710 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5711 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5712 {$IFDEF GLB_LIB_JPEG}
5714 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
5715 glBitmap_libJPEG_source_mgr = record
5716 pub: jpeg_source_mgr;
5719 SrcBuffer: array [1..4096] of byte;
5722 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
5723 glBitmap_libJPEG_dest_mgr = record
5724 pub: jpeg_destination_mgr;
5726 DestStream: TStream;
5727 DestBuffer: array [1..4096] of byte;
5730 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5732 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
5736 SetLength(Msg, 256);
5737 cinfo^.err^.format_message(cinfo, pChar(Msg));
5738 Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
5739 cinfo^.global_state := 0;
5744 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5746 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
5750 SetLength(Msg, 256);
5751 cinfo^.err^.format_message(cinfo, pChar(Msg));
5752 Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
5753 cinfo^.global_state := 0;
5757 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5759 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
5764 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5765 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
5767 src: glBitmap_libJPEG_source_mgr_ptr;
5770 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5772 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
5773 if (bytes <= 0) then begin
5774 src^.SrcBuffer[1] := $FF;
5775 src^.SrcBuffer[2] := JPEG_EOI;
5779 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
5780 src^.pub.bytes_in_buffer := bytes;
5785 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5786 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
5788 src: glBitmap_libJPEG_source_mgr_ptr;
5790 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5792 if num_bytes > 0 then begin
5793 // wanted byte isn't in buffer so set stream position and read buffer
5794 if num_bytes > src^.pub.bytes_in_buffer then begin
5795 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
5796 src^.pub.fill_input_buffer(cinfo);
5798 // wanted byte is in buffer so only skip
5799 inc(src^.pub.next_input_byte, num_bytes);
5800 dec(src^.pub.bytes_in_buffer, num_bytes);
5805 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5807 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
5812 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5814 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
5819 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5820 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
5822 dest: glBitmap_libJPEG_dest_mgr_ptr;
5824 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5826 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
5827 // write complete buffer
5828 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
5831 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
5832 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
5838 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5839 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
5842 dest: glBitmap_libJPEG_dest_mgr_ptr;
5844 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5846 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
5847 // check for endblock
5848 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
5850 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
5855 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
5860 {$IFDEF GLB_SUPPORT_JPEG_READ}
5861 {$IF DEFINED(GLB_SDL_IMAGE)}
5862 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5863 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
5865 Surface: PSDL_Surface;
5870 RWops := glBitmapCreateRWops(Stream);
5872 if IMG_isJPG(RWops) > 0 then begin
5873 Surface := IMG_LoadJPG_RW(RWops);
5875 AssignFromSurface(Surface);
5878 SDL_FreeSurface(Surface);
5886 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
5887 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5888 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
5891 Temp: array[0..1]of Byte;
5893 jpeg: jpeg_decompress_struct;
5894 jpeg_err: jpeg_error_mgr;
5896 IntFormat: TglBitmapInternalFormat;
5898 TempHeight, TempWidth: Integer;
5905 if not init_libJPEG then
5906 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
5909 // reading first two bytes to test file and set cursor back to begin
5910 StreamPos := Stream.Position;
5911 Stream.Read(Temp[0], 2);
5912 Stream.Position := StreamPos;
5914 // if Bitmap then read file.
5915 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
5916 FillChar(jpeg, SizeOf(jpeg_decompress_struct), $00);
5917 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
5920 jpeg.err := jpeg_std_error(@jpeg_err);
5921 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
5922 jpeg_err.output_message := glBitmap_libJPEG_output_message;
5924 // decompression struct
5925 jpeg_create_decompress(@jpeg);
5927 // allocation space for streaming methods
5928 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
5930 // seeting up custom functions
5931 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
5932 pub.init_source := glBitmap_libJPEG_init_source;
5933 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
5934 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
5935 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
5936 pub.term_source := glBitmap_libJPEG_term_source;
5938 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
5939 pub.next_input_byte := nil; // until buffer loaded
5941 SrcStream := Stream;
5944 // set global decoding state
5945 jpeg.global_state := DSTATE_START;
5947 // read header of jpeg
5948 jpeg_read_header(@jpeg, false);
5950 // setting output parameter
5951 case jpeg.jpeg_color_space of
5954 jpeg.out_color_space := JCS_GRAYSCALE;
5955 IntFormat := ifLuminance;
5958 jpeg.out_color_space := JCS_RGB;
5959 IntFormat := ifRGB8;
5963 jpeg_start_decompress(@jpeg);
5965 TempHeight := jpeg.output_height;
5966 TempWidth := jpeg.output_width;
5968 // creating new image
5969 GetMem(pImage, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
5973 for Row := 0 to TempHeight -1 do begin
5974 jpeg_read_scanlines(@jpeg, @pTemp, 1);
5975 Inc(pTemp, Trunc(FormatGetSize(IntFormat) * TempWidth));
5978 // finish decompression
5979 jpeg_finish_decompress(@jpeg);
5981 // destroy decompression
5982 jpeg_destroy_decompress(@jpeg);
5984 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight);
5997 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
5998 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5999 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6004 Temp: array[0..1]of Byte;
6008 // reading first two bytes to test file and set cursor back to begin
6009 StreamPos := Stream.Position;
6010 Stream.Read(Temp[0], 2);
6011 Stream.Position := StreamPos;
6013 // if Bitmap then read file.
6014 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6015 bmp := TBitmap.Create;
6017 jpg := TJPEGImage.Create;
6019 jpg.LoadFromStream(Stream);
6021 result := AssignFromBitmap(bmp);
6033 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6034 {$IF DEFEFINED(GLB_LIB_JPEG)}
6035 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6036 procedure TglBitmap.SaveJPEG(Stream: TStream);
6038 jpeg: jpeg_compress_struct;
6039 jpeg_err: jpeg_error_mgr;
6041 pTemp, pTemp2: pByte;
6043 procedure CopyRow(pDest, pSource: pByte);
6047 for X := 0 to Width - 1 do begin
6048 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6049 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6050 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6057 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6058 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
6060 if not init_libJPEG then
6061 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6064 FillChar(jpeg, SizeOf(jpeg_compress_struct), $00);
6065 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
6068 jpeg.err := jpeg_std_error(@jpeg_err);
6069 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6070 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6072 // compression struct
6073 jpeg_create_compress(@jpeg);
6075 // allocation space for streaming methods
6076 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6078 // seeting up custom functions
6079 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6080 pub.init_destination := glBitmap_libJPEG_init_destination;
6081 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6082 pub.term_destination := glBitmap_libJPEG_term_destination;
6084 pub.next_output_byte := @DestBuffer[1];
6085 pub.free_in_buffer := Length(DestBuffer);
6087 DestStream := Stream;
6090 // very important state
6091 jpeg.global_state := CSTATE_START;
6092 jpeg.image_width := Width;
6093 jpeg.image_height := Height;
6094 case InternalFormat of
6095 ifAlpha, ifLuminance, ifDepth8: begin
6096 jpeg.input_components := 1;
6097 jpeg.in_color_space := JCS_GRAYSCALE;
6099 ifRGB8, ifBGR8: begin
6100 jpeg.input_components := 3;
6101 jpeg.in_color_space := JCS_RGB;
6105 jpeg_set_defaults(@jpeg);
6106 jpeg_set_quality(@jpeg, 95, true);
6107 jpeg_start_compress(@jpeg, true);
6110 if InternalFormat = ifBGR8 then
6111 GetMem(pTemp2, fRowSize)
6116 for Row := 0 to jpeg.image_height -1 do begin
6118 if InternalFormat = ifBGR8 then
6119 CopyRow(pTemp2, pTemp)
6124 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6125 inc(pTemp, fRowSize);
6129 if InternalFormat = ifBGR8 then
6132 jpeg_finish_compress(@jpeg);
6133 jpeg_destroy_compress(@jpeg);
6139 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6140 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6141 procedure TglBitmap.SaveJPEG(Stream: TStream);
6146 if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then
6147 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
6149 Bmp := TBitmap.Create;
6151 Jpg := TJPEGImage.Create;
6153 AssignToBitmap(Bmp);
6154 if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
6155 Jpg.Grayscale := true;
6156 Jpg.PixelFormat := jf8Bit;
6159 Jpg.SaveToStream(Stream);
6170 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6171 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6172 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6179 BMP_COMP_BITFIELDS = 3;
6182 TBMPHeader = packed record
6187 bfOffBits: Cardinal;
6190 TBMPInfo = packed record
6196 biCompression: Cardinal;
6197 biSizeImage: Cardinal;
6198 biXPelsPerMeter: Longint;
6199 biYPelsPerMeter: Longint;
6200 biClrUsed: Cardinal;
6201 biClrImportant: Cardinal;
6204 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6205 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6207 //////////////////////////////////////////////////////////////////////////////////////////////////
6208 function ReadInfo(var aInfo: TBMPInfo; var aMask: TglBitmapColorRec): TglBitmapFormat;
6211 aStream.Read(aInfo, SizeOf(aInfo));
6212 FillChar(aMask, SizeOf(aMask), 0);
6215 case aInfo.biCompression of
6217 BMP_COMP_RLE8: begin
6218 raise EglBitmapException.Create('RLE compression is not supported');
6220 BMP_COMP_BITFIELDS: begin
6221 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6222 aStream.Read(aMask.r, SizeOf(aMask.r));
6223 aStream.Read(aMask.g, SizeOf(aMask.g));
6224 aStream.Read(aMask.b, SizeOf(aMask.b));
6225 aStream.Read(aMask.a, SizeOf(aMask.a));
6227 raise EglBitmapException.Create('Bitfields are only supported for 16bit and 32bit formats');
6231 //get suitable format
6232 case aInfo.biBitCount of
6233 8: result := tfLuminance8;
6234 16: result := tfBGR5;
6235 24: result := tfBGR8;
6236 32: result := tfBGRA8;
6240 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6243 ColorTable: TbmpColorTable;
6246 if (aInfo.biBitCount >= 16) then
6248 aFormat := tfLuminance8;
6249 c := aInfo.biClrUsed;
6251 c := 1 shl aInfo.biBitCount;
6252 SetLength(ColorTable, c);
6253 for i := 0 to c-1 do begin
6254 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6255 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6259 result := TbmpColorTableFormat.Create;
6260 result.PixelSize := aInfo.biBitCount / 8;
6261 result.ColorTable := ColorTable;
6262 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6265 //////////////////////////////////////////////////////////////////////////////////////////////////
6266 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6267 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6269 TmpFormat: TglBitmapFormat;
6270 FormatDesc: TFormatDescriptor;
6273 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6274 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6275 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6276 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6277 aFormat := FormatDesc.Format;
6282 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6283 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6284 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6285 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6287 result := TbmpBitfieldFormat.Create;
6288 result.PixelSize := aInfo.biBitCount / 8;
6289 result.RedMask := aMask.r;
6290 result.GreenMask := aMask.g;
6291 result.BlueMask := aMask.b;
6292 result.AlphaMask := aMask.a;
6299 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6300 PaddingBuff: Cardinal;
6301 LineBuf, ImageData, TmpData: PByte;
6302 SourceMD, DestMD: Pointer;
6303 BmpFormat: TglBitmapFormat;
6304 ColorTable: TbmpColorTable;
6307 Mask: TglBitmapColorRec;
6312 SpecialFormat: TFormatDescriptor;
6313 FormatDesc: TFormatDescriptor;
6315 //////////////////////////////////////////////////////////////////////////////////////////////////
6316 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6319 Pixel: TglBitmapPixelData;
6321 aStream.Read(aLineBuf^, rbLineSize);
6322 SpecialFormat.PreparePixel(Pixel);
6323 for i := 0 to Info.biWidth-1 do begin
6324 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6325 with FormatDesc do begin
6326 //TODO: use convert function
6328 if (SpecialFormat.Range.arr[j] <> Range.arr[j]) then begin
6329 if (SpecialFormat.Range.arr[j] > 0) then
6330 Pixel.Data.arr[j] := Round(Pixel.Data.arr[j] / SpecialFormat.Range.arr[j] * Range.arr[j])
6332 Pixel.Data.arr[j] := 0;
6335 FormatDesc.Map(Pixel, aData, DestMD);
6341 BmpFormat := tfEmpty;
6342 SpecialFormat := nil;
6348 StartPos := aStream.Position;
6349 aStream.Read(Header, SizeOf(Header));
6351 if Header.bfType = BMP_MAGIC then begin
6353 BmpFormat := ReadInfo(Info, Mask);
6354 SpecialFormat := ReadColorTable(BmpFormat, Info);
6355 if not Assigned(SpecialFormat) then
6356 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6357 aStream.Position := StartPos + Header.bfOffBits;
6359 if (BmpFormat <> tfEmpty) then begin
6360 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6361 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6362 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6363 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6366 DestMD := FormatDesc.CreateMappingData;
6367 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6368 GetMem(ImageData, ImageSize);
6369 if Assigned(SpecialFormat) then begin
6370 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6371 SourceMD := SpecialFormat.CreateMappingData;
6376 FillChar(ImageData^, ImageSize, $FF);
6377 TmpData := ImageData;
6378 if (Info.biHeight > 0) then
6379 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6380 for i := 0 to Abs(Info.biHeight)-1 do begin
6381 if Assigned(SpecialFormat) then
6382 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6384 aStream.Read(TmpData^, wbLineSize); //else only read data
6385 if (Info.biHeight > 0) then
6386 dec(TmpData, wbLineSize)
6388 inc(TmpData, wbLineSize);
6389 aStream.Read(PaddingBuff, Padding);
6391 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight));
6394 if Assigned(LineBuf) then
6396 if Assigned(SourceMD) then
6397 SpecialFormat.FreeMappingData(SourceMD);
6398 FormatDesc.FreeMappingData(DestMD);
6405 raise EglBitmapException.Create('LoadBMP - No suitable format found');
6407 aStream.Position := StartPos;
6411 FreeAndNil(SpecialFormat);
6414 else aStream.Position := StartPos;
6417 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6418 procedure TglBitmap.SaveBMP(const aStream: TStream);
6422 Converter: TbmpColorTableFormat;
6423 FormatDesc: TFormatDescriptor;
6424 SourceFD, DestFD: Pointer;
6425 pData, srcData, dstData, ConvertBuffer: pByte;
6427 Pixel: TglBitmapPixelData;
6428 PixelFormat: TglBitmapPixelData;
6429 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx, i: Integer;
6430 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6432 PaddingBuff: Cardinal;
6434 function GetLineWidth : Integer;
6436 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6440 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6441 raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
6444 FormatDesc := TFormatDescriptor.Get(Format);
6445 ImageSize := FormatDesc.GetSize(Dimension);
6447 FillChar(Header, SizeOf(Header), 0);
6448 Header.bfType := BMP_MAGIC;
6449 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6450 Header.bfReserved1 := 0;
6451 Header.bfReserved2 := 0;
6452 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6454 FillChar(Info, SizeOf(Info), 0);
6455 Info.biSize := SizeOf(Info);
6456 Info.biWidth := Width;
6457 Info.biHeight := Height;
6459 Info.biCompression := BMP_COMP_RGB;
6460 Info.biSizeImage := ImageSize;
6465 Info.biBitCount := 4;
6466 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6467 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6468 Converter := TbmpColorTableFormat.Create;
6469 Converter.PixelSize := 0.5;
6470 Converter.Format := Format;
6471 Converter.Range := glBitmapColorRec($F, $F, $F, $0);
6472 Converter.CreateColorTable;
6475 tfR3G3B2, tfLuminance8: begin
6476 Info.biBitCount := 8;
6477 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6478 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6479 Converter := TbmpColorTableFormat.Create;
6480 Converter.PixelSize := 1;
6481 Converter.Format := Format;
6482 if (Format = tfR3G3B2) then begin
6483 Converter.Range := glBitmapColorRec($7, $7, $3, $0);
6484 Converter.Shift := glBitmapShiftRec(0, 3, 6, 0);
6486 Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0);
6487 Converter.CreateColorTable;
6490 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6491 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6492 Info.biBitCount := 16;
6493 Info.biCompression := BMP_COMP_BITFIELDS;
6496 tfBGR8, tfRGB8: begin
6497 Info.biBitCount := 24;
6500 tfRGB10, tfRGB10A2, tfRGBA8,
6501 tfBGR10, tfBGR10A2, tfBGRA8: begin
6502 Info.biBitCount := 32;
6503 Info.biCompression := BMP_COMP_BITFIELDS;
6506 raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
6508 Info.biXPelsPerMeter := 2835;
6509 Info.biYPelsPerMeter := 2835;
6512 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6513 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
6514 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
6516 RedMask := FormatDesc.RedMask;
6517 GreenMask := FormatDesc.GreenMask;
6518 BlueMask := FormatDesc.BlueMask;
6519 AlphaMask := FormatDesc.AlphaMask;
6523 aStream.Write(Header, SizeOf(Header));
6524 aStream.Write(Info, SizeOf(Info));
6527 if Assigned(Converter) then
6528 aStream.Write(Converter.ColorTable[0].b,
6529 SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable));
6532 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6533 aStream.Write(RedMask, SizeOf(Cardinal));
6534 aStream.Write(GreenMask, SizeOf(Cardinal));
6535 aStream.Write(BlueMask, SizeOf(Cardinal));
6536 aStream.Write(AlphaMask, SizeOf(Cardinal));
6540 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
6541 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
6542 Padding := GetLineWidth - wbLineSize;
6546 inc(pData, (Height-1) * rbLineSize);
6548 // prepare row buffer. But only for RGB because RGBA supports color masks
6549 // so it's possible to change color within the image.
6550 if Assigned(Converter) then begin
6551 FormatDesc.PreparePixel(Pixel);
6552 GetMem(ConvertBuffer, wbLineSize);
6553 SourceFD := FormatDesc.CreateMappingData;
6554 DestFD := Converter.CreateMappingData;
6556 ConvertBuffer := nil;
6559 for LineIdx := 0 to Height - 1 do begin
6561 if Assigned(Converter) then begin
6563 dstData := ConvertBuffer;
6564 for PixelIdx := 0 to Info.biWidth-1 do begin
6565 FormatDesc.Unmap(srcData, Pixel, SourceFD);
6566 with FormatDesc do begin
6567 //TODO use convert function
6569 if (Converter.Range.arr[i] <> Range.arr[i]) then begin
6570 if (Range.arr[i] > 0) then
6571 Pixel.Data.arr[i] := Round(Pixel.Data.arr[i] / Range.arr[i] * Converter.Range.arr[i])
6573 Pixel.Data.arr[i] := 0;
6576 Converter.Map(Pixel, dstData, DestFD);
6578 aStream.Write(ConvertBuffer^, wbLineSize);
6580 aStream.Write(pData^, rbLineSize);
6582 dec(pData, rbLineSize);
6583 if (Padding > 0) then
6584 aStream.Write(PaddingBuff, Padding);
6587 // destroy row buffer
6588 if Assigned(ConvertBuffer) then begin
6589 FormatDesc.FreeMappingData(SourceFD);
6590 Converter.FreeMappingData(DestFD);
6591 FreeMem(ConvertBuffer);
6595 if Assigned(Converter) then
6600 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6601 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6602 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6604 TTGAHeader = packed record
6608 //ColorMapSpec: Array[0..4] of Byte;
6609 ColorMapStart: Word;
6610 ColorMapLength: Word;
6611 ColorMapEntrySize: Byte;
6621 TGA_UNCOMPRESSED_COLOR_TABLE = 1;
6622 TGA_UNCOMPRESSED_RGB = 2;
6623 TGA_UNCOMPRESSED_GRAY = 3;
6624 TGA_COMPRESSED_COLOR_TABLE = 9;
6625 TGA_COMPRESSED_RGB = 10;
6626 TGA_COMPRESSED_GRAY = 11;
6628 TGA_NONE_COLOR_TABLE = 0;
6629 TGA_COLOR_TABLE = 1;
6631 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6632 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
6636 StartPosition: Int64;
6637 PixelSize, LineSize: Integer;
6638 tgaFormat: TglBitmapFormat;
6639 FormatDesc: TFormatDescriptor;
6640 Counter: packed record
6642 low, high, dir: Integer;
6649 ////////////////////////////////////////////////////////////////////////////////////////
6650 procedure ReadUncompressed;
6653 buf, tmp1, tmp2: PByte;
6656 if (Counter.X.dir < 0) then
6657 buf := GetMem(LineSize);
6659 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
6660 tmp1 := ImageData + (Counter.Y.low * LineSize); //pointer to LineStart
6661 if (Counter.X.dir < 0) then begin //flip X
6662 aStream.Read(buf^, LineSize);
6663 tmp2 := buf + LineSize - PixelSize; //pointer to last pixel in line
6664 for i := 0 to Header.Width-1 do begin //for all pixels in line
6665 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
6670 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
6673 aStream.Read(tmp1^, LineSize);
6674 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
6677 if Assigned(buf) then
6682 ////////////////////////////////////////////////////////////////////////////////////////
6683 procedure ReadCompressed;
6685 /////////////////////////////////////////////////////////////////
6688 LinePixelsRead: Integer;
6689 procedure CheckLine;
6691 if (LinePixelsRead >= Header.Width) then begin
6692 LinePixelsRead := 0;
6693 inc(Counter.Y.low, Counter.Y.dir); //next line index
6694 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6695 if (Counter.X.dir < 0) then //if x flipped then
6696 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6700 /////////////////////////////////////////////////////////////////
6703 CacheSize, CachePos: Integer;
6704 procedure CachedRead(out Buffer; Count: Integer);
6708 if (CachePos + Count > CacheSize) then begin
6709 //if buffer overflow save non read bytes
6711 if (CacheSize - CachePos > 0) then begin
6712 BytesRead := CacheSize - CachePos;
6713 Move(PByteArray(Cache)^[CachePos], Buffer, BytesRead);
6714 inc(CachePos, BytesRead);
6717 //load cache from file
6718 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
6719 aStream.Read(Cache^, CacheSize);
6722 //read rest of requested bytes
6723 if (Count - BytesRead > 0) then begin
6724 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
6725 inc(CachePos, Count - BytesRead);
6728 //if no buffer overflow just read the data
6729 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
6730 inc(CachePos, Count);
6734 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
6739 inc(aBuffer, Counter.X.dir);
6742 PWord(aBuffer)^ := PWord(aData)^;
6743 inc(aBuffer, 2 * Counter.X.dir);
6746 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
6747 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
6748 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
6749 inc(aBuffer, 3 * Counter.X.dir);
6752 PCardinal(aBuffer)^ := PCardinal(aData)^;
6753 inc(aBuffer, 4 * Counter.X.dir);
6759 TotalPixelsToRead, TotalPixelsRead: Integer;
6761 buf: array [0..3] of Byte; //1 pixel is max 32bit long
6762 PixelRepeat: Boolean;
6763 PixelsToRead, PixelCount: Integer;
6768 TotalPixelsToRead := Header.Width * Header.Height;
6769 TotalPixelsRead := 0;
6770 LinePixelsRead := 0;
6772 GetMem(Cache, CACHE_SIZE);
6774 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6775 if (Counter.X.dir < 0) then //if x flipped then
6776 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6780 CachedRead(Temp, 1);
6781 PixelRepeat := (Temp and $80) > 0;
6782 PixelsToRead := (Temp and $7F) + 1;
6783 inc(TotalPixelsRead, PixelsToRead);
6786 CachedRead(buf[0], PixelSize);
6787 while (PixelsToRead > 0) do begin
6789 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
6790 while (PixelCount > 0) do begin
6791 if not PixelRepeat then
6792 CachedRead(buf[0], PixelSize);
6793 PixelToBuffer(@buf[0], TmpData);
6794 inc(LinePixelsRead);
6799 until (TotalPixelsRead >= TotalPixelsToRead);
6805 function IsGrayFormat: Boolean;
6807 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
6813 // reading header to test file and set cursor back to begin
6814 StartPosition := aStream.Position;
6815 aStream.Read(Header, SizeOf(Header));
6817 // no colormapped files
6818 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
6819 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
6822 if Header.ImageID <> 0 then // skip image ID
6823 aStream.Position := aStream.Position + Header.ImageID;
6826 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
6827 0: tgaFormat := tfLuminance8;
6828 8: tgaFormat := tfAlpha8;
6831 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
6832 0: tgaFormat := tfLuminance16;
6833 8: tgaFormat := tfLuminance8Alpha8;
6834 end else case (Header.ImageDesc and $F) of
6835 0: tgaFormat := tfBGR5;
6836 1: tgaFormat := tfBGR5A1;
6837 4: tgaFormat := tfBGRA4;
6840 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6841 0: tgaFormat := tfBGR8;
6844 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6845 2: tgaFormat := tfBGR10A2;
6846 8: tgaFormat := tfBGRA8;
6850 if (tgaFormat = tfEmpty) then
6851 raise EglBitmapException.Create('LoadTga - unsupported format');
6853 FormatDesc := TFormatDescriptor.Get(tgaFormat);
6854 PixelSize := FormatDesc.GetSize(1, 1);
6855 LineSize := FormatDesc.GetSize(Header.Width, 1);
6857 GetMem(ImageData, LineSize * Header.Height);
6860 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
6861 Counter.X.low := Header.Height-1;;
6862 Counter.X.high := 0;
6863 Counter.X.dir := -1;
6866 Counter.X.high := Header.Height-1;
6871 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
6873 Counter.Y.high := Header.Height-1;
6876 Counter.Y.low := Header.Height-1;;
6877 Counter.Y.high := 0;
6878 Counter.Y.dir := -1;
6882 case Header.ImageType of
6883 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
6885 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
6889 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height);
6896 aStream.Position := StartPosition;
6899 else aStream.Position := StartPosition;
6902 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6903 procedure TglBitmap.SaveTGA(const aStream: TStream);
6906 LineSize, Size, x, y: Integer;
6907 Pixel: TglBitmapPixelData;
6908 LineBuf, SourceData, DestData: PByte;
6909 SourceMD, DestMD: Pointer;
6910 FormatDesc: TFormatDescriptor;
6911 Converter: TFormatDescriptor;
6913 if not (ftTGA in FormatGetSupportedFiles(Format)) then
6914 raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT);
6917 FillChar(Header, SizeOf(Header), 0);
6920 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
6921 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
6922 Header.ImageType := TGA_UNCOMPRESSED_GRAY
6924 Header.ImageType := TGA_UNCOMPRESSED_RGB;
6927 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
6929 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
6930 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
6932 else if (Format in [tfBGR8, tfRGB8]) then
6940 Header.ImageDesc := 1 and $F;
6941 tfRGB10A2, tfBGR10A2:
6942 Header.ImageDesc := 2 and $F;
6944 Header.ImageDesc := 4 and $F;
6945 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
6946 Header.ImageDesc := 8 and $F;
6949 Header.Width := Width;
6950 Header.Height := Height;
6951 Header.ImageDesc := Header.ImageDesc or $20; //flip y
6952 aStream.Write(Header, SizeOf(Header));
6954 // convert RGB(A) to BGR(A)
6956 FormatDesc := TFormatDescriptor.Get(Format);
6957 Size := FormatDesc.GetSize(Dimension);
6958 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
6959 if (FormatDesc.RGBInverted = tfEmpty) then
6960 raise EglBitmapException.Create('inverted RGB format is empty');
6961 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
6962 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
6963 (Converter.PixelSize <> FormatDesc.PixelSize) then
6964 raise EglBitmapException.Create('invalid inverted RGB format');
6967 if Assigned(Converter) then begin
6968 LineSize := FormatDesc.GetSize(Width, 1);
6969 LineBuf := GetMem(LineSize);
6970 SourceMD := FormatDesc.CreateMappingData;
6971 DestMD := Converter.CreateMappingData;
6974 for y := 0 to Height-1 do begin
6975 DestData := LineBuf;
6976 for x := 0 to Width-1 do begin
6977 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
6978 Converter.Map(Pixel, DestData, DestMD);
6980 aStream.Write(LineBuf^, LineSize);
6984 FormatDesc.FreeMappingData(SourceMD);
6985 FormatDesc.FreeMappingData(DestMD);
6988 aStream.Write(Data^, Size);
6991 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6992 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6993 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6995 DDS_MAGIC: Cardinal = $20534444;
6997 // DDS_header.dwFlags
6998 DDSD_CAPS = $00000001;
6999 DDSD_HEIGHT = $00000002;
7000 DDSD_WIDTH = $00000004;
7001 DDSD_PITCH = $00000008;
7002 DDSD_PIXELFORMAT = $00001000;
7003 DDSD_MIPMAPCOUNT = $00020000;
7004 DDSD_LINEARSIZE = $00080000;
7005 DDSD_DEPTH = $00800000;
7007 // DDS_header.sPixelFormat.dwFlags
7008 DDPF_ALPHAPIXELS = $00000001;
7009 DDPF_ALPHA = $00000002;
7010 DDPF_FOURCC = $00000004;
7011 DDPF_INDEXED = $00000020;
7012 DDPF_RGB = $00000040;
7013 DDPF_LUMINANCE = $00020000;
7015 // DDS_header.sCaps.dwCaps1
7016 DDSCAPS_COMPLEX = $00000008;
7017 DDSCAPS_TEXTURE = $00001000;
7018 DDSCAPS_MIPMAP = $00400000;
7020 // DDS_header.sCaps.dwCaps2
7021 DDSCAPS2_CUBEMAP = $00000200;
7022 DDSCAPS2_CUBEMAP_POSITIVEX = $00000400;
7023 DDSCAPS2_CUBEMAP_NEGATIVEX = $00000800;
7024 DDSCAPS2_CUBEMAP_POSITIVEY = $00001000;
7025 DDSCAPS2_CUBEMAP_NEGATIVEY = $00002000;
7026 DDSCAPS2_CUBEMAP_POSITIVEZ = $00004000;
7027 DDSCAPS2_CUBEMAP_NEGATIVEZ = $00008000;
7028 DDSCAPS2_VOLUME = $00200000;
7030 D3DFMT_DXT1 = $31545844;
7031 D3DFMT_DXT3 = $33545844;
7032 D3DFMT_DXT5 = $35545844;
7035 TDDSPixelFormat = packed record
7039 dwRGBBitCount: Cardinal;
7040 dwRBitMask: Cardinal;
7041 dwGBitMask: Cardinal;
7042 dwBBitMask: Cardinal;
7043 dwABitMask: Cardinal;
7046 TDDSCaps = packed record
7050 dwReserved: Cardinal;
7053 TDDSHeader = packed record
7058 dwPitchOrLinearSize: Cardinal;
7060 dwMipMapCount: Cardinal;
7061 dwReserved: array[0..10] of Cardinal;
7062 PixelFormat: TDDSPixelFormat;
7064 dwReserved2: Cardinal;
7067 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7068 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7071 Converter: TbmpBitfieldFormat;
7073 function GetDDSFormat: TglBitmapFormat;
7075 fd: TFormatDescriptor;
7077 Range: TglBitmapColorRec;
7081 with Header.PixelFormat do begin
7083 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7084 case Header.PixelFormat.dwFourCC of
7085 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7086 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7087 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7089 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7091 //find matching format
7092 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7093 fd := TFormatDescriptor.Get(result);
7094 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7095 (8 * fd.PixelSize = dwRGBBitCount) then
7099 //find format with same Range
7100 Range.r := dwRBitMask;
7101 Range.g := dwGBitMask;
7102 Range.b := dwBBitMask;
7103 Range.a := dwABitMask;
7104 for i := 0 to 3 do begin
7105 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7106 Range.arr[i] := Range.arr[i] shr 1;
7108 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7109 fd := TFormatDescriptor.Get(result);
7112 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7120 //no format with same range found -> use default
7121 if (result = tfEmpty) then begin
7122 if (dwABitMask > 0) then
7128 Converter := TbmpBitfieldFormat.Create;
7129 Converter.RedMask := dwRBitMask;
7130 Converter.GreenMask := dwGBitMask;
7131 Converter.BlueMask := dwBBitMask;
7132 Converter.AlphaMask := dwABitMask;
7133 Converter.PixelSize := dwRGBBitCount / 8;
7140 x, y, j, LineSize, RowSize, Magic: Cardinal;
7141 NewImage, TmpData, RowData, SrcData: PByte;
7142 SourceMD, DestMD: Pointer;
7143 Pixel: TglBitmapPixelData;
7144 ddsFormat: TglBitmapFormat;
7145 FormatDesc: TFormatDescriptor;
7150 StreamPos := aStream.Position;
7153 aStream.Read(Magic, sizeof(Magic));
7154 if (Magic <> DDS_MAGIC) then begin
7155 aStream.Position := StreamPos;
7160 aStream.Read(Header, sizeof(Header));
7161 if (Header.dwSize <> SizeOf(Header)) or
7162 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7163 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7165 aStream.Position := StreamPos;
7169 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7170 raise EglBitmapException.Create('LoadDDS - CubeMaps are not supported');
7172 ddsFormat := GetDDSFormat;
7174 if (ddsFormat = tfEmpty) then
7175 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7177 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7178 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7179 GetMem(NewImage, Header.dwHeight * LineSize);
7181 TmpData := NewImage;
7184 if Assigned(Converter) then begin
7185 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7186 GetMem(RowData, RowSize);
7187 SourceMD := Converter.CreateMappingData;
7188 DestMD := FormatDesc.CreateMappingData;
7190 for y := 0 to Header.dwHeight-1 do begin
7191 TmpData := NewImage + y * LineSize;
7193 aStream.Read(SrcData^, RowSize);
7194 for x := 0 to Header.dwWidth-1 do begin
7195 Converter.Unmap(SrcData, Pixel, SourceMD);
7196 //TODO use converter function
7198 if (Converter.Range.arr[j] <> FormatDesc.Range.arr[j]) then begin
7199 if (Converter.Range.arr[j] > 0) then
7200 Pixel.Data.arr[j] := Round(Pixel.Data.arr[j] / Converter.Range.arr[j] * FormatDesc.Range.arr[j])
7202 Pixel.Data.arr[j] := 0;
7204 FormatDesc.Map(Pixel, TmpData, DestMD);
7208 Converter.FreeMappingData(SourceMD);
7209 FormatDesc.FreeMappingData(DestMD);
7215 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7216 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7217 for Y := 0 to Header.dwHeight-1 do begin
7218 aStream.Read(TmpData^, RowSize);
7219 Inc(TmpData, LineSize);
7224 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7225 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7226 for Y := 0 to Header.dwHeight-1 do begin
7227 aStream.Read(TmpData^, RowSize);
7228 Inc(TmpData, LineSize);
7231 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7233 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
7240 FreeAndNil(Converter);
7244 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7245 procedure TglBitmap.SaveDDS(const aStream: TStream);
7248 FormatDesc: TFormatDescriptor;
7250 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7251 raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_FORMAT);
7253 FormatDesc := TFormatDescriptor.Get(Format);
7256 FillChar(Header, SizeOf(Header), 0);
7257 Header.dwSize := SizeOf(Header);
7258 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7260 Header.dwWidth := Max(1, Width);
7261 Header.dwHeight := Max(1, Height);
7264 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7267 Header.PixelFormat.dwSize := sizeof(Header);
7268 if (FormatDesc.IsCompressed) then begin
7269 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7271 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7272 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7273 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7275 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7276 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7277 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7278 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7279 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7280 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7281 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7282 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7283 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7285 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7286 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7287 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7288 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7289 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7290 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7293 if (FormatDesc.HasAlpha) then
7294 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7296 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7297 aStream.Write(Header, SizeOf(Header));
7298 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7301 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7302 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7303 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7304 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7306 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7307 result := fLines[aIndex]
7312 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7313 procedure TglBitmap2D.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
7314 const aWidth: Integer; const aHeight: Integer);
7316 Idx, LineWidth: Integer;
7318 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7320 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7322 fGetPixelFunc := GetPixel2DUnmap;
7323 fSetPixelFunc := SetPixel2DUnmap;
7326 if Assigned(Data) then begin
7327 SetLength(fLines, GetHeight);
7328 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7330 for Idx := 0 to GetHeight -1 do begin
7331 fLines[Idx] := Data;
7332 Inc(fLines[Idx], Idx * LineWidth);
7335 else SetLength(fLines, 0);
7337 SetLength(fLines, 0);
7339 fSetPixelFunc := nil;
7343 fGetPixelFunc := GetPixel2DDXT1;
7345 fGetPixelFunc := GetPixel2DDXT3;
7347 fGetPixelFunc := GetPixel2DDXT5;
7349 fGetPixelFunc := nil;
7355 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7356 procedure TglBitmap2D.UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
7358 FormatDesc: TFormatDescriptor;
7360 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7362 FormatDesc := TFormatDescriptor.Get(Format);
7363 if FormatDesc.IsCompressed then begin
7364 glCompressedTexImage2D(Target, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7365 end else if aBuildWithGlu then begin
7366 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7367 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7369 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7370 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7374 if (FreeDataAfterGenTexture) then
7378 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7379 procedure TglBitmap2D.AfterConstruction;
7382 Target := GL_TEXTURE_2D;
7385 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7386 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7389 Size, w, h: Integer;
7390 FormatDesc: TFormatDescriptor;
7392 FormatDesc := TFormatDescriptor.Get(Format);
7393 if FormatDesc.IsCompressed then
7394 raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_FORMAT);
7396 w := aRight - aLeft;
7397 h := aBottom - aTop;
7398 Size := FormatDesc.GetSize(w, h);
7401 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7402 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7403 SetDataPointer(Temp, Format, w, h);
7411 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7412 procedure TglBitmap2D.GetDataFromTexture;
7415 TempWidth, TempHeight: Integer;
7416 TempType, TempIntFormat: Cardinal;
7417 IntFormat, f: TglBitmapFormat;
7418 FormatDesc: TFormatDescriptor;
7423 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7424 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7425 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7427 IntFormat := tfEmpty;
7428 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do
7429 if (TFormatDescriptor.Get(f).glInternalFormat = TempIntFormat) then begin
7430 IntFormat := FormatDesc.Format;
7434 // Getting data from OpenGL
7435 FormatDesc := TFormatDescriptor.Get(IntFormat);
7436 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
7438 if FormatDesc.IsCompressed then
7439 glGetCompressedTexImage(Target, 0, Temp)
7441 glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
7442 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
7449 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7450 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
7452 BuildWithGlu, PotTex, TexRec: Boolean;
7455 if Assigned(Data) then begin
7456 // Check Texture Size
7457 if (aTestTextureSize) then begin
7458 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7460 if ((Height > TexSize) or (Width > TexSize)) then
7461 raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7463 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
7464 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE_ARB);
7466 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7467 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7471 SetupParameters(BuildWithGlu);
7472 UploadData(Target, BuildWithGlu);
7473 glAreTexturesResident(1, @fID, @fIsResident);
7477 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7478 function TglBitmap2D.FlipHorz: Boolean;
7481 TempDestData, DestData, SourceData: PByte;
7484 result := inherited FlipHorz;
7485 if Assigned(Data) then begin
7487 ImgSize := Height * fRowSize;
7488 GetMem(DestData, ImgSize);
7490 TempDestData := DestData;
7491 Dec(TempDestData, fRowSize + fPixelSize);
7492 for Row := 0 to Height -1 do begin
7493 Inc(TempDestData, fRowSize * 2);
7494 for Col := 0 to Width -1 do begin
7495 Move(SourceData^, TempDestData^, fPixelSize);
7496 Inc(SourceData, fPixelSize);
7497 Dec(TempDestData, fPixelSize);
7500 SetDataPointer(DestData, Format);
7509 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7510 function TglBitmap2D.FlipVert: Boolean;
7513 TempDestData, DestData, SourceData: PByte;
7515 result := inherited FlipVert;
7516 if Assigned(Data) then begin
7518 GetMem(DestData, Height * fRowSize);
7520 TempDestData := DestData;
7521 Inc(TempDestData, Width * (Height -1) * fPixelSize);
7522 for Row := 0 to Height -1 do begin
7523 Move(SourceData^, TempDestData^, fRowSize);
7524 Dec(TempDestData, fRowSize);
7525 Inc(SourceData, fRowSize);
7527 SetDataPointer(DestData, Format);
7536 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7537 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7538 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7540 TMatrixItem = record
7545 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
7546 TglBitmapToNormalMapRec = Record
7548 Heights: array of Single;
7549 MatrixU : array of TMatrixItem;
7550 MatrixV : array of TMatrixItem;
7554 ONE_OVER_255 = 1 / 255;
7556 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7557 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
7561 with FuncRec do begin
7563 Source.Data.r * LUMINANCE_WEIGHT_R +
7564 Source.Data.g * LUMINANCE_WEIGHT_G +
7565 Source.Data.b * LUMINANCE_WEIGHT_B;
7566 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
7570 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7571 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
7574 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
7577 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7578 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
7580 TVec = Array[0..2] of Single;
7587 function GetHeight(X, Y: Integer): Single;
7589 with FuncRec do begin
7590 X := Max(0, Min(Size.X -1, X));
7591 Y := Max(0, Min(Size.Y -1, Y));
7592 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
7597 with FuncRec do begin
7598 with PglBitmapToNormalMapRec(Args)^ do begin
7600 for Idx := Low(MatrixU) to High(MatrixU) do
7601 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
7604 for Idx := Low(MatrixU) to High(MatrixU) do
7605 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
7607 Vec[0] := -du * Scale;
7608 Vec[1] := -dv * Scale;
7613 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
7614 if Len <> 0 then begin
7615 Vec[0] := Vec[0] * Len;
7616 Vec[1] := Vec[1] * Len;
7617 Vec[2] := Vec[2] * Len;
7621 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
7622 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
7623 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
7627 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7628 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
7630 Rec: TglBitmapToNormalMapRec;
7632 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
7634 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
7635 Matrix[Index].X := X;
7636 Matrix[Index].Y := Y;
7637 Matrix[Index].W := W;
7643 if not FormatIsUncompressed(InternalFormat) then
7644 raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_FORMAT);
7647 if aScale > 100 then
7649 else if aScale < -100 then
7652 Rec.Scale := aScale;
7654 SetLength(Rec.Heights, Width * Height);
7658 SetLength(Rec.MatrixU, 2);
7659 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
7660 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
7662 SetLength(Rec.MatrixV, 2);
7663 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
7664 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
7668 SetLength(Rec.MatrixU, 6);
7669 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
7670 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
7671 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
7672 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
7673 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
7674 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
7676 SetLength(Rec.MatrixV, 6);
7677 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
7678 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
7679 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
7680 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
7681 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
7682 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
7686 SetLength(Rec.MatrixU, 6);
7687 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
7688 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
7689 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
7690 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
7691 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
7692 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
7694 SetLength(Rec.MatrixV, 6);
7695 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
7696 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
7697 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
7698 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
7699 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
7700 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
7704 SetLength(Rec.MatrixU, 20);
7705 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
7706 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
7707 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
7708 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
7709 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
7710 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
7711 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
7712 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
7713 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
7714 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
7715 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
7716 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
7717 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
7718 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
7719 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
7720 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
7721 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
7722 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
7723 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
7724 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
7726 SetLength(Rec.MatrixV, 20);
7727 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
7728 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
7729 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
7730 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
7731 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
7732 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
7733 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
7734 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
7735 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
7736 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
7737 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
7738 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
7739 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
7740 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
7741 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
7742 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
7743 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
7744 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
7745 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
7746 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
7751 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
7752 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, PtrInt(@Rec))
7754 AddFunc(glBitmapToNormalMapPrepareFunc, false, PtrInt(@Rec));
7755 AddFunc(glBitmapToNormalMapFunc, false, PtrInt(@Rec));
7757 SetLength(Rec.Heights, 0);
7770 procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
7775 if Height > 1 then begin
7776 // extract first line of the data
7777 Size := FormatGetImageSize(glBitmapPosition(Width), Format);
7778 GetMem(pTemp, Size);
7780 Move(Data^, pTemp^, Size);
7787 inherited SetDataPointer(pTemp, Format, Width);
7789 if FormatIsUncompressed(Format) then begin
7790 fUnmapFunc := FormatGetUnMapFunc(Format);
7791 fGetPixelFunc := GetPixel1DUnmap;
7796 procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
7801 Inc(pTemp, Pos.X * fPixelSize);
7803 fUnmapFunc(pTemp, Pixel);
7807 function TglBitmap1D.FlipHorz: Boolean;
7810 pTempDest, pDest, pSource: pByte;
7812 result := inherited FlipHorz;
7814 if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin
7817 GetMem(pDest, fRowSize);
7821 Inc(pTempDest, fRowSize);
7822 for Col := 0 to Width -1 do begin
7823 Move(pSource^, pTempDest^, fPixelSize);
7825 Inc(pSource, fPixelSize);
7826 Dec(pTempDest, fPixelSize);
7829 SetDataPointer(pDest, InternalFormat);
7839 procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
7842 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
7843 glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data)
7847 if BuildWithGlu then
7848 gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data)
7850 glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data);
7853 if (FreeDataAfterGenTexture) then
7858 procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean);
7860 BuildWithGlu, TexRec: Boolean;
7861 glFormat, glInternalFormat, glType: Cardinal;
7864 if Assigned(Data) then begin
7865 // Check Texture Size
7866 if (TestTextureSize) then begin
7867 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7869 if (Width > TexSize) then
7870 raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7872 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7873 (Target = GL_TEXTURE_RECTANGLE_ARB);
7875 if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7876 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7881 SetupParameters(BuildWithGlu);
7882 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
7884 UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
7887 glAreTexturesResident(1, @fID, @fIsResident);
7892 procedure TglBitmap1D.AfterConstruction;
7896 Target := GL_TEXTURE_1D;
7900 { TglBitmapCubeMap }
7902 procedure TglBitmapCubeMap.AfterConstruction;
7906 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
7907 raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
7909 SetWrap; // set all to GL_CLAMP_TO_EDGE
7910 Target := GL_TEXTURE_CUBE_MAP;
7911 fGenMode := GL_REFLECTION_MAP;
7915 procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean);
7917 inherited Bind (EnableTextureUnit);
7919 if EnableTexCoordsGen then begin
7920 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
7921 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
7922 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
7923 glEnable(GL_TEXTURE_GEN_S);
7924 glEnable(GL_TEXTURE_GEN_T);
7925 glEnable(GL_TEXTURE_GEN_R);
7930 procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean);
7932 glFormat, glInternalFormat, glType: Cardinal;
7933 BuildWithGlu: Boolean;
7936 // Check Texture Size
7937 if (TestTextureSize) then begin
7938 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
7940 if ((Height > TexSize) or (Width > TexSize)) then
7941 raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
7943 if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
7944 raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
7948 if ID = 0 then begin
7950 SetupParameters(BuildWithGlu);
7953 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
7955 UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu);
7959 procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean);
7961 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
7965 procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen,
7966 DisableTextureUnit: Boolean);
7968 inherited Unbind (DisableTextureUnit);
7970 if DisableTexCoordsGen then begin
7971 glDisable(GL_TEXTURE_GEN_S);
7972 glDisable(GL_TEXTURE_GEN_T);
7973 glDisable(GL_TEXTURE_GEN_R);
7978 { TglBitmapNormalMap }
7981 TVec = Array[0..2] of Single;
7982 TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7984 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
7985 TglBitmapNormalMapRec = record
7987 Func: TglBitmapNormalMapGetVectorFunc;
7991 procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7994 Vec[1] := - (Position.Y + 0.5 - HalfSize);
7995 Vec[2] := - (Position.X + 0.5 - HalfSize);
7999 procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8001 Vec[0] := - HalfSize;
8002 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8003 Vec[2] := Position.X + 0.5 - HalfSize;
8007 procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8009 Vec[0] := Position.X + 0.5 - HalfSize;
8011 Vec[2] := Position.Y + 0.5 - HalfSize;
8015 procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8017 Vec[0] := Position.X + 0.5 - HalfSize;
8018 Vec[1] := - HalfSize;
8019 Vec[2] := - (Position.Y + 0.5 - HalfSize);
8023 procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8025 Vec[0] := Position.X + 0.5 - HalfSize;
8026 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8031 procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8033 Vec[0] := - (Position.X + 0.5 - HalfSize);
8034 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8035 Vec[2] := - HalfSize;
8039 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8044 with FuncRec do begin
8045 with PglBitmapNormalMapRec (CustomData)^ do begin
8046 Func(Vec, Position, HalfSize);
8049 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8050 if Len <> 0 then begin
8051 Vec[0] := Vec[0] * Len;
8052 Vec[1] := Vec[1] * Len;
8053 Vec[2] := Vec[2] * Len;
8056 // Scale Vector and AddVectro
8057 Vec[0] := Vec[0] * 0.5 + 0.5;
8058 Vec[1] := Vec[1] * 0.5 + 0.5;
8059 Vec[2] := Vec[2] * 0.5 + 0.5;
8063 Dest.Red := Round(Vec[0] * 255);
8064 Dest.Green := Round(Vec[1] * 255);
8065 Dest.Blue := Round(Vec[2] * 255);
8070 procedure TglBitmapNormalMap.AfterConstruction;
8074 fGenMode := GL_NORMAL_MAP;
8078 procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer;
8079 TestTextureSize: Boolean);
8081 Rec: TglBitmapNormalMapRec;
8082 SizeRec: TglBitmapPixelPosition;
8084 Rec.HalfSize := Size div 2;
8086 FreeDataAfterGenTexture := false;
8088 SizeRec.Fields := [ffX, ffY];
8093 Rec.Func := glBitmapNormalMapPosX;
8094 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8095 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize);
8098 Rec.Func := glBitmapNormalMapNegX;
8099 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8100 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize);
8103 Rec.Func := glBitmapNormalMapPosY;
8104 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8105 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize);
8108 Rec.Func := glBitmapNormalMapNegY;
8109 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8110 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize);
8113 Rec.Func := glBitmapNormalMapPosZ;
8114 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8115 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize);
8118 Rec.Func := glBitmapNormalMapNegZ;
8119 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8120 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize);
8125 glBitmapSetDefaultFormat(tfEmpty);
8126 glBitmapSetDefaultMipmap(mmMipmap);
8127 glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8128 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8130 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8131 glBitmapSetDefaultDeleteTextureOnFree (true);
8133 TFormatDescriptor.Init;
8136 TFormatDescriptor.Finalize;