1 {***********************************************************
2 glBitmap by Steffen Xonna aka Lossy eX (2003-2008)
3 http://www.opengl24.de/index.php?cat=header&file=glbitmap
5 modified by Delphi OpenGL Community (http://delphigl.com/) (2013)
7 ------------------------------------------------------------
8 The contents of this file are used with permission, subject to
9 the Mozilla Public License Version 1.1 (the "License"); you may
10 not use this file except in compliance with the License. You may
11 obtain a copy of the License at
12 http://www.mozilla.org/MPL/MPL-1.1.html
13 ------------------------------------------------------------
14 Version 3.0.0 unstable
15 ------------------------------------------------------------
18 - refactoring of the complete library
20 - The define GLB_DELPHI dosn't check versions anymore. If you say you are using delphi
21 then it's your problem if that isn't true. This prevents the unit for incompatibility
22 with newer versions of Delphi.
23 - Problems with D2009+ resolved (Thanks noeska and all i forgot)
24 - GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson)
26 - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson)
27 - Additional Datapointer for functioninterface now has the name CustomData
29 - AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson)
30 - If you load an texture from an file the property Filename will be set to the name of the file
31 - Three new properties to attach custom data to the Texture objects
32 - CustomName (free for use string)
33 - CustomNameW (free for use widestring)
34 - CustomDataPointer (free for use pointer to attach other objects or complex structures)
36 - RLE TGAs loaded much faster
38 - fixed some problem with reading RLE TGAs.
40 - function clone now only copys data if it's assigned and now it also copies the ID
41 - it seems that lazarus dont like comments in comments.
43 - It's possible to set the id of the texture
44 - define GLB_NO_NATIVE_GL deactivated by default
46 - Now supports the following libraries
50 - Linux compatibillity via free pascal compatibility (delphi sources optional)
51 - BMPs now loaded manuel
53 - Property DataPtr now has the name Data
54 - Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR
55 - Unused Depth removed
56 - Function FreeData to freeing image data added
58 - ImageID flag of TGAs was ignored. (Thanks Zwoetzen)
60 - Function SetBorderColor implemented (only used by opengl if wrap is set to GL_CLAMP_TO_BORDER)
61 - Function AddAlphaFromValue implemented to use an fixed Value as Alphachannel
62 - Function ReadOpenGLExtension is now only intern
64 - pngimage now disabled by default like all other versions.
66 - Setting up an anisotropic filter of 0 isnt allowed by nvidia (Thanks Ogridi)
68 - Fixed some Problem with Delphi 5
69 - Now uses the newest version of pngimage. Makes saving pngs much easier.
71 - Property IsCompressed and Size removed. Not really supported by Spec (Thanks Ogridi)
73 - Internal Format ifDepth8 added
74 - function GrabScreen now supports all uncompressed formats
76 - AddAlphaFromglBitmap implemented
78 - LoadFromResource and LoadFromResourceId now needs an Instance and an ResourceType (for ID)
80 - Width, Height and Depth internal changed to TglBitmapPixelPosition.
81 property Width, Height, Depth are still existing and new property Dimension are avail
83 - Added native OpenGL Support. Breaking the dglOpenGL "barrier".
85 - Added function GrabScreen to class TglBitmap2D
87 - Added support to Save images
88 - Added function Clone to Clone Instance
90 - Functions now works with Cardinals for each channel. Up to 32 Bits per channel.
92 - Several speed optimizations
94 - Internal structure change. Loading of TGA, PNG and DDS improved.
95 Data, format and size will now set directly with SetDataPtr.
96 - AddFunc now works with all Types of Images and Formats
97 - Some Funtions moved to Baseclass TglBitmap
99 - Added Support to decompress DXT3 and DXT5 compressed Images.
100 - Added Mapping to convert data from one format into an other.
102 - Added method ConvertTo in Class TglBitmap2D. Method allows to convert every
103 supported Input format (supported by GetPixel) into any uncompresed Format
104 - Added Support to decompress DXT1 compressed Images.
105 - SwapColors replaced by ConvertTo
107 - Added Support for compressed DDSs
108 - Added new internal formats (DXT1, DXT3, DXT5)
110 - Parameter Components renamed to InternalFormat
112 - Some AllocMem replaced with GetMem (little speed change)
113 - better exception handling. Better protection from memory leaks.
115 - Added support for Direct Draw Surfaces (.DDS) (uncompressed images only)
116 - Added new internal formats (RGB8, RGBA8, RGBA4, RGB5A1, RGB10A2, R5G6B5)
118 - Added support for Grayscale textures
119 - Added internal formats (Alpha, Luminance, LuminanceAlpha, BGR8, BGRA8)
121 - Added support for GL_VERSION_2_0
122 - Added support for GL_EXT_texture_filter_anisotropic
124 - Function FillWithColor fills the Image with one Color
125 - Function LoadNormalMap added
127 - ToNormalMap allows to Create an NormalMap from the Alphachannel
128 - ToNormalMap now supports Sobel (nmSobel) function.
130 - support for RLE Compressed RGB TGAs added
132 - Class TglBitmapNormalMap added to support Normalmap generation
133 - Added function ToNormalMap in class TglBitmap2D to genereate normal maps from textures.
134 3 Filters are supported. (4 Samples, 3x3 and 5x5)
136 - Method LoadCubeMapClass removed
137 - LoadCubeMap returnvalue is now the Texture paramter. Such as LoadTextures
138 - virtual abstract method GenTexture in class TglBitmap now is protected
140 - now support DescriptionFlag in LoadTga. Allows vertical flipped images to be loaded as normal
142 - little enhancement for IsPowerOfTwo
143 - TglBitmap1D.GenTexture now tests NPOT Textures
145 - some little name changes. All properties or function with Texture in name are
146 now without texture in name. We have allways texture so we dosn't name it.
148 - GenTexture now tests if texture is NPOT and NPOT-Texture are supported or
149 TextureTarget is GL_TEXTURE_RECTANGLE. Else it raised an exception.
151 - added support for GL_ARB_texture_rectangle, GL_EXT_texture_rectangle and GL_NV_texture_rectangle
153 - Function Unbind added
154 - call of SetFilter or SetTextureWrap if TextureID exists results in setting properties to opengl texture.
156 - class TglBitmapCubeMap added (allows to Create Cubemaps)
158 - Added Support for PNG Images. (http://pngdelphi.sourceforge.net/)
159 To Enable png's use the define pngimage
161 - New Functioninterface added
162 - Function GetPixel added
164 - Property BuildMipMaps renamed to MipMap
166 - property Name removed.
167 - BuildMipMaps is now a set of 3 values. None, GluBuildMipmaps and SGIS_generate_mipmap
169 - property name added. Only used in glForms!
171 - property FreeDataAfterGenTexture is now available as default (default = true)
172 - BuildMipmaps now implemented in TglBitmap1D (i've forgotten it)
173 - function MoveMemory replaced with function Move (little speed change)
174 - several calculations stored in variables (little speed change)
176 - property BuildMipsMaps added (default = true)
177 if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps
178 - property FreeDataAfterGenTexture added (default = true)
179 if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated.
180 - parameter DisableOtherTextureUnits of Bind removed
181 - parameter FreeDataAfterGeneration of GenTextures removed
183 - TglBitmap dosn't delete data if class was destroyed (fixed)
185 - Bind now enables TextureUnits (by params)
186 - GenTextures can leave data (by param)
187 - LoadTextures now optimal
189 - Performance optimization in AddFunc
190 - procedure Bind moved to subclasses
191 - Added new Class TglBitmap1D to support real OpenGL 1D Textures
193 - Texturefilter and texturewrap now also as defaults
194 Minfilter = GL_LINEAR_MIPMAP_LINEAR
195 Magfilter = GL_LINEAR
196 Wrap(str) = GL_CLAMP_TO_EDGE
197 - Added new format tfCompressed to create a compressed texture.
198 - propertys IsCompressed, TextureSize and IsResident added
199 IsCompressed and TextureSize only contains data from level 0
201 - Added function AddFunc to add PerPixelEffects to Image
202 - LoadFromFunc now based on AddFunc
203 - Invert now based on AddFunc
204 - SwapColors now based on AddFunc
206 - Added function FlipHorz
208 - Added function LaodFromFunc to create images with function
209 - Added function FlipVert
210 - Added internal format RGB(A) if GL_EXT_bgra or OpenGL 1.2 isn't supported
212 - Added Alphafunctions to calculate alpha per function
213 - Added Alpha from ColorKey using alphafunctions
215 - First full functionally Version of glBitmap
216 - Support for 24Bit and 32Bit TGA Pictures added
218 - begin of programming
219 ***********************************************************}
222 // Please uncomment the defines below to configure the glBitmap to your preferences.
223 // If you have configured the unit you can uncomment the warning above.
224 {$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
227 // Preferences ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
229 // activate to enable build-in OpenGL support with statically linked methods
230 // use dglOpenGL.pas if not enabled
231 {.$DEFINE GLB_NATIVE_OGL_STATIC}
233 // activate to enable build-in OpenGL support with dynamically linked methods
234 // use dglOpenGL.pas if not enabled
235 {.$DEFINE GLB_NATIVE_OGL_DYNAMIC}
238 // activate to enable the support for SDL_surfaces
241 // activate to enable the support for TBitmap from Delphi (not lazarus)
242 {.$DEFINE GLB_DELPHI}
244 // activate to enable the support for TLazIntfImage from Lazarus
245 {$DEFINE GLB_LAZARUS}
249 // activate to enable the support of SDL_image to load files. (READ ONLY)
250 // If you enable SDL_image all other libraries will be ignored!
251 {.$DEFINE GLB_SDL_IMAGE}
255 // activate to enable Lazarus TPortableNetworkGraphic support
256 // if you enable this pngImage and libPNG will be ignored
257 {$DEFINE GLB_LAZ_PNG}
259 // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/
260 // if you enable pngimage the libPNG will be ignored
261 {.$DEFINE GLB_PNGIMAGE}
263 // activate to use the libPNG -> http://www.libpng.org/
264 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libpng
265 {.$DEFINE GLB_LIB_PNG}
269 // activate to enable Lazarus TJPEGImage support
270 // if you enable this delphi jpegs and libJPEG will be ignored
271 {$DEFINE GLB_LAZ_JPEG}
273 // if you enable delphi jpegs the libJPEG will be ignored
274 {.$DEFINE GLB_DELPHI_JPEG}
276 // activate to use the libJPEG -> http://www.ijg.org/
277 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libjpeg
278 {.$DEFINE GLB_LIB_JPEG}
281 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
282 // PRIVATE: do not change anything! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299 {$IF DEFINED(WIN32) or DEFINED(WIN64) or DEFINED(WINDOWS)}
301 {$ELSEIF DEFINED(LINUX)}
305 // native OpenGL Support
306 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) OR DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
307 {$DEFINE GLB_NATIVE_OGL}
310 // checking define combinations
312 {$IFDEF GLB_SDL_IMAGE}
314 {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
319 {$MESSAGE warn 'The Lazarus TPortableNetworkGraphics will be ignored because you are using SDL_image.'}
323 {$IFDEF GLB_PNGIMAGE}
324 {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
325 {$undef GLB_PNGIMAGE}
328 {$IFDEF GLB_LAZ_JPEG}
329 {$MESSAGE warn 'The Lazarus TJPEGImage will be ignored because you are using SDL_image.'}
330 {$undef GLB_LAZ_JPEG}
333 {$IFDEF GLB_DELPHI_JPEG}
334 {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
335 {$undef GLB_DELPHI_JPEG}
339 {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
343 {$IFDEF GLB_LIB_JPEG}
344 {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
345 {$undef GLB_LIB_JPEG}
348 {$DEFINE GLB_SUPPORT_PNG_READ}
349 {$DEFINE GLB_SUPPORT_JPEG_READ}
352 // Lazarus TPortableNetworkGraphic
354 {$IFNDEF GLB_LAZARUS}
355 {$MESSAGE warn 'Lazarus TPortableNetworkGraphic won''t work without Lazarus. Lazarus will be activated.'}
356 {$DEFINE GLB_LAZARUS}
359 {$IFDEF GLB_PNGIMAGE}
360 {$MESSAGE warn 'The pngimage will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
361 {$undef GLB_PNGIMAGE}
365 {$MESSAGE warn 'The library libPNG will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
369 {$DEFINE GLB_SUPPORT_PNG_READ}
370 {$DEFINE GLB_SUPPORT_PNG_WRITE}
374 {$IFDEF GLB_PNGIMAGE}
376 {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'}
380 {$DEFINE GLB_SUPPORT_PNG_READ}
381 {$DEFINE GLB_SUPPORT_PNG_WRITE}
386 {$DEFINE GLB_SUPPORT_PNG_READ}
387 {$DEFINE GLB_SUPPORT_PNG_WRITE}
390 // Lazarus TJPEGImage
391 {$IFDEF GLB_LAZ_JPEG}
392 {$IFNDEF GLB_LAZARUS}
393 {$MESSAGE warn 'Lazarus TJPEGImage won''t work without Lazarus. Lazarus will be activated.'}
394 {$DEFINE GLB_LAZARUS}
397 {$IFDEF GLB_DELPHI_JPEG}
398 {$MESSAGE warn 'The Delphi JPEGImage will be ignored if you are using the Lazarus TJPEGImage.'}
399 {$undef GLB_DELPHI_JPEG}
402 {$IFDEF GLB_LIB_JPEG}
403 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the Lazarus TJPEGImage.'}
404 {$undef GLB_LIB_JPEG}
407 {$DEFINE GLB_SUPPORT_JPEG_READ}
408 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
412 {$IFDEF GLB_DELPHI_JPEG}
413 {$IFDEF GLB_LIB_JPEG}
414 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
415 {$undef GLB_LIB_JPEG}
418 {$DEFINE GLB_SUPPORT_JPEG_READ}
419 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
423 {$IFDEF GLB_LIB_JPEG}
424 {$DEFINE GLB_SUPPORT_JPEG_READ}
425 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
429 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) AND DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
430 {$MESSAGE warn 'GLB_NATIVE_OGL_STATIC will be ignored because you enabled GLB_NATIVE_OGL_DYNAMIC'}
444 {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF}
445 {$IF DEFINED(GLB_WIN) AND
446 DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND}
448 {$IFDEF GLB_SDL} SDL, {$ENDIF}
449 {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, Graphics, {$ENDIF}
450 {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF}
452 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
453 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
454 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
455 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
456 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
460 {$IFDEF GLB_NATIVE_OGL}
469 GL_EXTENSIONS = $1F03;
471 GL_TEXTURE_1D = $0DE0;
472 GL_TEXTURE_2D = $0DE1;
473 GL_TEXTURE_RECTANGLE = $84F5;
475 GL_NORMAL_MAP = $8511;
476 GL_TEXTURE_CUBE_MAP = $8513;
477 GL_REFLECTION_MAP = $8512;
478 GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515;
479 GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516;
480 GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517;
481 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518;
482 GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519;
483 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A;
485 GL_TEXTURE_WIDTH = $1000;
486 GL_TEXTURE_HEIGHT = $1001;
487 GL_TEXTURE_INTERNAL_FORMAT = $1003;
488 GL_TEXTURE_SWIZZLE_RGBA = $8E46;
495 GL_TEXTURE_GEN_S = $0C60;
496 GL_TEXTURE_GEN_T = $0C61;
497 GL_TEXTURE_GEN_R = $0C62;
498 GL_TEXTURE_GEN_Q = $0C63;
510 GL_LUMINANCE = $1909;
511 GL_LUMINANCE4 = $803F;
512 GL_LUMINANCE8 = $8040;
513 GL_LUMINANCE12 = $8041;
514 GL_LUMINANCE16 = $8042;
516 GL_LUMINANCE_ALPHA = $190A;
517 GL_LUMINANCE4_ALPHA4 = $8043;
518 GL_LUMINANCE6_ALPHA2 = $8044;
519 GL_LUMINANCE8_ALPHA8 = $8045;
520 GL_LUMINANCE12_ALPHA4 = $8046;
521 GL_LUMINANCE12_ALPHA12 = $8047;
522 GL_LUMINANCE16_ALPHA16 = $8048;
545 GL_DEPTH_COMPONENT = $1902;
546 GL_DEPTH_COMPONENT16 = $81A5;
547 GL_DEPTH_COMPONENT24 = $81A6;
548 GL_DEPTH_COMPONENT32 = $81A7;
550 GL_COMPRESSED_RGB = $84ED;
551 GL_COMPRESSED_RGBA = $84EE;
552 GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
553 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
554 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
555 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
557 GL_UNSIGNED_BYTE = $1401;
558 GL_UNSIGNED_BYTE_3_3_2 = $8032;
559 GL_UNSIGNED_BYTE_2_3_3_REV = $8362;
561 GL_UNSIGNED_SHORT = $1403;
562 GL_UNSIGNED_SHORT_5_6_5 = $8363;
563 GL_UNSIGNED_SHORT_4_4_4_4 = $8033;
564 GL_UNSIGNED_SHORT_5_5_5_1 = $8034;
565 GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
566 GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
567 GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
569 GL_UNSIGNED_INT = $1405;
570 GL_UNSIGNED_INT_8_8_8_8 = $8035;
571 GL_UNSIGNED_INT_10_10_10_2 = $8036;
572 GL_UNSIGNED_INT_8_8_8_8_REV = $8367;
573 GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
576 GL_TEXTURE_MAG_FILTER = $2800;
577 GL_TEXTURE_MIN_FILTER = $2801;
579 GL_NEAREST_MIPMAP_NEAREST = $2700;
580 GL_NEAREST_MIPMAP_LINEAR = $2702;
582 GL_LINEAR_MIPMAP_NEAREST = $2701;
583 GL_LINEAR_MIPMAP_LINEAR = $2703;
586 GL_TEXTURE_WRAP_S = $2802;
587 GL_TEXTURE_WRAP_T = $2803;
588 GL_TEXTURE_WRAP_R = $8072;
591 GL_CLAMP_TO_EDGE = $812F;
592 GL_CLAMP_TO_BORDER = $812D;
593 GL_MIRRORED_REPEAT = $8370;
596 GL_GENERATE_MIPMAP = $8191;
597 GL_TEXTURE_BORDER_COLOR = $1004;
598 GL_MAX_TEXTURE_SIZE = $0D33;
599 GL_PACK_ALIGNMENT = $0D05;
600 GL_UNPACK_ALIGNMENT = $0CF5;
602 GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
603 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
604 GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C;
605 GL_TEXTURE_GEN_MODE = $2500;
607 {$IF DEFINED(GLB_WIN)}
608 libglu = 'glu32.dll';
609 libopengl = 'opengl32.dll';
610 {$ELSEIF DEFINED(GLB_LINUX)}
611 libglu = 'libGLU.so.1';
612 libopengl = 'libGL.so.1';
616 GLboolean = BYTEBOOL;
624 PGLboolean = ^GLboolean;
629 TglCompressedTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
630 TglCompressedTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
631 TglGetCompressedTexImage = procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
633 {$IF DEFINED(GLB_WIN)}
634 TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall;
635 {$ELSEIF DEFINED(GLB_LINUX)}
636 TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl;
637 TglXGetProcAddressARB = function(const name: PAnsiChar): pointer; cdecl;
640 {$IF DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
641 TglEnable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
642 TglDisable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
644 TglGetString = function(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
645 TglGetIntegerv = procedure(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
647 TglTexParameteri = procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
648 TglTexParameteriv = procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
649 TglTexParameterfv = procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
650 TglGetTexParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
651 TglGetTexParameterfv = procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
652 TglGetTexLevelParameteriv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
653 TglGetTexLevelParameterfv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
655 TglTexGeni = procedure(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
656 TglGenTextures = procedure(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
657 TglBindTexture = procedure(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
658 TglDeleteTextures = procedure(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
660 TglAreTexturesResident = function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
661 TglReadPixels = procedure(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
662 TglPixelStorei = procedure(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
664 TglTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
665 TglTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
666 TglGetTexImage = procedure(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
668 TgluBuild1DMipmaps = function(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
669 TgluBuild2DMipmaps = function(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
671 {$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)}
672 procedure glEnable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
673 procedure glDisable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
675 function glGetString(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
676 procedure glGetIntegerv(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
678 procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
679 procedure glTexParameteriv(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
680 procedure glTexParameterfv(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
681 procedure glGetTexParameteriv(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
682 procedure glGetTexParameterfv(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
683 procedure glGetTexLevelParameteriv(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
684 procedure glGetTexLevelParameterfv(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
686 procedure glTexGeni(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
687 procedure glGenTextures(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
688 procedure glBindTexture(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
689 procedure glDeleteTextures(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
691 function glAreTexturesResident(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
692 procedure glReadPixels(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
693 procedure glPixelStorei(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
695 procedure glTexImage1D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
696 procedure glTexImage2D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
697 procedure glGetTexImage(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
699 function gluBuild1DMipmaps(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
700 function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
710 GL_SGIS_generate_mipmap,
712 GL_ARB_texture_border_clamp,
713 GL_ARB_texture_mirrored_repeat,
714 GL_ARB_texture_rectangle,
715 GL_ARB_texture_non_power_of_two,
716 GL_ARB_texture_swizzle,
717 GL_ARB_texture_cube_map,
719 GL_IBM_texture_mirrored_repeat,
721 GL_NV_texture_rectangle,
723 GL_EXT_texture_edge_clamp,
724 GL_EXT_texture_rectangle,
725 GL_EXT_texture_swizzle,
726 GL_EXT_texture_cube_map,
727 GL_EXT_texture_filter_anisotropic: Boolean;
729 glCompressedTexImage1D: TglCompressedTexImage1D;
730 glCompressedTexImage2D: TglCompressedTexImage2D;
731 glGetCompressedTexImage: TglGetCompressedTexImage;
733 {$IF DEFINED(GLB_WIN)}
734 wglGetProcAddress: TwglGetProcAddress;
735 {$ELSEIF DEFINED(GLB_LINUX)}
736 glXGetProcAddress: TglXGetProcAddress;
737 glXGetProcAddressARB: TglXGetProcAddress;
740 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
742 glDisable: TglDisable;
744 glGetString: TglGetString;
745 glGetIntegerv: TglGetIntegerv;
747 glTexParameteri: TglTexParameteri;
748 glTexParameteriv: TglTexParameteriv;
749 glTexParameterfv: TglTexParameterfv;
750 glGetTexParameteriv: TglGetTexParameteriv;
751 glGetTexParameterfv: TglGetTexParameterfv;
752 glGetTexLevelParameteriv: TglGetTexLevelParameteriv;
753 glGetTexLevelParameterfv: TglGetTexLevelParameterfv;
755 glTexGeni: TglTexGeni;
756 glGenTextures: TglGenTextures;
757 glBindTexture: TglBindTexture;
758 glDeleteTextures: TglDeleteTextures;
760 glAreTexturesResident: TglAreTexturesResident;
761 glReadPixels: TglReadPixels;
762 glPixelStorei: TglPixelStorei;
764 glTexImage1D: TglTexImage1D;
765 glTexImage2D: TglTexImage2D;
766 glGetTexImage: TglGetTexImage;
768 gluBuild1DMipmaps: TgluBuild1DMipmaps;
769 gluBuild2DMipmaps: TgluBuild2DMipmaps;
774 ////////////////////////////////////////////////////////////////////////////////////////////////////
776 tfEmpty = 0, //must be smallest value!
792 tfLuminance12Alpha12,
793 tfLuminance16Alpha16,
837 TglBitmapFileType = (
838 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
839 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
843 TglBitmapFileTypes = set of TglBitmapFileType;
850 TglBitmapNormalMapFunc = (
856 ////////////////////////////////////////////////////////////////////////////////////////////////////
857 EglBitmap = class(Exception);
858 EglBitmapNotSupported = class(Exception);
859 EglBitmapSizeToLarge = class(EglBitmap);
860 EglBitmapNonPowerOfTwo = class(EglBitmap);
861 EglBitmapUnsupportedFormat = class(EglBitmap)
862 constructor Create(const aFormat: TglBitmapFormat); overload;
863 constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload;
866 ////////////////////////////////////////////////////////////////////////////////////////////////////
867 TglBitmapColorRec = packed record
869 0: (r, g, b, a: Cardinal);
870 1: (arr: array[0..3] of Cardinal);
873 TglBitmapPixelData = packed record
874 Data, Range: TglBitmapColorRec;
875 Format: TglBitmapFormat;
877 PglBitmapPixelData = ^TglBitmapPixelData;
879 ////////////////////////////////////////////////////////////////////////////////////////////////////
880 TglBitmapPixelPositionFields = set of (ffX, ffY);
881 TglBitmapPixelPosition = record
882 Fields : TglBitmapPixelPositionFields;
887 TglBitmapFormatDescriptor = class(TObject)
889 function GetIsCompressed: Boolean; virtual; abstract;
890 function GetHasAlpha: Boolean; virtual; abstract;
892 function GetglDataFormat: GLenum; virtual; abstract;
893 function GetglFormat: GLenum; virtual; abstract;
894 function GetglInternalFormat: GLenum; virtual; abstract;
896 property IsCompressed: Boolean read GetIsCompressed;
897 property HasAlpha: Boolean read GetHasAlpha;
899 property glFormat: GLenum read GetglFormat;
900 property glInternalFormat: GLenum read GetglInternalFormat;
901 property glDataFormat: GLenum read GetglDataFormat;
904 ////////////////////////////////////////////////////////////////////////////////////////////////////
906 TglBitmapFunctionRec = record
908 Size: TglBitmapPixelPosition;
909 Position: TglBitmapPixelPosition;
910 Source: TglBitmapPixelData;
911 Dest: TglBitmapPixelData;
914 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
916 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
919 function GetFormatDesc: TglBitmapFormatDescriptor;
923 fAnisotropic: Integer;
924 fDeleteTextureOnFree: Boolean;
925 fFreeDataAfterGenTexture: Boolean;
927 fIsResident: Boolean;
928 fBorderColor: array[0..3] of Single;
930 fDimension: TglBitmapPixelPosition;
931 fMipMap: TglBitmapMipMap;
932 fFormat: TglBitmapFormat;
948 fSwizzle: array[0..3] of GLenum;
953 fCustomNameW: WideString;
954 fCustomData: Pointer;
957 function GetWidth: Integer; virtual;
958 function GetHeight: Integer; virtual;
960 function GetFileWidth: Integer; virtual;
961 function GetFileHeight: Integer; virtual;
964 procedure SetCustomData(const aValue: Pointer);
965 procedure SetCustomName(const aValue: String);
966 procedure SetCustomNameW(const aValue: WideString);
967 procedure SetDeleteTextureOnFree(const aValue: Boolean);
968 procedure SetFormat(const aValue: TglBitmapFormat);
969 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
970 procedure SetID(const aValue: Cardinal);
971 procedure SetMipMap(const aValue: TglBitmapMipMap);
972 procedure SetTarget(const aValue: Cardinal);
973 procedure SetAnisotropic(const aValue: Integer);
976 procedure SetupParameters(out aBuildWithGlu: Boolean);
977 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
978 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; //be careful, aData could be freed by this method
979 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
981 function FlipHorz: Boolean; virtual;
982 function FlipVert: Boolean; virtual;
984 property Width: Integer read GetWidth;
985 property Height: Integer read GetHeight;
987 property FileWidth: Integer read GetFileWidth;
988 property FileHeight: Integer read GetFileHeight;
991 property ID: Cardinal read fID write SetID;
992 property Target: Cardinal read fTarget write SetTarget;
993 property Format: TglBitmapFormat read fFormat write SetFormat;
994 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
995 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
997 property FormatDesc: TglBitmapFormatDescriptor read GetFormatDesc;
999 property Filename: String read fFilename;
1000 property CustomName: String read fCustomName write SetCustomName;
1001 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
1002 property CustomData: Pointer read fCustomData write SetCustomData;
1004 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
1005 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
1007 property Dimension: TglBitmapPixelPosition read fDimension;
1008 property Data: PByte read fData;
1009 property IsResident: Boolean read fIsResident;
1011 procedure AfterConstruction; override;
1012 procedure BeforeDestruction; override;
1014 procedure PrepareResType(var aResource: String; var aResType: PChar);
1017 procedure LoadFromFile(const aFilename: String);
1018 procedure LoadFromStream(const aStream: TStream); virtual;
1019 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
1020 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil);
1021 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil);
1022 procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
1025 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
1026 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
1029 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
1030 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
1031 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
1035 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
1036 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
1037 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
1038 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
1039 const aArgs: Pointer = nil): Boolean;
1043 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
1044 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
1045 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
1046 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
1047 const aArgs: Pointer = nil): Boolean;
1050 {$IFDEF GLB_LAZARUS}
1051 function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1052 function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
1053 function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1054 function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil;
1055 const aArgs: Pointer = nil): Boolean;
1058 function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil;
1059 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1060 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
1061 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1063 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
1064 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1065 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1066 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1068 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
1069 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
1070 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
1072 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
1073 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
1074 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
1076 function RemoveAlpha: Boolean; virtual;
1079 function Clone: TglBitmap;
1080 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
1081 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
1082 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
1086 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
1087 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
1088 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
1091 procedure SetFilter(const aMin, aMag: GLenum);
1093 const S: GLenum = GL_CLAMP_TO_EDGE;
1094 const T: GLenum = GL_CLAMP_TO_EDGE;
1095 const R: GLenum = GL_CLAMP_TO_EDGE);
1096 procedure SetSwizzle(const r, g, b, a: GLenum);
1098 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
1099 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
1102 constructor Create; overload;
1103 constructor Create(const aFileName: String); overload;
1104 constructor Create(const aStream: TStream); overload;
1105 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload;
1106 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
1107 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
1108 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
1110 {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1111 {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF}
1113 {$IFDEF GLB_SUPPORT_JPEG_READ} function LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1114 {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF}
1116 function LoadBMP(const aStream: TStream): Boolean; virtual;
1117 procedure SaveBMP(const aStream: TStream); virtual;
1119 function LoadTGA(const aStream: TStream): Boolean; virtual;
1120 procedure SaveTGA(const aStream: TStream); virtual;
1122 function LoadDDS(const aStream: TStream): Boolean; virtual;
1123 procedure SaveDDS(const aStream: TStream); virtual;
1126 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1127 TglBitmap1D = class(TglBitmap)
1129 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1130 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1131 procedure UploadData(const aBuildWithGlu: Boolean);
1134 procedure AfterConstruction; override;
1135 function FlipHorz: Boolean; override;
1136 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1139 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1140 TglBitmap2D = class(TglBitmap)
1142 fLines: array of PByte;
1143 function GetScanline(const aIndex: Integer): Pointer;
1144 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1145 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1146 procedure UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
1150 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
1152 procedure AfterConstruction; override;
1154 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
1155 procedure GetDataFromTexture;
1156 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1158 function FlipHorz: Boolean; override;
1159 function FlipVert: Boolean; override;
1161 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
1162 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1165 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1166 TglBitmapCubeMap = class(TglBitmap2D)
1169 procedure GenTexture(const aTestTextureSize: Boolean = true); reintroduce;
1171 procedure AfterConstruction; override;
1172 procedure GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean = true);
1173 procedure Bind(const aEnableTexCoordsGen: Boolean = true; const aEnableTextureUnit: Boolean = true); reintroduce; virtual;
1174 procedure Unbind(const aDisableTexCoordsGen: Boolean = true; const aDisableTextureUnit: Boolean = true); reintroduce; virtual;
1177 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1178 TglBitmapNormalMap = class(TglBitmapCubeMap)
1180 procedure AfterConstruction; override;
1181 procedure GenerateNormalMap(const aSize: Integer = 32; const aTestTextureSize: Boolean = true);
1185 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1187 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1188 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1189 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1190 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1191 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1192 procedure glBitmapSetDefaultWrap(
1193 const S: Cardinal = GL_CLAMP_TO_EDGE;
1194 const T: Cardinal = GL_CLAMP_TO_EDGE;
1195 const R: Cardinal = GL_CLAMP_TO_EDGE);
1197 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1198 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1199 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1200 function glBitmapGetDefaultFormat: TglBitmapFormat;
1201 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1202 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1204 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1205 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1206 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1209 glBitmapDefaultDeleteTextureOnFree: Boolean;
1210 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1211 glBitmapDefaultFormat: TglBitmapFormat;
1212 glBitmapDefaultMipmap: TglBitmapMipMap;
1213 glBitmapDefaultFilterMin: Cardinal;
1214 glBitmapDefaultFilterMag: Cardinal;
1215 glBitmapDefaultWrapS: Cardinal;
1216 glBitmapDefaultWrapT: Cardinal;
1217 glBitmapDefaultWrapR: Cardinal;
1218 glDefaultSwizzle: array[0..3] of GLenum;
1221 function CreateGrayPalette: HPALETTE;
1227 Math, syncobjs, typinfo;
1231 QWord = System.UInt64;
1238 ////////////////////////////////////////////////////////////////////////////////////////////////////
1239 TShiftRec = packed record
1241 0: (r, g, b, a: Byte);
1242 1: (arr: array[0..3] of Byte);
1245 TFormatDescriptor = class(TglBitmapFormatDescriptor)
1247 function GetRedMask: QWord;
1248 function GetGreenMask: QWord;
1249 function GetBlueMask: QWord;
1250 function GetAlphaMask: QWord;
1252 fFormat: TglBitmapFormat;
1253 fWithAlpha: TglBitmapFormat;
1254 fWithoutAlpha: TglBitmapFormat;
1255 fRGBInverted: TglBitmapFormat;
1256 fUncompressed: TglBitmapFormat;
1258 fIsCompressed: Boolean;
1260 fRange: TglBitmapColorRec;
1264 fglInternalFormat: GLenum;
1265 fglDataFormat: GLenum;
1267 function GetIsCompressed: Boolean; override;
1268 function GetHasAlpha: Boolean; override;
1270 function GetglFormat: GLenum; override;
1271 function GetglInternalFormat: GLenum; override;
1272 function GetglDataFormat: GLenum; override;
1274 function GetComponents: Integer; virtual;
1276 property Format: TglBitmapFormat read fFormat;
1277 property WithAlpha: TglBitmapFormat read fWithAlpha;
1278 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1279 property RGBInverted: TglBitmapFormat read fRGBInverted;
1280 property Components: Integer read GetComponents;
1281 property PixelSize: Single read fPixelSize;
1283 property Range: TglBitmapColorRec read fRange;
1284 property Shift: TShiftRec read fShift;
1286 property RedMask: QWord read GetRedMask;
1287 property GreenMask: QWord read GetGreenMask;
1288 property BlueMask: QWord read GetBlueMask;
1289 property AlphaMask: QWord read GetAlphaMask;
1291 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1292 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1294 function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual;
1295 function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
1297 function CreateMappingData: Pointer; virtual;
1298 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1300 function IsEmpty: Boolean; virtual;
1301 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual;
1303 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1305 constructor Create; virtual;
1307 class procedure Init;
1308 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1309 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1310 class procedure Clear;
1311 class procedure Finalize;
1313 TFormatDescriptorClass = class of TFormatDescriptor;
1315 TfdEmpty = class(TFormatDescriptor);
1317 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1318 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1319 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1320 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1321 constructor Create; override;
1324 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1325 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1326 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1327 constructor Create; override;
1330 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1331 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1332 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1333 constructor Create; override;
1336 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1337 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1338 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1339 constructor Create; override;
1342 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1343 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1344 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1345 constructor Create; override;
1348 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1349 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1350 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1351 constructor Create; override;
1354 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1355 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1356 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1357 constructor Create; override;
1360 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1361 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1362 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1363 constructor Create; override;
1366 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1367 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1368 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1369 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1370 constructor Create; override;
1373 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1374 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1375 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1376 constructor Create; override;
1379 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1380 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1381 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1382 constructor Create; override;
1385 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1386 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1387 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1388 constructor Create; override;
1391 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1392 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1393 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1394 constructor Create; override;
1397 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1398 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1399 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1400 constructor Create; override;
1403 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1404 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1405 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1406 constructor Create; override;
1409 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1410 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1411 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1412 constructor Create; override;
1415 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1416 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1417 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1418 constructor Create; override;
1421 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1422 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1423 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1424 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1425 constructor Create; override;
1428 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1429 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1430 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1431 constructor Create; override;
1434 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1435 TfdAlpha4 = class(TfdAlpha_UB1)
1436 constructor Create; override;
1439 TfdAlpha8 = class(TfdAlpha_UB1)
1440 constructor Create; override;
1443 TfdAlpha12 = class(TfdAlpha_US1)
1444 constructor Create; override;
1447 TfdAlpha16 = class(TfdAlpha_US1)
1448 constructor Create; override;
1451 TfdLuminance4 = class(TfdLuminance_UB1)
1452 constructor Create; override;
1455 TfdLuminance8 = class(TfdLuminance_UB1)
1456 constructor Create; override;
1459 TfdLuminance12 = class(TfdLuminance_US1)
1460 constructor Create; override;
1463 TfdLuminance16 = class(TfdLuminance_US1)
1464 constructor Create; override;
1467 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1468 constructor Create; override;
1471 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1472 constructor Create; override;
1475 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1476 constructor Create; override;
1479 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1480 constructor Create; override;
1483 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1484 constructor Create; override;
1487 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1488 constructor Create; override;
1491 TfdR3G3B2 = class(TfdUniversal_UB1)
1492 constructor Create; override;
1495 TfdRGB4 = class(TfdUniversal_US1)
1496 constructor Create; override;
1499 TfdR5G6B5 = class(TfdUniversal_US1)
1500 constructor Create; override;
1503 TfdRGB5 = class(TfdUniversal_US1)
1504 constructor Create; override;
1507 TfdRGB8 = class(TfdRGB_UB3)
1508 constructor Create; override;
1511 TfdRGB10 = class(TfdUniversal_UI1)
1512 constructor Create; override;
1515 TfdRGB12 = class(TfdRGB_US3)
1516 constructor Create; override;
1519 TfdRGB16 = class(TfdRGB_US3)
1520 constructor Create; override;
1523 TfdRGBA2 = class(TfdRGBA_UB4)
1524 constructor Create; override;
1527 TfdRGBA4 = class(TfdUniversal_US1)
1528 constructor Create; override;
1531 TfdRGB5A1 = class(TfdUniversal_US1)
1532 constructor Create; override;
1535 TfdRGBA8 = class(TfdRGBA_UB4)
1536 constructor Create; override;
1539 TfdRGB10A2 = class(TfdUniversal_UI1)
1540 constructor Create; override;
1543 TfdRGBA12 = class(TfdRGBA_US4)
1544 constructor Create; override;
1547 TfdRGBA16 = class(TfdRGBA_US4)
1548 constructor Create; override;
1551 TfdBGR4 = class(TfdUniversal_US1)
1552 constructor Create; override;
1555 TfdB5G6R5 = class(TfdUniversal_US1)
1556 constructor Create; override;
1559 TfdBGR5 = class(TfdUniversal_US1)
1560 constructor Create; override;
1563 TfdBGR8 = class(TfdBGR_UB3)
1564 constructor Create; override;
1567 TfdBGR10 = class(TfdUniversal_UI1)
1568 constructor Create; override;
1571 TfdBGR12 = class(TfdBGR_US3)
1572 constructor Create; override;
1575 TfdBGR16 = class(TfdBGR_US3)
1576 constructor Create; override;
1579 TfdBGRA2 = class(TfdBGRA_UB4)
1580 constructor Create; override;
1583 TfdBGRA4 = class(TfdUniversal_US1)
1584 constructor Create; override;
1587 TfdBGR5A1 = class(TfdUniversal_US1)
1588 constructor Create; override;
1591 TfdBGRA8 = class(TfdBGRA_UB4)
1592 constructor Create; override;
1595 TfdBGR10A2 = class(TfdUniversal_UI1)
1596 constructor Create; override;
1599 TfdBGRA12 = class(TfdBGRA_US4)
1600 constructor Create; override;
1603 TfdBGRA16 = class(TfdBGRA_US4)
1604 constructor Create; override;
1607 TfdDepth16 = class(TfdDepth_US1)
1608 constructor Create; override;
1611 TfdDepth24 = class(TfdDepth_UI1)
1612 constructor Create; override;
1615 TfdDepth32 = class(TfdDepth_UI1)
1616 constructor Create; override;
1619 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1620 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1621 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1622 constructor Create; override;
1625 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1626 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1627 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1628 constructor Create; override;
1631 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1632 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1633 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1634 constructor Create; override;
1637 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1638 TbmpBitfieldFormat = class(TFormatDescriptor)
1640 procedure SetRedMask (const aValue: QWord);
1641 procedure SetGreenMask(const aValue: QWord);
1642 procedure SetBlueMask (const aValue: QWord);
1643 procedure SetAlphaMask(const aValue: QWord);
1645 procedure Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte);
1647 property RedMask: QWord read GetRedMask write SetRedMask;
1648 property GreenMask: QWord read GetGreenMask write SetGreenMask;
1649 property BlueMask: QWord read GetBlueMask write SetBlueMask;
1650 property AlphaMask: QWord read GetAlphaMask write SetAlphaMask;
1652 property PixelSize: Single read fPixelSize write fPixelSize;
1654 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1655 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1658 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1659 TbmpColorTableEnty = packed record
1662 TbmpColorTable = array of TbmpColorTableEnty;
1663 TbmpColorTableFormat = class(TFormatDescriptor)
1665 fColorTable: TbmpColorTable;
1667 property PixelSize: Single read fPixelSize write fPixelSize;
1668 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1669 property Range: TglBitmapColorRec read fRange write fRange;
1670 property Shift: TShiftRec read fShift write fShift;
1671 property Format: TglBitmapFormat read fFormat write fFormat;
1673 procedure CreateColorTable;
1675 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1676 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1677 destructor Destroy; override;
1681 LUMINANCE_WEIGHT_R = 0.30;
1682 LUMINANCE_WEIGHT_G = 0.59;
1683 LUMINANCE_WEIGHT_B = 0.11;
1685 ALPHA_WEIGHT_R = 0.30;
1686 ALPHA_WEIGHT_G = 0.59;
1687 ALPHA_WEIGHT_B = 0.11;
1689 DEPTH_WEIGHT_R = 0.333333333;
1690 DEPTH_WEIGHT_G = 0.333333333;
1691 DEPTH_WEIGHT_B = 0.333333333;
1693 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1695 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1708 TfdLuminance4Alpha4,
1709 TfdLuminance6Alpha2,
1710 TfdLuminance8Alpha8,
1711 TfdLuminance12Alpha4,
1712 TfdLuminance12Alpha12,
1713 TfdLuminance16Alpha16,
1758 FormatDescriptorCS: TCriticalSection;
1759 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1761 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1762 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1764 inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1767 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1768 constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat);
1770 inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1773 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1774 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1776 result.Fields := [];
1779 result.Fields := result.Fields + [ffX];
1781 result.Fields := result.Fields + [ffY];
1783 result.X := Max(0, X);
1784 result.Y := Max(0, Y);
1787 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1788 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1796 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1797 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1802 for i := 0 to high(r1.arr) do
1803 if (r1.arr[i] <> r2.arr[i]) then
1808 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1809 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1817 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1818 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1827 tfR3G3B2, tfLuminance8,
1830 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1831 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1837 tfRGB10, tfRGB10A2, tfRGBA8,
1838 tfBGR10, tfBGR10A2, tfBGRA8]) then
1839 result := result + [ftBMP];
1843 tfLuminance8, tfAlpha8,
1846 tfLuminance16, tfLuminance8Alpha8,
1847 tfRGB5, tfRGB5A1, tfRGBA4,
1848 tfBGR5, tfBGR5A1, tfBGRA4,
1854 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1855 result := result + [ftTGA];
1859 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1860 tfR3G3B2, tfRGBA2, tfBGRA2,
1863 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1864 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1865 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1871 tfLuminance16Alpha16,
1876 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1877 result := result + [ftDDS];
1879 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1881 tfAlpha8, tfLuminance8, tfLuminance8Alpha8,
1883 tfBGR8, tfBGRA8] then
1884 result := result + [ftPNG];
1887 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1888 if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then
1889 result := result + [ftJPEG];
1893 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1894 function IsPowerOfTwo(aNumber: Integer): Boolean;
1896 while (aNumber and 1) = 0 do
1897 aNumber := aNumber shr 1;
1898 result := aNumber = 1;
1901 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1902 function GetTopMostBit(aBitSet: QWord): Integer;
1905 while aBitSet > 0 do begin
1907 aBitSet := aBitSet shr 1;
1911 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1912 function CountSetBits(aBitSet: QWord): Integer;
1915 while aBitSet > 0 do begin
1916 if (aBitSet and 1) = 1 then
1918 aBitSet := aBitSet shr 1;
1922 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1923 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1926 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1927 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1928 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1931 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1932 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1935 DEPTH_WEIGHT_R * aPixel.Data.r +
1936 DEPTH_WEIGHT_G * aPixel.Data.g +
1937 DEPTH_WEIGHT_B * aPixel.Data.b);
1940 {$IFDEF GLB_NATIVE_OGL}
1941 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1942 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1943 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1945 GL_LibHandle: Pointer = nil;
1947 function glbGetProcAddress(aProcName: PChar; aLibHandle: Pointer = nil): Pointer;
1949 if not Assigned(aLibHandle) then
1950 aLibHandle := GL_LibHandle;
1952 {$IF DEFINED(GLB_WIN)}
1953 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1954 if Assigned(result) then
1957 if Assigned(wglGetProcAddress) then
1958 result := wglGetProcAddress(aProcName);
1959 {$ELSEIF DEFINED(GLB_LINUX)}
1960 if Assigned(glXGetProcAddress) then begin
1961 result := glXGetProcAddress(aProcName);
1962 if Assigned(result) then
1966 if Assigned(glXGetProcAddressARB) then begin
1967 result := glXGetProcAddressARB(aProcName);
1968 if Assigned(result) then
1972 result := dlsym(aLibHandle, aProcName);
1974 if not Assigned(result) then
1975 raise EglBitmap.Create('unable to load procedure form library: ' + aProcName);
1978 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1980 GLU_LibHandle: Pointer = nil;
1981 OpenGLInitialized: Boolean;
1982 InitOpenGLCS: TCriticalSection;
1984 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1985 procedure glbInitOpenGL;
1987 ////////////////////////////////////////////////////////////////////////////////
1988 function glbLoadLibrary(const aName: PChar): Pointer;
1990 {$IF DEFINED(GLB_WIN)}
1991 result := {%H-}Pointer(LoadLibrary(aName));
1992 {$ELSEIF DEFINED(GLB_LINUX)}
1993 result := dlopen(Name, RTLD_LAZY);
1999 ////////////////////////////////////////////////////////////////////////////////
2000 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
2003 if not Assigned(aLibHandle) then
2006 {$IF DEFINED(GLB_WIN)}
2007 Result := FreeLibrary({%H-}HINST(aLibHandle));
2008 {$ELSEIF DEFINED(GLB_LINUX)}
2009 Result := dlclose(aLibHandle) = 0;
2014 if Assigned(GL_LibHandle) then
2015 glbFreeLibrary(GL_LibHandle);
2017 if Assigned(GLU_LibHandle) then
2018 glbFreeLibrary(GLU_LibHandle);
2020 GL_LibHandle := glbLoadLibrary(libopengl);
2021 if not Assigned(GL_LibHandle) then
2022 raise EglBitmap.Create('unable to load library: ' + libopengl);
2024 GLU_LibHandle := glbLoadLibrary(libglu);
2025 if not Assigned(GLU_LibHandle) then
2026 raise EglBitmap.Create('unable to load library: ' + libglu);
2029 {$IF DEFINED(GLB_WIN)}
2030 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
2031 {$ELSEIF DEFINED(GLB_LINUX)}
2032 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
2033 glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
2036 glEnable := glbGetProcAddress('glEnable');
2037 glDisable := glbGetProcAddress('glDisable');
2038 glGetString := glbGetProcAddress('glGetString');
2039 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
2040 glTexParameteri := glbGetProcAddress('glTexParameteri');
2041 glTexParameteriv := glbGetProcAddress('glTexParameteriv');
2042 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
2043 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
2044 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
2045 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
2046 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
2047 glTexGeni := glbGetProcAddress('glTexGeni');
2048 glGenTextures := glbGetProcAddress('glGenTextures');
2049 glBindTexture := glbGetProcAddress('glBindTexture');
2050 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
2051 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
2052 glReadPixels := glbGetProcAddress('glReadPixels');
2053 glPixelStorei := glbGetProcAddress('glPixelStorei');
2054 glTexImage1D := glbGetProcAddress('glTexImage1D');
2055 glTexImage2D := glbGetProcAddress('glTexImage2D');
2056 glGetTexImage := glbGetProcAddress('glGetTexImage');
2058 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
2059 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
2061 glbFreeLibrary(GL_LibHandle);
2062 glbFreeLibrary(GLU_LibHandle);
2067 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2068 procedure glbReadOpenGLExtensions;
2071 MajorVersion, MinorVersion: Integer;
2073 ///////////////////////////////////////////////////////////////////////////////////////////
2074 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
2081 Separator := Pos(AnsiString('.'), aBuffer);
2082 if (Separator > 1) and (Separator < Length(aBuffer)) and
2083 (aBuffer[Separator - 1] in ['0'..'9']) and
2084 (aBuffer[Separator + 1] in ['0'..'9']) then begin
2087 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
2090 Delete(aBuffer, 1, Separator);
2091 Separator := Pos(AnsiString('.'), aBuffer) + 1;
2093 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
2096 Delete(aBuffer, Separator, 255);
2097 Separator := Pos(AnsiString('.'), aBuffer);
2099 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
2100 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2104 ///////////////////////////////////////////////////////////////////////////////////////////
2105 function CheckExtension(const Extension: AnsiString): Boolean;
2109 ExtPos := Pos(Extension, Buffer);
2110 result := ExtPos > 0;
2112 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2115 ///////////////////////////////////////////////////////////////////////////////////////////
2116 function CheckVersion(const aMajor, aMinor: Integer): Boolean;
2118 result := (MajorVersion > aMajor) or ((MajorVersion = aMajor) and (MinorVersion >= aMinor));
2122 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2125 if not OpenGLInitialized then begin
2127 OpenGLInitialized := true;
2135 Buffer := glGetString(GL_VERSION);
2136 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2138 GL_VERSION_1_2 := CheckVersion(1, 2);
2139 GL_VERSION_1_3 := CheckVersion(1, 3);
2140 GL_VERSION_1_4 := CheckVersion(1, 4);
2141 GL_VERSION_2_0 := CheckVersion(2, 0);
2142 GL_VERSION_3_3 := CheckVersion(3, 3);
2145 Buffer := glGetString(GL_EXTENSIONS);
2146 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2147 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2148 GL_ARB_texture_swizzle := CheckExtension('GL_ARB_texture_swizzle');
2149 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
2150 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2151 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2152 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2153 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2154 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2155 GL_EXT_texture_swizzle := CheckExtension('GL_EXT_texture_swizzle');
2156 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
2157 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2158 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2159 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2161 if GL_VERSION_1_3 then begin
2162 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2163 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2164 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2166 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB');
2167 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB');
2168 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB');
2173 {$IFDEF GLB_SDL_IMAGE}
2174 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2175 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2176 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2177 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2179 result := TStream(context^.unknown.data1).Seek(offset, whence);
2182 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2184 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2187 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2189 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2192 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2197 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2199 result := SDL_AllocRW;
2201 if result = nil then
2202 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2204 result^.seek := glBitmapRWseek;
2205 result^.read := glBitmapRWread;
2206 result^.write := glBitmapRWwrite;
2207 result^.close := glBitmapRWclose;
2208 result^.unknown.data1 := Stream;
2212 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2213 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2215 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2218 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2219 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2221 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2225 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2227 glBitmapDefaultMipmap := aValue;
2230 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2231 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2233 glBitmapDefaultFormat := aFormat;
2236 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2237 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2239 glBitmapDefaultFilterMin := aMin;
2240 glBitmapDefaultFilterMag := aMag;
2243 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2244 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2246 glBitmapDefaultWrapS := S;
2247 glBitmapDefaultWrapT := T;
2248 glBitmapDefaultWrapR := R;
2251 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2252 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
2254 glDefaultSwizzle[0] := r;
2255 glDefaultSwizzle[1] := g;
2256 glDefaultSwizzle[2] := b;
2257 glDefaultSwizzle[3] := a;
2260 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2261 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2263 result := glBitmapDefaultDeleteTextureOnFree;
2266 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2267 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2269 result := glBitmapDefaultFreeDataAfterGenTextures;
2272 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2273 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2275 result := glBitmapDefaultMipmap;
2278 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2279 function glBitmapGetDefaultFormat: TglBitmapFormat;
2281 result := glBitmapDefaultFormat;
2284 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2285 procedure glBitmapGetDefaultFilter(var aMin, aMag: GLenum);
2287 aMin := glBitmapDefaultFilterMin;
2288 aMag := glBitmapDefaultFilterMag;
2291 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2292 procedure glBitmapGetDefaultTextureWrap(var S, T, R: GLenum);
2294 S := glBitmapDefaultWrapS;
2295 T := glBitmapDefaultWrapT;
2296 R := glBitmapDefaultWrapR;
2299 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2300 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
2302 r := glDefaultSwizzle[0];
2303 g := glDefaultSwizzle[1];
2304 b := glDefaultSwizzle[2];
2305 a := glDefaultSwizzle[3];
2308 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2309 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2310 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2311 function TFormatDescriptor.GetRedMask: QWord;
2313 result := fRange.r shl fShift.r;
2316 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2317 function TFormatDescriptor.GetGreenMask: QWord;
2319 result := fRange.g shl fShift.g;
2322 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2323 function TFormatDescriptor.GetBlueMask: QWord;
2325 result := fRange.b shl fShift.b;
2328 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2329 function TFormatDescriptor.GetAlphaMask: QWord;
2331 result := fRange.a shl fShift.a;
2334 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2335 function TFormatDescriptor.GetIsCompressed: Boolean;
2337 result := fIsCompressed;
2340 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2341 function TFormatDescriptor.GetHasAlpha: Boolean;
2343 result := (fRange.a > 0);
2346 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2347 function TFormatDescriptor.GetglFormat: GLenum;
2349 result := fglFormat;
2352 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2353 function TFormatDescriptor.GetglInternalFormat: GLenum;
2355 result := fglInternalFormat;
2358 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2359 function TFormatDescriptor.GetglDataFormat: GLenum;
2361 result := fglDataFormat;
2364 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2365 function TFormatDescriptor.GetComponents: Integer;
2371 if (fRange.arr[i] > 0) then
2375 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2376 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2380 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2381 w := Max(1, aSize.X);
2382 h := Max(1, aSize.Y);
2383 result := GetSize(w, h);
2388 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2389 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2392 if (aWidth <= 0) or (aHeight <= 0) then
2394 result := Ceil(aWidth * aHeight * fPixelSize);
2397 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2398 function TFormatDescriptor.CreateMappingData: Pointer;
2403 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2404 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2409 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2410 function TFormatDescriptor.IsEmpty: Boolean;
2412 result := (fFormat = tfEmpty);
2415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2416 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2419 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2420 raise EglBitmap.Create('FormatCheckFormat - All Masks are 0');
2421 if (aRedMask <> RedMask) then
2423 if (aGreenMask <> GreenMask) then
2425 if (aBlueMask <> BlueMask) then
2427 if (aAlphaMask <> AlphaMask) then
2432 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2433 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2435 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2436 aPixel.Data := fRange;
2437 aPixel.Range := fRange;
2438 aPixel.Format := fFormat;
2441 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2442 constructor TFormatDescriptor.Create;
2447 fWithAlpha := tfEmpty;
2448 fWithoutAlpha := tfEmpty;
2449 fRGBInverted := tfEmpty;
2450 fUncompressed := tfEmpty;
2452 fIsCompressed := false;
2455 fglInternalFormat := 0;
2458 FillChar(fRange, 0, SizeOf(fRange));
2459 FillChar(fShift, 0, SizeOf(fShift));
2462 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2463 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2464 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2465 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2467 aData^ := aPixel.Data.a;
2471 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2476 aPixel.Data.a := aData^;
2480 constructor TfdAlpha_UB1.Create;
2485 fglFormat := GL_ALPHA;
2486 fglDataFormat := GL_UNSIGNED_BYTE;
2489 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2490 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2492 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2494 aData^ := LuminanceWeight(aPixel);
2498 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2500 aPixel.Data.r := aData^;
2501 aPixel.Data.g := aData^;
2502 aPixel.Data.b := aData^;
2507 constructor TfdLuminance_UB1.Create;
2514 fglFormat := GL_LUMINANCE;
2515 fglDataFormat := GL_UNSIGNED_BYTE;
2518 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2519 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2520 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2521 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2527 if (fRange.arr[i] > 0) then
2528 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2532 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2537 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2541 constructor TfdUniversal_UB1.Create;
2547 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2548 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2549 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2550 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2552 inherited Map(aPixel, aData, aMapData);
2553 aData^ := aPixel.Data.a;
2557 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2559 inherited Unmap(aData, aPixel, aMapData);
2560 aPixel.Data.a := aData^;
2564 constructor TfdLuminanceAlpha_UB2.Create;
2570 fglFormat := GL_LUMINANCE_ALPHA;
2571 fglDataFormat := GL_UNSIGNED_BYTE;
2574 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2575 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2576 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2577 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2579 aData^ := aPixel.Data.r;
2581 aData^ := aPixel.Data.g;
2583 aData^ := aPixel.Data.b;
2587 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2589 aPixel.Data.r := aData^;
2591 aPixel.Data.g := aData^;
2593 aPixel.Data.b := aData^;
2598 constructor TfdRGB_UB3.Create;
2608 fglFormat := GL_RGB;
2609 fglDataFormat := GL_UNSIGNED_BYTE;
2612 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2613 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2614 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2615 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2617 aData^ := aPixel.Data.b;
2619 aData^ := aPixel.Data.g;
2621 aData^ := aPixel.Data.r;
2625 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2627 aPixel.Data.b := aData^;
2629 aPixel.Data.g := aData^;
2631 aPixel.Data.r := aData^;
2636 constructor TfdBGR_UB3.Create;
2645 fglFormat := GL_BGR;
2646 fglDataFormat := GL_UNSIGNED_BYTE;
2649 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2650 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2651 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2652 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2654 inherited Map(aPixel, aData, aMapData);
2655 aData^ := aPixel.Data.a;
2659 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2661 inherited Unmap(aData, aPixel, aMapData);
2662 aPixel.Data.a := aData^;
2666 constructor TfdRGBA_UB4.Create;
2672 fglFormat := GL_RGBA;
2673 fglDataFormat := GL_UNSIGNED_BYTE;
2676 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2677 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2678 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2679 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2681 inherited Map(aPixel, aData, aMapData);
2682 aData^ := aPixel.Data.a;
2686 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2688 inherited Unmap(aData, aPixel, aMapData);
2689 aPixel.Data.a := aData^;
2693 constructor TfdBGRA_UB4.Create;
2699 fglFormat := GL_BGRA;
2700 fglDataFormat := GL_UNSIGNED_BYTE;
2703 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2704 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2705 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2706 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2708 PWord(aData)^ := aPixel.Data.a;
2712 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2717 aPixel.Data.a := PWord(aData)^;
2721 constructor TfdAlpha_US1.Create;
2726 fglFormat := GL_ALPHA;
2727 fglDataFormat := GL_UNSIGNED_SHORT;
2730 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2731 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2732 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2733 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2735 PWord(aData)^ := LuminanceWeight(aPixel);
2739 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2741 aPixel.Data.r := PWord(aData)^;
2742 aPixel.Data.g := PWord(aData)^;
2743 aPixel.Data.b := PWord(aData)^;
2748 constructor TfdLuminance_US1.Create;
2755 fglFormat := GL_LUMINANCE;
2756 fglDataFormat := GL_UNSIGNED_SHORT;
2759 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2760 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2761 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2762 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2768 if (fRange.arr[i] > 0) then
2769 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2773 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2778 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2782 constructor TfdUniversal_US1.Create;
2788 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2789 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2790 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2791 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2793 PWord(aData)^ := DepthWeight(aPixel);
2797 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2799 aPixel.Data.r := PWord(aData)^;
2800 aPixel.Data.g := PWord(aData)^;
2801 aPixel.Data.b := PWord(aData)^;
2806 constructor TfdDepth_US1.Create;
2813 fglFormat := GL_DEPTH_COMPONENT;
2814 fglDataFormat := GL_UNSIGNED_SHORT;
2817 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2818 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2819 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2820 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2822 inherited Map(aPixel, aData, aMapData);
2823 PWord(aData)^ := aPixel.Data.a;
2827 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2829 inherited Unmap(aData, aPixel, aMapData);
2830 aPixel.Data.a := PWord(aData)^;
2834 constructor TfdLuminanceAlpha_US2.Create;
2840 fglFormat := GL_LUMINANCE_ALPHA;
2841 fglDataFormat := GL_UNSIGNED_SHORT;
2844 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2845 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2846 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2847 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2849 PWord(aData)^ := aPixel.Data.r;
2851 PWord(aData)^ := aPixel.Data.g;
2853 PWord(aData)^ := aPixel.Data.b;
2857 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2859 aPixel.Data.r := PWord(aData)^;
2861 aPixel.Data.g := PWord(aData)^;
2863 aPixel.Data.b := PWord(aData)^;
2868 constructor TfdRGB_US3.Create;
2878 fglFormat := GL_RGB;
2879 fglDataFormat := GL_UNSIGNED_SHORT;
2882 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2883 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2884 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2885 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2887 PWord(aData)^ := aPixel.Data.b;
2889 PWord(aData)^ := aPixel.Data.g;
2891 PWord(aData)^ := aPixel.Data.r;
2895 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2897 aPixel.Data.b := PWord(aData)^;
2899 aPixel.Data.g := PWord(aData)^;
2901 aPixel.Data.r := PWord(aData)^;
2906 constructor TfdBGR_US3.Create;
2916 fglFormat := GL_BGR;
2917 fglDataFormat := GL_UNSIGNED_SHORT;
2920 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2921 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2922 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2923 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2925 inherited Map(aPixel, aData, aMapData);
2926 PWord(aData)^ := aPixel.Data.a;
2930 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2932 inherited Unmap(aData, aPixel, aMapData);
2933 aPixel.Data.a := PWord(aData)^;
2937 constructor TfdRGBA_US4.Create;
2943 fglFormat := GL_RGBA;
2944 fglDataFormat := GL_UNSIGNED_SHORT;
2947 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2948 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2949 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2950 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2952 inherited Map(aPixel, aData, aMapData);
2953 PWord(aData)^ := aPixel.Data.a;
2957 procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2959 inherited Unmap(aData, aPixel, aMapData);
2960 aPixel.Data.a := PWord(aData)^;
2964 constructor TfdBGRA_US4.Create;
2970 fglFormat := GL_BGRA;
2971 fglDataFormat := GL_UNSIGNED_SHORT;
2974 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2975 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2976 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2977 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2981 PCardinal(aData)^ := 0;
2983 if (fRange.arr[i] > 0) then
2984 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2988 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2993 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2997 constructor TfdUniversal_UI1.Create;
3003 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3004 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3005 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3006 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3008 PCardinal(aData)^ := DepthWeight(aPixel);
3012 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3014 aPixel.Data.r := PCardinal(aData)^;
3015 aPixel.Data.g := PCardinal(aData)^;
3016 aPixel.Data.b := PCardinal(aData)^;
3021 constructor TfdDepth_UI1.Create;
3025 fRange.r := $FFFFFFFF;
3026 fRange.g := $FFFFFFFF;
3027 fRange.b := $FFFFFFFF;
3028 fglFormat := GL_DEPTH_COMPONENT;
3029 fglDataFormat := GL_UNSIGNED_INT;
3032 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3033 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3034 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3035 constructor TfdAlpha4.Create;
3038 fFormat := tfAlpha4;
3039 fWithAlpha := tfAlpha4;
3040 fglInternalFormat := GL_ALPHA4;
3043 constructor TfdAlpha8.Create;
3046 fFormat := tfAlpha8;
3047 fWithAlpha := tfAlpha8;
3048 fglInternalFormat := GL_ALPHA8;
3051 constructor TfdAlpha12.Create;
3054 fFormat := tfAlpha12;
3055 fWithAlpha := tfAlpha12;
3056 fglInternalFormat := GL_ALPHA12;
3059 constructor TfdAlpha16.Create;
3062 fFormat := tfAlpha16;
3063 fWithAlpha := tfAlpha16;
3064 fglInternalFormat := GL_ALPHA16;
3067 constructor TfdLuminance4.Create;
3070 fFormat := tfLuminance4;
3071 fWithAlpha := tfLuminance4Alpha4;
3072 fWithoutAlpha := tfLuminance4;
3073 fglInternalFormat := GL_LUMINANCE4;
3076 constructor TfdLuminance8.Create;
3079 fFormat := tfLuminance8;
3080 fWithAlpha := tfLuminance8Alpha8;
3081 fWithoutAlpha := tfLuminance8;
3082 fglInternalFormat := GL_LUMINANCE8;
3085 constructor TfdLuminance12.Create;
3088 fFormat := tfLuminance12;
3089 fWithAlpha := tfLuminance12Alpha12;
3090 fWithoutAlpha := tfLuminance12;
3091 fglInternalFormat := GL_LUMINANCE12;
3094 constructor TfdLuminance16.Create;
3097 fFormat := tfLuminance16;
3098 fWithAlpha := tfLuminance16Alpha16;
3099 fWithoutAlpha := tfLuminance16;
3100 fglInternalFormat := GL_LUMINANCE16;
3103 constructor TfdLuminance4Alpha4.Create;
3106 fFormat := tfLuminance4Alpha4;
3107 fWithAlpha := tfLuminance4Alpha4;
3108 fWithoutAlpha := tfLuminance4;
3109 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3112 constructor TfdLuminance6Alpha2.Create;
3115 fFormat := tfLuminance6Alpha2;
3116 fWithAlpha := tfLuminance6Alpha2;
3117 fWithoutAlpha := tfLuminance8;
3118 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3121 constructor TfdLuminance8Alpha8.Create;
3124 fFormat := tfLuminance8Alpha8;
3125 fWithAlpha := tfLuminance8Alpha8;
3126 fWithoutAlpha := tfLuminance8;
3127 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3130 constructor TfdLuminance12Alpha4.Create;
3133 fFormat := tfLuminance12Alpha4;
3134 fWithAlpha := tfLuminance12Alpha4;
3135 fWithoutAlpha := tfLuminance12;
3136 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3139 constructor TfdLuminance12Alpha12.Create;
3142 fFormat := tfLuminance12Alpha12;
3143 fWithAlpha := tfLuminance12Alpha12;
3144 fWithoutAlpha := tfLuminance12;
3145 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3148 constructor TfdLuminance16Alpha16.Create;
3151 fFormat := tfLuminance16Alpha16;
3152 fWithAlpha := tfLuminance16Alpha16;
3153 fWithoutAlpha := tfLuminance16;
3154 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3157 constructor TfdR3G3B2.Create;
3160 fFormat := tfR3G3B2;
3161 fWithAlpha := tfRGBA2;
3162 fWithoutAlpha := tfR3G3B2;
3169 fglFormat := GL_RGB;
3170 fglInternalFormat := GL_R3_G3_B2;
3171 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3174 constructor TfdRGB4.Create;
3178 fWithAlpha := tfRGBA4;
3179 fWithoutAlpha := tfRGB4;
3180 fRGBInverted := tfBGR4;
3187 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3188 fglInternalFormat := GL_RGB4;
3189 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3192 constructor TfdR5G6B5.Create;
3195 fFormat := tfR5G6B5;
3196 fWithAlpha := tfRGBA4;
3197 fWithoutAlpha := tfR5G6B5;
3198 fRGBInverted := tfB5G6R5;
3205 fglFormat := GL_RGB;
3206 fglInternalFormat := GL_RGB565;
3207 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3210 constructor TfdRGB5.Create;
3214 fWithAlpha := tfRGB5A1;
3215 fWithoutAlpha := tfRGB5;
3216 fRGBInverted := tfBGR5;
3223 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3224 fglInternalFormat := GL_RGB5;
3225 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3228 constructor TfdRGB8.Create;
3232 fWithAlpha := tfRGBA8;
3233 fWithoutAlpha := tfRGB8;
3234 fRGBInverted := tfBGR8;
3235 fglInternalFormat := GL_RGB8;
3238 constructor TfdRGB10.Create;
3242 fWithAlpha := tfRGB10A2;
3243 fWithoutAlpha := tfRGB10;
3244 fRGBInverted := tfBGR10;
3251 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3252 fglInternalFormat := GL_RGB10;
3253 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3256 constructor TfdRGB12.Create;
3260 fWithAlpha := tfRGBA12;
3261 fWithoutAlpha := tfRGB12;
3262 fRGBInverted := tfBGR12;
3263 fglInternalFormat := GL_RGB12;
3266 constructor TfdRGB16.Create;
3270 fWithAlpha := tfRGBA16;
3271 fWithoutAlpha := tfRGB16;
3272 fRGBInverted := tfBGR16;
3273 fglInternalFormat := GL_RGB16;
3276 constructor TfdRGBA2.Create;
3280 fWithAlpha := tfRGBA2;
3281 fWithoutAlpha := tfR3G3B2;
3282 fRGBInverted := tfBGRA2;
3283 fglInternalFormat := GL_RGBA2;
3286 constructor TfdRGBA4.Create;
3290 fWithAlpha := tfRGBA4;
3291 fWithoutAlpha := tfRGB4;
3292 fRGBInverted := tfBGRA4;
3301 fglFormat := GL_RGBA;
3302 fglInternalFormat := GL_RGBA4;
3303 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3306 constructor TfdRGB5A1.Create;
3309 fFormat := tfRGB5A1;
3310 fWithAlpha := tfRGB5A1;
3311 fWithoutAlpha := tfRGB5;
3312 fRGBInverted := tfBGR5A1;
3321 fglFormat := GL_RGBA;
3322 fglInternalFormat := GL_RGB5_A1;
3323 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3326 constructor TfdRGBA8.Create;
3330 fWithAlpha := tfRGBA8;
3331 fWithoutAlpha := tfRGB8;
3332 fRGBInverted := tfBGRA8;
3333 fglInternalFormat := GL_RGBA8;
3336 constructor TfdRGB10A2.Create;
3339 fFormat := tfRGB10A2;
3340 fWithAlpha := tfRGB10A2;
3341 fWithoutAlpha := tfRGB10;
3342 fRGBInverted := tfBGR10A2;
3351 fglFormat := GL_RGBA;
3352 fglInternalFormat := GL_RGB10_A2;
3353 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3356 constructor TfdRGBA12.Create;
3359 fFormat := tfRGBA12;
3360 fWithAlpha := tfRGBA12;
3361 fWithoutAlpha := tfRGB12;
3362 fRGBInverted := tfBGRA12;
3363 fglInternalFormat := GL_RGBA12;
3366 constructor TfdRGBA16.Create;
3369 fFormat := tfRGBA16;
3370 fWithAlpha := tfRGBA16;
3371 fWithoutAlpha := tfRGB16;
3372 fRGBInverted := tfBGRA16;
3373 fglInternalFormat := GL_RGBA16;
3376 constructor TfdBGR4.Create;
3381 fWithAlpha := tfBGRA4;
3382 fWithoutAlpha := tfBGR4;
3383 fRGBInverted := tfRGB4;
3392 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3393 fglInternalFormat := GL_RGB4;
3394 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3397 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3398 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3399 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3400 constructor TfdB5G6R5.Create;
3403 fFormat := tfB5G6R5;
3404 fWithAlpha := tfBGRA4;
3405 fWithoutAlpha := tfB5G6R5;
3406 fRGBInverted := tfR5G6B5;
3413 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3414 fglInternalFormat := GL_RGB8;
3415 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3418 constructor TfdBGR5.Create;
3423 fWithAlpha := tfBGR5A1;
3424 fWithoutAlpha := tfBGR5;
3425 fRGBInverted := tfRGB5;
3434 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3435 fglInternalFormat := GL_RGB5;
3436 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3439 constructor TfdBGR8.Create;
3443 fWithAlpha := tfBGRA8;
3444 fWithoutAlpha := tfBGR8;
3445 fRGBInverted := tfRGB8;
3446 fglInternalFormat := GL_RGB8;
3449 constructor TfdBGR10.Create;
3453 fWithAlpha := tfBGR10A2;
3454 fWithoutAlpha := tfBGR10;
3455 fRGBInverted := tfRGB10;
3464 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3465 fglInternalFormat := GL_RGB10;
3466 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3469 constructor TfdBGR12.Create;
3473 fWithAlpha := tfBGRA12;
3474 fWithoutAlpha := tfBGR12;
3475 fRGBInverted := tfRGB12;
3476 fglInternalFormat := GL_RGB12;
3479 constructor TfdBGR16.Create;
3483 fWithAlpha := tfBGRA16;
3484 fWithoutAlpha := tfBGR16;
3485 fRGBInverted := tfRGB16;
3486 fglInternalFormat := GL_RGB16;
3489 constructor TfdBGRA2.Create;
3493 fWithAlpha := tfBGRA4;
3494 fWithoutAlpha := tfBGR4;
3495 fRGBInverted := tfRGBA2;
3496 fglInternalFormat := GL_RGBA2;
3499 constructor TfdBGRA4.Create;
3503 fWithAlpha := tfBGRA4;
3504 fWithoutAlpha := tfBGR4;
3505 fRGBInverted := tfRGBA4;
3514 fglFormat := GL_BGRA;
3515 fglInternalFormat := GL_RGBA4;
3516 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3519 constructor TfdBGR5A1.Create;
3522 fFormat := tfBGR5A1;
3523 fWithAlpha := tfBGR5A1;
3524 fWithoutAlpha := tfBGR5;
3525 fRGBInverted := tfRGB5A1;
3534 fglFormat := GL_BGRA;
3535 fglInternalFormat := GL_RGB5_A1;
3536 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3539 constructor TfdBGRA8.Create;
3543 fWithAlpha := tfBGRA8;
3544 fWithoutAlpha := tfBGR8;
3545 fRGBInverted := tfRGBA8;
3546 fglInternalFormat := GL_RGBA8;
3549 constructor TfdBGR10A2.Create;
3552 fFormat := tfBGR10A2;
3553 fWithAlpha := tfBGR10A2;
3554 fWithoutAlpha := tfBGR10;
3555 fRGBInverted := tfRGB10A2;
3564 fglFormat := GL_BGRA;
3565 fglInternalFormat := GL_RGB10_A2;
3566 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3569 constructor TfdBGRA12.Create;
3572 fFormat := tfBGRA12;
3573 fWithAlpha := tfBGRA12;
3574 fWithoutAlpha := tfBGR12;
3575 fRGBInverted := tfRGBA12;
3576 fglInternalFormat := GL_RGBA12;
3579 constructor TfdBGRA16.Create;
3582 fFormat := tfBGRA16;
3583 fWithAlpha := tfBGRA16;
3584 fWithoutAlpha := tfBGR16;
3585 fRGBInverted := tfRGBA16;
3586 fglInternalFormat := GL_RGBA16;
3589 constructor TfdDepth16.Create;
3592 fFormat := tfDepth16;
3593 fWithAlpha := tfEmpty;
3594 fWithoutAlpha := tfDepth16;
3595 fglInternalFormat := GL_DEPTH_COMPONENT16;
3598 constructor TfdDepth24.Create;
3601 fFormat := tfDepth24;
3602 fWithAlpha := tfEmpty;
3603 fWithoutAlpha := tfDepth24;
3604 fglInternalFormat := GL_DEPTH_COMPONENT24;
3607 constructor TfdDepth32.Create;
3610 fFormat := tfDepth32;
3611 fWithAlpha := tfEmpty;
3612 fWithoutAlpha := tfDepth32;
3613 fglInternalFormat := GL_DEPTH_COMPONENT32;
3616 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3617 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3618 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3619 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3621 raise EglBitmap.Create('mapping for compressed formats is not supported');
3624 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3626 raise EglBitmap.Create('mapping for compressed formats is not supported');
3629 constructor TfdS3tcDtx1RGBA.Create;
3632 fFormat := tfS3tcDtx1RGBA;
3633 fWithAlpha := tfS3tcDtx1RGBA;
3634 fUncompressed := tfRGB5A1;
3636 fIsCompressed := true;
3637 fglFormat := GL_COMPRESSED_RGBA;
3638 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3639 fglDataFormat := GL_UNSIGNED_BYTE;
3642 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3643 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3644 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3645 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3647 raise EglBitmap.Create('mapping for compressed formats is not supported');
3650 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3652 raise EglBitmap.Create('mapping for compressed formats is not supported');
3655 constructor TfdS3tcDtx3RGBA.Create;
3658 fFormat := tfS3tcDtx3RGBA;
3659 fWithAlpha := tfS3tcDtx3RGBA;
3660 fUncompressed := tfRGBA8;
3662 fIsCompressed := true;
3663 fglFormat := GL_COMPRESSED_RGBA;
3664 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3665 fglDataFormat := GL_UNSIGNED_BYTE;
3668 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3669 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3670 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3671 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3673 raise EglBitmap.Create('mapping for compressed formats is not supported');
3676 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3678 raise EglBitmap.Create('mapping for compressed formats is not supported');
3681 constructor TfdS3tcDtx5RGBA.Create;
3684 fFormat := tfS3tcDtx3RGBA;
3685 fWithAlpha := tfS3tcDtx3RGBA;
3686 fUncompressed := tfRGBA8;
3688 fIsCompressed := true;
3689 fglFormat := GL_COMPRESSED_RGBA;
3690 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3691 fglDataFormat := GL_UNSIGNED_BYTE;
3694 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3695 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3696 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3697 class procedure TFormatDescriptor.Init;
3699 if not Assigned(FormatDescriptorCS) then
3700 FormatDescriptorCS := TCriticalSection.Create;
3703 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3704 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3706 FormatDescriptorCS.Enter;
3708 result := FormatDescriptors[aFormat];
3709 if not Assigned(result) then begin
3710 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3711 FormatDescriptors[aFormat] := result;
3714 FormatDescriptorCS.Leave;
3718 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3719 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3721 result := Get(Get(aFormat).WithAlpha);
3724 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3725 class procedure TFormatDescriptor.Clear;
3729 FormatDescriptorCS.Enter;
3731 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3732 FreeAndNil(FormatDescriptors[f]);
3734 FormatDescriptorCS.Leave;
3738 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3739 class procedure TFormatDescriptor.Finalize;
3742 FreeAndNil(FormatDescriptorCS);
3745 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3746 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3747 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3748 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3750 Update(aValue, fRange.r, fShift.r);
3753 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3754 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3756 Update(aValue, fRange.g, fShift.g);
3759 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3760 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3762 Update(aValue, fRange.b, fShift.b);
3765 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3766 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3768 Update(aValue, fRange.a, fShift.a);
3771 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3772 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3779 while (aMask > 0) and ((aMask and 1) = 0) do begin
3781 aMask := aMask shr 1;
3784 while (aMask > 0) do begin
3785 aRange := aRange shl 1;
3786 aMask := aMask shr 1;
3790 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3793 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3794 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3800 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3801 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3802 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3803 ((aPixel.Data.a and fRange.a) shl fShift.a);
3804 s := Round(fPixelSize);
3807 2: PWord(aData)^ := data;
3808 4: PCardinal(aData)^ := data;
3809 8: PQWord(aData)^ := data;
3811 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3816 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3817 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3822 s := Round(fPixelSize);
3825 2: data := PWord(aData)^;
3826 4: data := PCardinal(aData)^;
3827 8: data := PQWord(aData)^;
3829 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3832 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3836 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3837 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3838 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3839 procedure TbmpColorTableFormat.CreateColorTable;
3843 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3844 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3846 if (Format = tfLuminance4) then
3847 SetLength(fColorTable, 16)
3849 SetLength(fColorTable, 256);
3853 for i := 0 to High(fColorTable) do begin
3854 fColorTable[i].r := 16 * i;
3855 fColorTable[i].g := 16 * i;
3856 fColorTable[i].b := 16 * i;
3857 fColorTable[i].a := 0;
3862 for i := 0 to High(fColorTable) do begin
3863 fColorTable[i].r := i;
3864 fColorTable[i].g := i;
3865 fColorTable[i].b := i;
3866 fColorTable[i].a := 0;
3871 for i := 0 to High(fColorTable) do begin
3872 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3873 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3874 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3875 fColorTable[i].a := 0;
3881 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3882 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3886 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3887 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3891 if (aMapData = nil) then
3893 d := LuminanceWeight(aPixel) and Range.r;
3894 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3895 inc(PByte(aMapData), 4);
3896 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3903 aData^ := LuminanceWeight(aPixel) and Range.r;
3909 ((aPixel.Data.r and Range.r) shl Shift.r) or
3910 ((aPixel.Data.g and Range.g) shl Shift.g) or
3911 ((aPixel.Data.b and Range.b) shl Shift.b));
3917 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3918 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3925 s := Trunc(fPixelSize);
3926 f := fPixelSize - s;
3927 bits := Round(8 * f);
3929 0: idx := (aData^ shr (8 - bits - {%H-}PtrInt(aMapData))) and ((1 shl bits) - 1);
3931 2: idx := PWord(aData)^;
3932 4: idx := PCardinal(aData)^;
3933 8: idx := PQWord(aData)^;
3935 raise EglBitmap.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3937 if (idx >= Length(fColorTable)) then
3938 raise EglBitmap.CreateFmt('invalid color index: %d', [idx]);
3939 with fColorTable[idx] do begin
3945 inc(PByte(aMapData), bits);
3946 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3948 dec(PByte(aMapData), 8);
3953 destructor TbmpColorTableFormat.Destroy;
3955 SetLength(fColorTable, 0);
3959 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3960 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3961 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3962 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
3966 for i := 0 to 3 do begin
3967 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
3968 if (aSourceFD.Range.arr[i] > 0) then
3969 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
3971 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
3976 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3977 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
3979 with aFuncRec do begin
3980 if (Source.Range.r > 0) then
3981 Dest.Data.r := Source.Data.r;
3982 if (Source.Range.g > 0) then
3983 Dest.Data.g := Source.Data.g;
3984 if (Source.Range.b > 0) then
3985 Dest.Data.b := Source.Data.b;
3986 if (Source.Range.a > 0) then
3987 Dest.Data.a := Source.Data.a;
3991 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3992 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3996 with aFuncRec do begin
3998 if (Source.Range.arr[i] > 0) then
3999 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4004 TShiftData = packed record
4006 0: (r, g, b, a: SmallInt);
4007 1: (arr: array[0..3] of SmallInt);
4009 PShiftData = ^TShiftData;
4011 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4012 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4018 if (Source.Range.arr[i] > 0) then
4019 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4022 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4023 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4025 with aFuncRec do begin
4026 Dest.Data := Source.Data;
4027 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4028 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4029 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4030 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4032 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4033 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4038 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4039 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4043 with aFuncRec do begin
4045 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4049 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4050 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4054 with FuncRec do begin
4055 if (FuncRec.Args = nil) then begin //source has no alpha
4057 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4058 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4059 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4060 Dest.Data.a := Round(Dest.Range.a * Temp);
4062 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4066 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4067 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4069 PglBitmapPixelData = ^TglBitmapPixelData;
4071 with FuncRec do begin
4072 Dest.Data.r := Source.Data.r;
4073 Dest.Data.g := Source.Data.g;
4074 Dest.Data.b := Source.Data.b;
4076 with PglBitmapPixelData(Args)^ do
4077 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4078 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4079 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4082 Dest.Data.a := Dest.Range.a;
4086 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4087 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4089 with FuncRec do begin
4090 Dest.Data.r := Source.Data.r;
4091 Dest.Data.g := Source.Data.g;
4092 Dest.Data.b := Source.Data.b;
4093 Dest.Data.a := PCardinal(Args)^;
4097 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4098 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4101 TRGBPix = array [0..2] of byte;
4105 while aWidth > 0 do begin
4106 Temp := PRGBPix(aData)^[0];
4107 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4108 PRGBPix(aData)^[2] := Temp;
4118 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4119 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4120 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4121 function TglBitmap.GetFormatDesc: TglBitmapFormatDescriptor;
4123 result := TFormatDescriptor.Get(Format);
4126 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4127 function TglBitmap.GetWidth: Integer;
4129 if (ffX in fDimension.Fields) then
4130 result := fDimension.X
4135 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4136 function TglBitmap.GetHeight: Integer;
4138 if (ffY in fDimension.Fields) then
4139 result := fDimension.Y
4144 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4145 function TglBitmap.GetFileWidth: Integer;
4147 result := Max(1, Width);
4150 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4151 function TglBitmap.GetFileHeight: Integer;
4153 result := Max(1, Height);
4156 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4157 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4159 if fCustomData = aValue then
4161 fCustomData := aValue;
4164 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4165 procedure TglBitmap.SetCustomName(const aValue: String);
4167 if fCustomName = aValue then
4169 fCustomName := aValue;
4172 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4173 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4175 if fCustomNameW = aValue then
4177 fCustomNameW := aValue;
4180 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4181 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4183 if fDeleteTextureOnFree = aValue then
4185 fDeleteTextureOnFree := aValue;
4188 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4189 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4191 if fFormat = aValue then
4193 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4194 raise EglBitmapUnsupportedFormat.Create(Format);
4195 SetDataPointer(fData, aValue, Width, Height); //be careful, Data could be freed by this method
4198 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4199 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4201 if fFreeDataAfterGenTexture = aValue then
4203 fFreeDataAfterGenTexture := aValue;
4206 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4207 procedure TglBitmap.SetID(const aValue: Cardinal);
4209 if fID = aValue then
4214 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4215 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4217 if fMipMap = aValue then
4222 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4223 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4225 if fTarget = aValue then
4230 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4231 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4233 MaxAnisotropic: Integer;
4235 fAnisotropic := aValue;
4236 if (ID > 0) then begin
4237 if GL_EXT_texture_filter_anisotropic then begin
4238 if fAnisotropic > 0 then begin
4240 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4241 if aValue > MaxAnisotropic then
4242 fAnisotropic := MaxAnisotropic;
4243 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4251 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4252 procedure TglBitmap.CreateID;
4255 glDeleteTextures(1, @fID);
4256 glGenTextures(1, @fID);
4260 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4261 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4263 // Set Up Parameters
4264 SetWrap(fWrapS, fWrapT, fWrapR);
4265 SetFilter(fFilterMin, fFilterMag);
4266 SetAnisotropic(fAnisotropic);
4267 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4269 if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
4270 SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4272 // Mip Maps Generation Mode
4273 aBuildWithGlu := false;
4274 if (MipMap = mmMipmap) then begin
4275 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4276 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4278 aBuildWithGlu := true;
4279 end else if (MipMap = mmMipmapGlu) then
4280 aBuildWithGlu := true;
4283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4284 procedure TglBitmap.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
4285 const aWidth: Integer; const aHeight: Integer);
4289 if (Data <> aData) then begin
4290 if (Assigned(Data)) then
4295 FillChar(fDimension, SizeOf(fDimension), 0);
4296 if not Assigned(fData) then begin
4301 if aWidth <> -1 then begin
4302 fDimension.Fields := fDimension.Fields + [ffX];
4303 fDimension.X := aWidth;
4306 if aHeight <> -1 then begin
4307 fDimension.Fields := fDimension.Fields + [ffY];
4308 fDimension.Y := aHeight;
4311 s := TFormatDescriptor.Get(aFormat).PixelSize;
4313 fPixelSize := Ceil(s);
4314 fRowSize := Ceil(s * aWidth);
4318 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4319 function TglBitmap.FlipHorz: Boolean;
4324 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4325 function TglBitmap.FlipVert: Boolean;
4330 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4331 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4332 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4333 procedure TglBitmap.AfterConstruction;
4335 inherited AfterConstruction;
4339 fIsResident := false;
4341 fFormat := glBitmapGetDefaultFormat;
4342 fMipMap := glBitmapDefaultMipmap;
4343 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4344 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4346 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4347 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4348 glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4351 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4352 procedure TglBitmap.BeforeDestruction;
4357 SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
4358 if (fID > 0) and fDeleteTextureOnFree then
4359 glDeleteTextures(1, @fID);
4360 inherited BeforeDestruction;
4363 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4364 procedure TglBitmap.PrepareResType(var aResource: String; var aResType: PChar);
4368 if not Assigned(aResType) then begin
4369 TempPos := Pos('.', aResource);
4370 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4371 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4375 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4376 procedure TglBitmap.LoadFromFile(const aFilename: String);
4380 if not FileExists(aFilename) then
4381 raise EglBitmap.Create('file does not exist: ' + aFilename);
4382 fFilename := aFilename;
4383 fs := TFileStream.Create(fFilename, fmOpenRead);
4392 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4393 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4395 {$IFDEF GLB_SUPPORT_PNG_READ}
4396 if not LoadPNG(aStream) then
4398 {$IFDEF GLB_SUPPORT_JPEG_READ}
4399 if not LoadJPEG(aStream) then
4401 if not LoadDDS(aStream) then
4402 if not LoadTGA(aStream) then
4403 if not LoadBMP(aStream) then
4404 raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4407 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4408 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4409 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4414 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4415 GetMem(tmpData, size);
4417 FillChar(tmpData^, size, #$FF);
4418 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
4420 if Assigned(tmpData) then
4424 AddFunc(Self, aFunc, false, Format, aArgs);
4427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4428 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
4430 rs: TResourceStream;
4432 PrepareResType(aResource, aResType);
4433 rs := TResourceStream.Create(aInstance, aResource, aResType);
4441 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4442 procedure TglBitmap.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4444 rs: TResourceStream;
4446 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
4454 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4455 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4459 fs := TFileStream.Create(aFileName, fmCreate);
4462 SaveToStream(fs, aFileType);
4468 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4469 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4472 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4473 ftPNG: SavePNG(aStream);
4475 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4476 ftJPEG: SaveJPEG(aStream);
4478 ftDDS: SaveDDS(aStream);
4479 ftTGA: SaveTGA(aStream);
4480 ftBMP: SaveBMP(aStream);
4484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4485 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4487 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4490 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4491 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4492 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4494 DestData, TmpData, SourceData: pByte;
4495 TempHeight, TempWidth: Integer;
4496 SourceFD, DestFD: TFormatDescriptor;
4497 SourceMD, DestMD: Pointer;
4499 FuncRec: TglBitmapFunctionRec;
4501 Assert(Assigned(Data));
4502 Assert(Assigned(aSource));
4503 Assert(Assigned(aSource.Data));
4506 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4507 SourceFD := TFormatDescriptor.Get(aSource.Format);
4508 DestFD := TFormatDescriptor.Get(aFormat);
4510 if (SourceFD.IsCompressed) then
4511 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
4512 if (DestFD.IsCompressed) then
4513 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
4515 // inkompatible Formats so CreateTemp
4516 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4517 aCreateTemp := true;
4520 TempHeight := Max(1, aSource.Height);
4521 TempWidth := Max(1, aSource.Width);
4523 FuncRec.Sender := Self;
4524 FuncRec.Args := aArgs;
4527 if aCreateTemp then begin
4528 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
4529 DestData := TmpData;
4534 SourceFD.PreparePixel(FuncRec.Source);
4535 DestFD.PreparePixel (FuncRec.Dest);
4537 SourceMD := SourceFD.CreateMappingData;
4538 DestMD := DestFD.CreateMappingData;
4540 FuncRec.Size := aSource.Dimension;
4541 FuncRec.Position.Fields := FuncRec.Size.Fields;
4544 SourceData := aSource.Data;
4545 FuncRec.Position.Y := 0;
4546 while FuncRec.Position.Y < TempHeight do begin
4547 FuncRec.Position.X := 0;
4548 while FuncRec.Position.X < TempWidth do begin
4549 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4551 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4552 inc(FuncRec.Position.X);
4554 inc(FuncRec.Position.Y);
4557 // Updating Image or InternalFormat
4559 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) //be careful, Data could be freed by this method
4560 else if (aFormat <> fFormat) then
4565 SourceFD.FreeMappingData(SourceMD);
4566 DestFD.FreeMappingData(DestMD);
4569 if aCreateTemp and Assigned(TmpData) then
4577 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4578 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4580 Row, RowSize: Integer;
4581 SourceData, TmpData: PByte;
4583 FormatDesc: TFormatDescriptor;
4585 function GetRowPointer(Row: Integer): pByte;
4587 result := aSurface.pixels;
4588 Inc(result, Row * RowSize);
4594 FormatDesc := TFormatDescriptor.Get(Format);
4595 if FormatDesc.IsCompressed then
4596 raise EglBitmapUnsupportedFormat.Create(Format);
4598 if Assigned(Data) then begin
4599 case Trunc(FormatDesc.PixelSize) of
4605 raise EglBitmapUnsupportedFormat.Create(Format);
4608 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4609 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4611 RowSize := FormatDesc.GetSize(FileWidth, 1);
4613 for Row := 0 to FileHeight-1 do begin
4614 TmpData := GetRowPointer(Row);
4615 if Assigned(TmpData) then begin
4616 Move(SourceData^, TmpData^, RowSize);
4617 inc(SourceData, RowSize);
4624 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4625 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4627 pSource, pData, pTempData: PByte;
4628 Row, RowSize, TempWidth, TempHeight: Integer;
4629 IntFormat: TglBitmapFormat;
4630 FormatDesc: TFormatDescriptor;
4632 function GetRowPointer(Row: Integer): pByte;
4634 result := aSurface^.pixels;
4635 Inc(result, Row * RowSize);
4640 if (Assigned(aSurface)) then begin
4641 with aSurface^.format^ do begin
4642 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4643 FormatDesc := TFormatDescriptor.Get(IntFormat);
4644 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4647 if (IntFormat = tfEmpty) then
4648 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4651 TempWidth := aSurface^.w;
4652 TempHeight := aSurface^.h;
4653 RowSize := FormatDesc.GetSize(TempWidth, 1);
4654 GetMem(pData, TempHeight * RowSize);
4657 for Row := 0 to TempHeight -1 do begin
4658 pSource := GetRowPointer(Row);
4659 if (Assigned(pSource)) then begin
4660 Move(pSource^, pTempData^, RowSize);
4661 Inc(pTempData, RowSize);
4664 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4667 if Assigned(pData) then
4674 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4675 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4677 Row, Col, AlphaInterleave: Integer;
4678 pSource, pDest: PByte;
4680 function GetRowPointer(Row: Integer): pByte;
4682 result := aSurface.pixels;
4683 Inc(result, Row * Width);
4688 if Assigned(Data) then begin
4689 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4690 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4692 AlphaInterleave := 0;
4695 AlphaInterleave := 1;
4697 AlphaInterleave := 3;
4701 for Row := 0 to Height -1 do begin
4702 pDest := GetRowPointer(Row);
4703 if Assigned(pDest) then begin
4704 for Col := 0 to Width -1 do begin
4705 Inc(pSource, AlphaInterleave);
4717 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4718 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4722 bmp := TglBitmap2D.Create;
4724 bmp.AssignFromSurface(aSurface);
4725 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4733 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4734 function CreateGrayPalette: HPALETTE;
4739 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
4741 Pal.palVersion := $300;
4742 Pal.palNumEntries := 256;
4744 for Idx := 0 to Pal.palNumEntries - 1 do begin
4745 Pal.palPalEntry[Idx].peRed := Idx;
4746 Pal.palPalEntry[Idx].peGreen := Idx;
4747 Pal.palPalEntry[Idx].peBlue := Idx;
4748 Pal.palPalEntry[Idx].peFlags := 0;
4750 Result := CreatePalette(Pal^);
4754 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4755 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4758 pSource, pData: PByte;
4761 if Assigned(Data) then begin
4762 if Assigned(aBitmap) then begin
4763 aBitmap.Width := Width;
4764 aBitmap.Height := Height;
4767 tfAlpha8, tfLuminance8: begin
4768 aBitmap.PixelFormat := pf8bit;
4769 aBitmap.Palette := CreateGrayPalette;
4772 aBitmap.PixelFormat := pf15bit;
4774 aBitmap.PixelFormat := pf16bit;
4776 aBitmap.PixelFormat := pf24bit;
4778 aBitmap.PixelFormat := pf32bit;
4780 raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
4784 for Row := 0 to FileHeight -1 do begin
4785 pData := aBitmap.Scanline[Row];
4786 Move(pSource^, pData^, fRowSize);
4787 Inc(pSource, fRowSize);
4788 if (Format in [tfRGB8, tfRGBA8]) then // swap RGB(A) to BGR(A)
4789 SwapRGB(pData, FileWidth, Format = tfRGBA8);
4796 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4797 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4799 pSource, pData, pTempData: PByte;
4800 Row, RowSize, TempWidth, TempHeight: Integer;
4801 IntFormat: TglBitmapFormat;
4805 if (Assigned(aBitmap)) then begin
4806 case aBitmap.PixelFormat of
4808 IntFormat := tfLuminance8;
4810 IntFormat := tfRGB5A1;
4812 IntFormat := tfR5G6B5;
4814 IntFormat := tfBGR8;
4816 IntFormat := tfBGRA8;
4818 raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
4821 TempWidth := aBitmap.Width;
4822 TempHeight := aBitmap.Height;
4823 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
4824 GetMem(pData, TempHeight * RowSize);
4827 for Row := 0 to TempHeight -1 do begin
4828 pSource := aBitmap.Scanline[Row];
4829 if (Assigned(pSource)) then begin
4830 Move(pSource^, pTempData^, RowSize);
4831 Inc(pTempData, RowSize);
4834 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4837 if Assigned(pData) then
4844 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4845 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4847 Row, Col, AlphaInterleave: Integer;
4848 pSource, pDest: PByte;
4852 if Assigned(Data) then begin
4853 if (Format in [tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8]) then begin
4854 if Assigned(aBitmap) then begin
4855 aBitmap.PixelFormat := pf8bit;
4856 aBitmap.Palette := CreateGrayPalette;
4857 aBitmap.Width := Width;
4858 aBitmap.Height := Height;
4862 AlphaInterleave := 1;
4864 AlphaInterleave := 3;
4866 AlphaInterleave := 0;
4872 for Row := 0 to Height -1 do begin
4873 pDest := aBitmap.Scanline[Row];
4874 if Assigned(pDest) then begin
4875 for Col := 0 to Width -1 do begin
4876 Inc(pSource, AlphaInterleave);
4889 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4890 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4894 tex := TglBitmap2D.Create;
4896 tex.AssignFromBitmap(ABitmap);
4897 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4904 {$IFDEF GLB_LAZARUS}
4905 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4906 function TglBitmap.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4908 rid: TRawImageDescription;
4909 FormatDesc: TFormatDescriptor;
4912 if not Assigned(aImage) or (Format = tfEmpty) then
4914 FormatDesc := TFormatDescriptor.Get(Format);
4915 if FormatDesc.IsCompressed then
4918 FillChar(rid{%H-}, SizeOf(rid), 0);
4920 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
4921 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
4922 tfLuminance4Alpha4, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16]) then
4923 rid.Format := ricfGray
4925 rid.Format := ricfRGBA;
4928 rid.Height := Height;
4929 rid.Depth := CountSetBits(FormatDesc.Range.r or FormatDesc.Range.g or FormatDesc.Range.b or FormatDesc.Range.a);
4930 rid.BitOrder := riboBitsInOrder;
4931 rid.ByteOrder := riboLSBFirst;
4932 rid.LineOrder := riloTopToBottom;
4933 rid.LineEnd := rileTight;
4934 rid.BitsPerPixel := Round(8 * FormatDesc.PixelSize);
4935 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
4936 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
4937 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
4938 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
4939 rid.RedShift := FormatDesc.Shift.r;
4940 rid.GreenShift := FormatDesc.Shift.g;
4941 rid.BlueShift := FormatDesc.Shift.b;
4942 rid.AlphaShift := FormatDesc.Shift.a;
4944 rid.MaskBitsPerPixel := 0;
4945 rid.PaletteColorCount := 0;
4947 aImage.DataDescription := rid;
4950 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
4955 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4956 function TglBitmap.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
4959 FormatDesc: TFormatDescriptor;
4964 if not Assigned(aImage) then
4966 for f := High(f) downto Low(f) do begin
4967 FormatDesc := TFormatDescriptor.Get(f);
4968 with aImage.DataDescription do
4969 if FormatDesc.MaskMatch(
4970 (QWord(1 shl RedPrec )-1) shl RedShift,
4971 (QWord(1 shl GreenPrec)-1) shl GreenShift,
4972 (QWord(1 shl BluePrec )-1) shl BlueShift,
4973 (QWord(1 shl AlphaPrec)-1) shl AlphaShift) then
4977 if (f = tfEmpty) then
4980 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
4981 ImageData := GetMem(ImageSize);
4983 Move(aImage.PixelData^, ImageData^, (aImage.Width * aImage.Height * aImage.DataDescription.BitsPerPixel) shr 3);
4984 SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method
4986 if Assigned(ImageData) then
4994 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4995 function TglBitmap.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4997 rid: TRawImageDescription;
4998 FormatDesc: TFormatDescriptor;
4999 Pixel: TglBitmapPixelData;
5005 if not Assigned(aImage) or (Format = tfEmpty) then
5007 FormatDesc := TFormatDescriptor.Get(Format);
5008 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5011 FillChar(rid{%H-}, SizeOf(rid), 0);
5012 rid.Format := ricfGray;
5014 rid.Height := Height;
5015 rid.Depth := CountSetBits(FormatDesc.Range.a);
5016 rid.BitOrder := riboBitsInOrder;
5017 rid.ByteOrder := riboLSBFirst;
5018 rid.LineOrder := riloTopToBottom;
5019 rid.LineEnd := rileTight;
5020 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
5021 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
5026 rid.GreenShift := 0;
5028 rid.AlphaShift := 0;
5030 rid.MaskBitsPerPixel := 0;
5031 rid.PaletteColorCount := 0;
5033 aImage.DataDescription := rid;
5036 srcMD := FormatDesc.CreateMappingData;
5038 FormatDesc.PreparePixel(Pixel);
5040 dst := aImage.PixelData;
5041 for y := 0 to Height-1 do
5042 for x := 0 to Width-1 do begin
5043 FormatDesc.Unmap(src, Pixel, srcMD);
5044 case rid.BitsPerPixel of
5046 dst^ := Pixel.Data.a;
5050 PWord(dst)^ := Pixel.Data.a;
5054 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
5055 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
5056 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
5060 PCardinal(dst)^ := Pixel.Data.a;
5064 raise EglBitmapUnsupportedFormat.Create(Format);
5068 FormatDesc.FreeMappingData(srcMD);
5073 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5074 function TglBitmap.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5078 tex := TglBitmap2D.Create;
5080 tex.AssignFromLazIntfImage(aImage);
5081 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5089 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
5090 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5092 rs: TResourceStream;
5094 PrepareResType(aResource, aResType);
5095 rs := TResourceStream.Create(aInstance, aResource, aResType);
5097 result := AddAlphaFromStream(rs, aFunc, aArgs);
5103 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5104 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
5105 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5107 rs: TResourceStream;
5109 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
5111 result := AddAlphaFromStream(rs, aFunc, aArgs);
5117 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5118 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5120 if TFormatDescriptor.Get(Format).IsCompressed then
5121 raise EglBitmapUnsupportedFormat.Create(Format);
5122 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
5125 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5126 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5130 FS := TFileStream.Create(aFileName, fmOpenRead);
5132 result := AddAlphaFromStream(FS, aFunc, aArgs);
5138 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5139 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5143 tex := TglBitmap2D.Create(aStream);
5145 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5151 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5152 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5154 DestData, DestData2, SourceData: pByte;
5155 TempHeight, TempWidth: Integer;
5156 SourceFD, DestFD: TFormatDescriptor;
5157 SourceMD, DestMD, DestMD2: Pointer;
5159 FuncRec: TglBitmapFunctionRec;
5163 Assert(Assigned(Data));
5164 Assert(Assigned(aBitmap));
5165 Assert(Assigned(aBitmap.Data));
5167 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
5168 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
5170 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
5171 DestFD := TFormatDescriptor.Get(Format);
5173 if not Assigned(aFunc) then begin
5174 aFunc := glBitmapAlphaFunc;
5175 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5177 FuncRec.Args := aArgs;
5180 TempHeight := aBitmap.FileHeight;
5181 TempWidth := aBitmap.FileWidth;
5183 FuncRec.Sender := Self;
5184 FuncRec.Size := Dimension;
5185 FuncRec.Position.Fields := FuncRec.Size.Fields;
5189 SourceData := aBitmap.Data;
5192 SourceFD.PreparePixel(FuncRec.Source);
5193 DestFD.PreparePixel (FuncRec.Dest);
5195 SourceMD := SourceFD.CreateMappingData;
5196 DestMD := DestFD.CreateMappingData;
5197 DestMD2 := DestFD.CreateMappingData;
5199 FuncRec.Position.Y := 0;
5200 while FuncRec.Position.Y < TempHeight do begin
5201 FuncRec.Position.X := 0;
5202 while FuncRec.Position.X < TempWidth do begin
5203 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5204 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5206 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5207 inc(FuncRec.Position.X);
5209 inc(FuncRec.Position.Y);
5212 SourceFD.FreeMappingData(SourceMD);
5213 DestFD.FreeMappingData(DestMD);
5214 DestFD.FreeMappingData(DestMD2);
5219 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5220 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5222 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5226 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5228 PixelData: TglBitmapPixelData;
5230 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5231 result := AddAlphaFromColorKeyFloat(
5232 aRed / PixelData.Range.r,
5233 aGreen / PixelData.Range.g,
5234 aBlue / PixelData.Range.b,
5235 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5238 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5239 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5241 values: array[0..2] of Single;
5244 PixelData: TglBitmapPixelData;
5246 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5247 with PixelData do begin
5249 values[1] := aGreen;
5252 for i := 0 to 2 do begin
5253 tmp := Trunc(Range.arr[i] * aDeviation);
5254 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5255 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5260 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5263 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5264 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5266 result := AddAlphaFromValueFloat(aAlpha / $FF);
5269 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5270 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5272 PixelData: TglBitmapPixelData;
5274 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5275 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5278 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5279 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5281 PixelData: TglBitmapPixelData;
5283 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5285 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5286 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5289 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5290 function TglBitmap.RemoveAlpha: Boolean;
5292 FormatDesc: TFormatDescriptor;
5295 FormatDesc := TFormatDescriptor.Get(Format);
5296 if Assigned(Data) then begin
5297 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5298 raise EglBitmapUnsupportedFormat.Create(Format);
5299 result := ConvertTo(FormatDesc.WithoutAlpha);
5303 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5304 function TglBitmap.Clone: TglBitmap;
5311 Temp := (ClassType.Create as TglBitmap);
5313 // copy texture data if assigned
5314 if Assigned(Data) then begin
5315 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5316 GetMem(TempPtr, Size);
5318 Move(Data^, TempPtr^, Size);
5319 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5321 if Assigned(TempPtr) then
5327 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5332 Temp.fTarget := Target;
5333 Temp.fFormat := Format;
5334 Temp.fMipMap := MipMap;
5335 Temp.fAnisotropic := Anisotropic;
5336 Temp.fBorderColor := fBorderColor;
5337 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5338 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5339 Temp.fFilterMin := fFilterMin;
5340 Temp.fFilterMag := fFilterMag;
5341 Temp.fWrapS := fWrapS;
5342 Temp.fWrapT := fWrapT;
5343 Temp.fWrapR := fWrapR;
5344 Temp.fFilename := fFilename;
5345 Temp.fCustomName := fCustomName;
5346 Temp.fCustomNameW := fCustomNameW;
5347 Temp.fCustomData := fCustomData;
5356 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5357 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5359 SourceFD, DestFD: TFormatDescriptor;
5360 SourcePD, DestPD: TglBitmapPixelData;
5361 ShiftData: TShiftData;
5363 function CanCopyDirect: Boolean;
5366 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5367 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5368 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5369 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5372 function CanShift: Boolean;
5375 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5376 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5377 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5378 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5381 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5384 while (aSource > aDest) and (aSource > 0) do begin
5386 aSource := aSource shr 1;
5391 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5392 SourceFD := TFormatDescriptor.Get(Format);
5393 DestFD := TFormatDescriptor.Get(aFormat);
5395 SourceFD.PreparePixel(SourcePD);
5396 DestFD.PreparePixel (DestPD);
5398 if CanCopyDirect then
5399 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5400 else if CanShift then begin
5401 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5402 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5403 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5404 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5405 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5407 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5412 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5413 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5415 if aUseRGB or aUseAlpha then
5416 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5417 ((PtrInt(aUseAlpha) and 1) shl 1) or
5418 (PtrInt(aUseRGB) and 1) ));
5421 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5422 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5424 fBorderColor[0] := aRed;
5425 fBorderColor[1] := aGreen;
5426 fBorderColor[2] := aBlue;
5427 fBorderColor[3] := aAlpha;
5428 if (ID > 0) then begin
5430 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5434 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5435 procedure TglBitmap.FreeData;
5440 SetDataPointer(TempPtr, tfEmpty); //be careful, Data could be freed by this method
5443 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5444 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5445 const aAlpha: Byte);
5447 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5450 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5451 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5453 PixelData: TglBitmapPixelData;
5455 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5457 aRed / PixelData.Range.r,
5458 aGreen / PixelData.Range.g,
5459 aBlue / PixelData.Range.b,
5460 aAlpha / PixelData.Range.a);
5463 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5464 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5466 PixelData: TglBitmapPixelData;
5468 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5469 with PixelData do begin
5470 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5471 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5472 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5473 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5475 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5478 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5479 procedure TglBitmap.SetFilter(const aMin, aMag: GLenum);
5484 fFilterMin := GL_NEAREST;
5486 fFilterMin := GL_LINEAR;
5487 GL_NEAREST_MIPMAP_NEAREST:
5488 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5489 GL_LINEAR_MIPMAP_NEAREST:
5490 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5491 GL_NEAREST_MIPMAP_LINEAR:
5492 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5493 GL_LINEAR_MIPMAP_LINEAR:
5494 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5496 raise EglBitmap.Create('SetFilter - Unknow MIN filter.');
5502 fFilterMag := GL_NEAREST;
5504 fFilterMag := GL_LINEAR;
5506 raise EglBitmap.Create('SetFilter - Unknow MAG filter.');
5510 if (ID > 0) then begin
5512 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5514 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5516 GL_NEAREST, GL_LINEAR:
5517 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5518 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5519 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5520 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5521 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5524 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5528 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5529 procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum);
5531 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5535 aTarget := GL_CLAMP;
5538 aTarget := GL_REPEAT;
5540 GL_CLAMP_TO_EDGE: begin
5541 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5542 aTarget := GL_CLAMP_TO_EDGE
5544 aTarget := GL_CLAMP;
5547 GL_CLAMP_TO_BORDER: begin
5548 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5549 aTarget := GL_CLAMP_TO_BORDER
5551 aTarget := GL_CLAMP;
5554 GL_MIRRORED_REPEAT: begin
5555 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5556 aTarget := GL_MIRRORED_REPEAT
5558 raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5561 raise EglBitmap.Create('SetWrap - Unknow Texturewrap');
5566 CheckAndSetWrap(S, fWrapS);
5567 CheckAndSetWrap(T, fWrapT);
5568 CheckAndSetWrap(R, fWrapR);
5570 if (ID > 0) then begin
5572 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5573 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5574 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5578 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5579 procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum);
5581 procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer);
5583 if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or
5584 (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then
5585 fSwizzle[aIndex] := aValue
5587 raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value');
5591 if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
5592 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
5593 CheckAndSetValue(r, 0);
5594 CheckAndSetValue(g, 1);
5595 CheckAndSetValue(b, 2);
5596 CheckAndSetValue(a, 3);
5598 if (ID > 0) then begin
5600 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, @fSwizzle[0]);
5604 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5605 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5607 if aEnableTextureUnit then
5610 glBindTexture(Target, ID);
5613 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5614 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5616 if aDisableTextureUnit then
5618 glBindTexture(Target, 0);
5621 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5622 constructor TglBitmap.Create;
5624 if (ClassType = TglBitmap) then
5625 raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5626 {$IFDEF GLB_NATIVE_OGL}
5627 glbReadOpenGLExtensions;
5632 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5633 constructor TglBitmap.Create(const aFileName: String);
5636 LoadFromFile(aFileName);
5639 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5640 constructor TglBitmap.Create(const aStream: TStream);
5643 LoadFromStream(aStream);
5646 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5647 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
5653 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5654 GetMem(Image, ImageSize);
5656 FillChar(Image^, ImageSize, #$FF);
5657 SetDataPointer(Image, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5659 if Assigned(Image) then
5665 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5666 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
5667 const aFunc: TglBitmapFunction; const aArgs: Pointer);
5670 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5673 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5674 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5677 LoadFromResource(aInstance, aResource, aResType);
5680 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5681 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5684 LoadFromResourceID(aInstance, aResourceID, aResType);
5687 {$IFDEF GLB_SUPPORT_PNG_READ}
5688 {$IF DEFINED(GLB_LAZ_PNG)}
5689 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5690 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5691 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5692 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5694 png: TPortableNetworkGraphic;
5695 intf: TLazIntfImage;
5699 StreamPos := aStream.Position;
5700 png := TPortableNetworkGraphic.Create;
5702 png.LoadFromStream(aStream);
5703 intf := png.CreateIntfImage;
5705 AssignFromLazIntfImage(intf);
5708 aStream.Position := StreamPos;
5716 aStream.Position := StreamPos;
5724 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
5725 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5726 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5728 Surface: PSDL_Surface;
5732 RWops := glBitmapCreateRWops(aStream);
5734 if IMG_isPNG(RWops) > 0 then begin
5735 Surface := IMG_LoadPNG_RW(RWops);
5737 AssignFromSurface(Surface);
5740 SDL_FreeSurface(Surface);
5748 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5749 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5750 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5752 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5755 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5756 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5759 signature: array [0..7] of byte;
5761 png_info: png_infop;
5763 TempHeight, TempWidth: Integer;
5764 Format: TglBitmapFormat;
5767 png_rows: array of pByte;
5768 Row, LineSize: Integer;
5772 if not init_libPNG then
5773 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5777 StreamPos := aStream.Position;
5778 aStream.Read(signature{%H-}, 8);
5779 aStream.Position := StreamPos;
5781 if png_check_sig(@signature, 8) <> 0 then begin
5783 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5785 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5788 png_info := png_create_info_struct(png);
5789 if png_info = nil then begin
5790 png_destroy_read_struct(@png, nil, nil);
5791 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5794 // set read callback
5795 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5797 // read informations
5798 png_read_info(png, png_info);
5801 TempHeight := png_get_image_height(png, png_info);
5802 TempWidth := png_get_image_width(png, png_info);
5805 case png_get_color_type(png, png_info) of
5806 PNG_COLOR_TYPE_GRAY:
5807 Format := tfLuminance8;
5808 PNG_COLOR_TYPE_GRAY_ALPHA:
5809 Format := tfLuminance8Alpha8;
5812 PNG_COLOR_TYPE_RGB_ALPHA:
5815 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5818 // cut upper 8 bit from 16 bit formats
5819 if png_get_bit_depth(png, png_info) > 8 then
5820 png_set_strip_16(png);
5822 // expand bitdepth smaller than 8
5823 if png_get_bit_depth(png, png_info) < 8 then
5824 png_set_expand(png);
5826 // allocating mem for scanlines
5827 LineSize := png_get_rowbytes(png, png_info);
5828 GetMem(png_data, TempHeight * LineSize);
5830 SetLength(png_rows, TempHeight);
5831 for Row := Low(png_rows) to High(png_rows) do begin
5832 png_rows[Row] := png_data;
5833 Inc(png_rows[Row], Row * LineSize);
5836 // read complete image into scanlines
5837 png_read_image(png, @png_rows[0]);
5840 png_read_end(png, png_info);
5842 // destroy read struct
5843 png_destroy_read_struct(@png, @png_info, nil);
5845 SetLength(png_rows, 0);
5848 SetDataPointer(png_data, Format, TempWidth, TempHeight); //be careful, Data could be freed by this method
5852 if Assigned(png_data) then
5862 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5863 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5864 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5869 Row, Col, PixSize, LineSize: Integer;
5870 NewImage, pSource, pDest, pAlpha: pByte;
5871 PngFormat: TglBitmapFormat;
5872 FormatDesc: TFormatDescriptor;
5875 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
5880 StreamPos := aStream.Position;
5881 aStream.Read(Header[0], SizeOf(Header));
5882 aStream.Position := StreamPos;
5884 {Test if the header matches}
5885 if Header = PngHeader then begin
5886 Png := TPNGObject.Create;
5888 Png.LoadFromStream(aStream);
5890 case Png.Header.ColorType of
5892 PngFormat := tfLuminance8;
5893 COLOR_GRAYSCALEALPHA:
5894 PngFormat := tfLuminance8Alpha8;
5896 PngFormat := tfBGR8;
5898 PngFormat := tfBGRA8;
5900 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5903 FormatDesc := TFormatDescriptor.Get(PngFormat);
5904 PixSize := Round(FormatDesc.PixelSize);
5905 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
5907 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5911 case Png.Header.ColorType of
5912 COLOR_RGB, COLOR_GRAYSCALE:
5914 for Row := 0 to Png.Height -1 do begin
5915 Move (Png.Scanline[Row]^, pDest^, LineSize);
5916 Inc(pDest, LineSize);
5919 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5921 PixSize := PixSize -1;
5923 for Row := 0 to Png.Height -1 do begin
5924 pSource := Png.Scanline[Row];
5925 pAlpha := pByte(Png.AlphaScanline[Row]);
5927 for Col := 0 to Png.Width -1 do begin
5928 Move (pSource^, pDest^, PixSize);
5929 Inc(pSource, PixSize);
5930 Inc(pDest, PixSize);
5939 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5942 SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); //be careful, Data could be freed by this method
5946 if Assigned(NewImage) then
5958 {$IFDEF GLB_SUPPORT_PNG_WRITE}
5959 {$IFDEF GLB_LIB_PNG}
5960 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5961 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5963 TStream(png_get_io_ptr(png)).Write(buffer^, size);
5967 {$IF DEFINED(GLB_LAZ_PNG)}
5968 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5969 procedure TglBitmap.SavePNG(const aStream: TStream);
5971 png: TPortableNetworkGraphic;
5972 intf: TLazIntfImage;
5974 png := TPortableNetworkGraphic.Create;
5975 intf := TLazIntfImage.Create(0, 0);
5977 if not AssignToLazIntfImage(intf) then
5978 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
5979 png.LoadFromIntfImage(intf);
5980 png.SaveToStream(aStream);
5987 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5988 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5989 procedure TglBitmap.SavePNG(const aStream: TStream);
5992 png_info: png_infop;
5993 png_rows: array of pByte;
5997 FormatDesc: TFormatDescriptor;
5999 if not (ftPNG in FormatGetSupportedFiles(Format)) then
6000 raise EglBitmapUnsupportedFormat.Create(Format);
6002 if not init_libPNG then
6003 raise Exception.Create('unable to initialize libPNG.');
6007 tfAlpha8, tfLuminance8:
6008 ColorType := PNG_COLOR_TYPE_GRAY;
6010 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
6012 ColorType := PNG_COLOR_TYPE_RGB;
6014 ColorType := PNG_COLOR_TYPE_RGBA;
6016 raise EglBitmapUnsupportedFormat.Create(Format);
6019 FormatDesc := TFormatDescriptor.Get(Format);
6020 LineSize := FormatDesc.GetSize(Width, 1);
6022 // creating array for scanline
6023 SetLength(png_rows, Height);
6025 for Row := 0 to Height - 1 do begin
6026 png_rows[Row] := Data;
6027 Inc(png_rows[Row], Row * LineSize)
6031 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
6033 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
6036 png_info := png_create_info_struct(png);
6037 if png_info = nil then begin
6038 png_destroy_write_struct(@png, nil);
6039 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
6042 // set read callback
6043 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
6046 png_set_compression_level(png, 6);
6048 if Format in [tfBGR8, tfBGRA8] then
6051 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
6052 png_write_info(png, png_info);
6053 png_write_image(png, @png_rows[0]);
6054 png_write_end(png, png_info);
6055 png_destroy_write_struct(@png, @png_info);
6057 SetLength(png_rows, 0);
6064 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
6065 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6066 procedure TglBitmap.SavePNG(const aStream: TStream);
6070 pSource, pDest: pByte;
6071 X, Y, PixSize: Integer;
6072 ColorType: Cardinal;
6078 if not (ftPNG in FormatGetSupportedFiles (Format)) then
6079 raise EglBitmapUnsupportedFormat.Create(Format);
6082 tfAlpha8, tfLuminance8: begin
6083 ColorType := COLOR_GRAYSCALE;
6087 tfLuminance8Alpha8: begin
6088 ColorType := COLOR_GRAYSCALEALPHA;
6092 tfBGR8, tfRGB8: begin
6093 ColorType := COLOR_RGB;
6097 tfBGRA8, tfRGBA8: begin
6098 ColorType := COLOR_RGBALPHA;
6103 raise EglBitmapUnsupportedFormat.Create(Format);
6106 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
6110 for Y := 0 to Height -1 do begin
6111 pDest := png.ScanLine[Y];
6112 for X := 0 to Width -1 do begin
6113 Move(pSource^, pDest^, PixSize);
6114 Inc(pDest, PixSize);
6115 Inc(pSource, PixSize);
6117 png.AlphaScanline[Y]^[X] := pSource^;
6122 // convert RGB line to BGR
6123 if Format in [tfRGB8, tfRGBA8] then begin
6124 pTemp := png.ScanLine[Y];
6125 for X := 0 to Width -1 do begin
6126 Temp := pByteArray(pTemp)^[0];
6127 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
6128 pByteArray(pTemp)^[2] := Temp;
6135 Png.CompressionLevel := 6;
6136 Png.SaveToStream(aStream);
6144 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6145 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6146 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6147 {$IFDEF GLB_LIB_JPEG}
6149 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
6150 glBitmap_libJPEG_source_mgr = record
6151 pub: jpeg_source_mgr;
6154 SrcBuffer: array [1..4096] of byte;
6157 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
6158 glBitmap_libJPEG_dest_mgr = record
6159 pub: jpeg_destination_mgr;
6161 DestStream: TStream;
6162 DestBuffer: array [1..4096] of byte;
6165 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
6171 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
6177 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
6182 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
6188 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
6194 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6195 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
6197 src: glBitmap_libJPEG_source_mgr_ptr;
6200 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6202 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
6203 if (bytes <= 0) then begin
6204 src^.SrcBuffer[1] := $FF;
6205 src^.SrcBuffer[2] := JPEG_EOI;
6209 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
6210 src^.pub.bytes_in_buffer := bytes;
6215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6216 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
6218 src: glBitmap_libJPEG_source_mgr_ptr;
6220 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6222 if num_bytes > 0 then begin
6223 // wanted byte isn't in buffer so set stream position and read buffer
6224 if num_bytes > src^.pub.bytes_in_buffer then begin
6225 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
6226 src^.pub.fill_input_buffer(cinfo);
6228 // wanted byte is in buffer so only skip
6229 inc(src^.pub.next_input_byte, num_bytes);
6230 dec(src^.pub.bytes_in_buffer, num_bytes);
6235 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6236 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
6238 dest: glBitmap_libJPEG_dest_mgr_ptr;
6240 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6242 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
6243 // write complete buffer
6244 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
6247 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
6248 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
6254 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6255 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
6258 dest: glBitmap_libJPEG_dest_mgr_ptr;
6260 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6262 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6263 // check for endblock
6264 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6266 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6271 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6276 {$IFDEF GLB_SUPPORT_JPEG_READ}
6277 {$IF DEFINED(GLB_LAZ_JPEG)}
6278 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6279 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6282 intf: TLazIntfImage;
6286 StreamPos := aStream.Position;
6287 jpeg := TJPEGImage.Create;
6289 jpeg.LoadFromStream(aStream);
6290 intf := TLazIntfImage.Create(0, 0);
6292 intf.LoadFromBitmap(jpeg.BitmapHandle, jpeg.MaskHandle);
6293 AssignFromLazIntfImage(intf);
6296 aStream.Position := StreamPos;
6304 aStream.Position := StreamPos;
6312 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
6313 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6314 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6316 Surface: PSDL_Surface;
6321 RWops := glBitmapCreateRWops(aStream);
6323 if IMG_isJPG(RWops) > 0 then begin
6324 Surface := IMG_LoadJPG_RW(RWops);
6326 AssignFromSurface(Surface);
6329 SDL_FreeSurface(Surface);
6337 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6338 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6339 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6342 Temp: array[0..1]of Byte;
6344 jpeg: jpeg_decompress_struct;
6345 jpeg_err: jpeg_error_mgr;
6347 IntFormat: TglBitmapFormat;
6349 TempHeight, TempWidth: Integer;
6354 FormatDesc: TFormatDescriptor;
6358 if not init_libJPEG then
6359 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6362 // reading first two bytes to test file and set cursor back to begin
6363 StreamPos := aStream.Position;
6364 aStream.Read({%H-}Temp[0], 2);
6365 aStream.Position := StreamPos;
6367 // if Bitmap then read file.
6368 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6369 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6370 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6373 jpeg.err := jpeg_std_error(@jpeg_err);
6374 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6375 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6377 // decompression struct
6378 jpeg_create_decompress(@jpeg);
6380 // allocation space for streaming methods
6381 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6383 // seeting up custom functions
6384 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6385 pub.init_source := glBitmap_libJPEG_init_source;
6386 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6387 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6388 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6389 pub.term_source := glBitmap_libJPEG_term_source;
6391 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6392 pub.next_input_byte := nil; // until buffer loaded
6394 SrcStream := aStream;
6397 // set global decoding state
6398 jpeg.global_state := DSTATE_START;
6400 // read header of jpeg
6401 jpeg_read_header(@jpeg, false);
6403 // setting output parameter
6404 case jpeg.jpeg_color_space of
6407 jpeg.out_color_space := JCS_GRAYSCALE;
6408 IntFormat := tfLuminance8;
6411 jpeg.out_color_space := JCS_RGB;
6412 IntFormat := tfRGB8;
6416 jpeg_start_decompress(@jpeg);
6418 TempHeight := jpeg.output_height;
6419 TempWidth := jpeg.output_width;
6421 FormatDesc := TFormatDescriptor.Get(IntFormat);
6423 // creating new image
6424 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6428 for Row := 0 to TempHeight -1 do begin
6429 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6430 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6433 // finish decompression
6434 jpeg_finish_decompress(@jpeg);
6436 // destroy decompression
6437 jpeg_destroy_decompress(@jpeg);
6439 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
6443 if Assigned(pImage) then
6453 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6454 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6455 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6460 Temp: array[0..1]of Byte;
6464 // reading first two bytes to test file and set cursor back to begin
6465 StreamPos := aStream.Position;
6466 aStream.Read(Temp[0], 2);
6467 aStream.Position := StreamPos;
6469 // if Bitmap then read file.
6470 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6471 bmp := TBitmap.Create;
6473 jpg := TJPEGImage.Create;
6475 jpg.LoadFromStream(aStream);
6477 result := AssignFromBitmap(bmp);
6489 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6490 {$IF DEFINED(GLB_LAZ_JPEG)}
6491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6492 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6495 intf: TLazIntfImage;
6497 jpeg := TJPEGImage.Create;
6498 intf := TLazIntfImage.Create(0, 0);
6500 if not AssignToLazIntfImage(intf) then
6501 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6502 jpeg.LoadFromIntfImage(intf);
6503 jpeg.SaveToStream(aStream);
6510 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6511 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6512 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6514 jpeg: jpeg_compress_struct;
6515 jpeg_err: jpeg_error_mgr;
6517 pTemp, pTemp2: pByte;
6519 procedure CopyRow(pDest, pSource: pByte);
6523 for X := 0 to Width - 1 do begin
6524 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6525 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6526 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6533 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6534 raise EglBitmapUnsupportedFormat.Create(Format);
6536 if not init_libJPEG then
6537 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6540 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6541 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6544 jpeg.err := jpeg_std_error(@jpeg_err);
6545 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6546 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6548 // compression struct
6549 jpeg_create_compress(@jpeg);
6551 // allocation space for streaming methods
6552 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6554 // seeting up custom functions
6555 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6556 pub.init_destination := glBitmap_libJPEG_init_destination;
6557 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6558 pub.term_destination := glBitmap_libJPEG_term_destination;
6560 pub.next_output_byte := @DestBuffer[1];
6561 pub.free_in_buffer := Length(DestBuffer);
6563 DestStream := aStream;
6566 // very important state
6567 jpeg.global_state := CSTATE_START;
6568 jpeg.image_width := Width;
6569 jpeg.image_height := Height;
6571 tfAlpha8, tfLuminance8: begin
6572 jpeg.input_components := 1;
6573 jpeg.in_color_space := JCS_GRAYSCALE;
6575 tfRGB8, tfBGR8: begin
6576 jpeg.input_components := 3;
6577 jpeg.in_color_space := JCS_RGB;
6581 jpeg_set_defaults(@jpeg);
6582 jpeg_set_quality(@jpeg, 95, true);
6583 jpeg_start_compress(@jpeg, true);
6586 if Format = tfBGR8 then
6587 GetMem(pTemp2, fRowSize)
6592 for Row := 0 to jpeg.image_height -1 do begin
6594 if Format = tfBGR8 then
6595 CopyRow(pTemp2, pTemp)
6600 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6601 inc(pTemp, fRowSize);
6605 if Format = tfBGR8 then
6608 jpeg_finish_compress(@jpeg);
6609 jpeg_destroy_compress(@jpeg);
6615 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6616 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6617 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6622 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6623 raise EglBitmapUnsupportedFormat.Create(Format);
6625 Bmp := TBitmap.Create;
6627 Jpg := TJPEGImage.Create;
6629 AssignToBitmap(Bmp);
6630 if (Format in [tfAlpha8, tfLuminance8]) then begin
6631 Jpg.Grayscale := true;
6632 Jpg.PixelFormat := jf8Bit;
6635 Jpg.SaveToStream(aStream);
6646 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6647 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6648 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6655 BMP_COMP_BITFIELDS = 3;
6658 TBMPHeader = packed record
6663 bfOffBits: Cardinal;
6666 TBMPInfo = packed record
6672 biCompression: Cardinal;
6673 biSizeImage: Cardinal;
6674 biXPelsPerMeter: Longint;
6675 biYPelsPerMeter: Longint;
6676 biClrUsed: Cardinal;
6677 biClrImportant: Cardinal;
6680 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6681 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6683 //////////////////////////////////////////////////////////////////////////////////////////////////
6684 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6687 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6688 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6691 case aInfo.biCompression of
6693 BMP_COMP_RLE8: begin
6694 raise EglBitmap.Create('RLE compression is not supported');
6696 BMP_COMP_BITFIELDS: begin
6697 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6698 aStream.Read(aMask.r, SizeOf(aMask.r));
6699 aStream.Read(aMask.g, SizeOf(aMask.g));
6700 aStream.Read(aMask.b, SizeOf(aMask.b));
6701 aStream.Read(aMask.a, SizeOf(aMask.a));
6703 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
6707 //get suitable format
6708 case aInfo.biBitCount of
6709 8: result := tfLuminance8;
6710 16: result := tfBGR5;
6711 24: result := tfBGR8;
6712 32: result := tfBGRA8;
6716 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6719 ColorTable: TbmpColorTable;
6722 if (aInfo.biBitCount >= 16) then
6724 aFormat := tfLuminance8;
6725 c := aInfo.biClrUsed;
6727 c := 1 shl aInfo.biBitCount;
6728 SetLength(ColorTable, c);
6729 for i := 0 to c-1 do begin
6730 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6731 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6735 result := TbmpColorTableFormat.Create;
6736 result.PixelSize := aInfo.biBitCount / 8;
6737 result.ColorTable := ColorTable;
6738 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6741 //////////////////////////////////////////////////////////////////////////////////////////////////
6742 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6743 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6745 TmpFormat: TglBitmapFormat;
6746 FormatDesc: TFormatDescriptor;
6749 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6750 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6751 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6752 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6753 aFormat := FormatDesc.Format;
6758 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6759 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6760 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6761 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6763 result := TbmpBitfieldFormat.Create;
6764 result.PixelSize := aInfo.biBitCount / 8;
6765 result.RedMask := aMask.r;
6766 result.GreenMask := aMask.g;
6767 result.BlueMask := aMask.b;
6768 result.AlphaMask := aMask.a;
6775 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6776 PaddingBuff: Cardinal;
6777 LineBuf, ImageData, TmpData: PByte;
6778 SourceMD, DestMD: Pointer;
6779 BmpFormat: TglBitmapFormat;
6782 Mask: TglBitmapColorRec;
6787 SpecialFormat: TFormatDescriptor;
6788 FormatDesc: TFormatDescriptor;
6790 //////////////////////////////////////////////////////////////////////////////////////////////////
6791 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6794 Pixel: TglBitmapPixelData;
6796 aStream.Read(aLineBuf^, rbLineSize);
6797 SpecialFormat.PreparePixel(Pixel);
6798 for i := 0 to Info.biWidth-1 do begin
6799 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6800 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6801 FormatDesc.Map(Pixel, aData, DestMD);
6807 BmpFormat := tfEmpty;
6808 SpecialFormat := nil;
6814 StartPos := aStream.Position;
6815 aStream.Read(Header{%H-}, SizeOf(Header));
6817 if Header.bfType = BMP_MAGIC then begin
6819 BmpFormat := ReadInfo(Info, Mask);
6820 SpecialFormat := ReadColorTable(BmpFormat, Info);
6821 if not Assigned(SpecialFormat) then
6822 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6823 aStream.Position := StartPos + Header.bfOffBits;
6825 if (BmpFormat <> tfEmpty) then begin
6826 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6827 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6828 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6829 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6832 DestMD := FormatDesc.CreateMappingData;
6833 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6834 GetMem(ImageData, ImageSize);
6835 if Assigned(SpecialFormat) then begin
6836 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6837 SourceMD := SpecialFormat.CreateMappingData;
6842 FillChar(ImageData^, ImageSize, $FF);
6843 TmpData := ImageData;
6844 if (Info.biHeight > 0) then
6845 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6846 for i := 0 to Abs(Info.biHeight)-1 do begin
6847 if Assigned(SpecialFormat) then
6848 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6850 aStream.Read(TmpData^, wbLineSize); //else only read data
6851 if (Info.biHeight > 0) then
6852 dec(TmpData, wbLineSize)
6854 inc(TmpData, wbLineSize);
6855 aStream.Read(PaddingBuff{%H-}, Padding);
6857 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method
6860 if Assigned(LineBuf) then
6862 if Assigned(SourceMD) then
6863 SpecialFormat.FreeMappingData(SourceMD);
6864 FormatDesc.FreeMappingData(DestMD);
6867 if Assigned(ImageData) then
6872 raise EglBitmap.Create('LoadBMP - No suitable format found');
6874 aStream.Position := StartPos;
6878 FreeAndNil(SpecialFormat);
6881 else aStream.Position := StartPos;
6884 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6885 procedure TglBitmap.SaveBMP(const aStream: TStream);
6889 Converter: TbmpColorTableFormat;
6890 FormatDesc: TFormatDescriptor;
6891 SourceFD, DestFD: Pointer;
6892 pData, srcData, dstData, ConvertBuffer: pByte;
6894 Pixel: TglBitmapPixelData;
6895 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6896 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6898 PaddingBuff: Cardinal;
6900 function GetLineWidth : Integer;
6902 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6906 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6907 raise EglBitmapUnsupportedFormat.Create(Format);
6910 FormatDesc := TFormatDescriptor.Get(Format);
6911 ImageSize := FormatDesc.GetSize(Dimension);
6913 FillChar(Header{%H-}, SizeOf(Header), 0);
6914 Header.bfType := BMP_MAGIC;
6915 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6916 Header.bfReserved1 := 0;
6917 Header.bfReserved2 := 0;
6918 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6920 FillChar(Info{%H-}, SizeOf(Info), 0);
6921 Info.biSize := SizeOf(Info);
6922 Info.biWidth := Width;
6923 Info.biHeight := Height;
6925 Info.biCompression := BMP_COMP_RGB;
6926 Info.biSizeImage := ImageSize;
6931 Info.biBitCount := 4;
6932 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6933 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6934 Converter := TbmpColorTableFormat.Create;
6935 Converter.PixelSize := 0.5;
6936 Converter.Format := Format;
6937 Converter.Range := glBitmapColorRec($F, $F, $F, $0);
6938 Converter.CreateColorTable;
6941 tfR3G3B2, tfLuminance8: begin
6942 Info.biBitCount := 8;
6943 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6944 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6945 Converter := TbmpColorTableFormat.Create;
6946 Converter.PixelSize := 1;
6947 Converter.Format := Format;
6948 if (Format = tfR3G3B2) then begin
6949 Converter.Range := glBitmapColorRec($7, $7, $3, $0);
6950 Converter.Shift := glBitmapShiftRec(0, 3, 6, 0);
6952 Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0);
6953 Converter.CreateColorTable;
6956 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6957 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6958 Info.biBitCount := 16;
6959 Info.biCompression := BMP_COMP_BITFIELDS;
6962 tfBGR8, tfRGB8: begin
6963 Info.biBitCount := 24;
6966 tfRGB10, tfRGB10A2, tfRGBA8,
6967 tfBGR10, tfBGR10A2, tfBGRA8: begin
6968 Info.biBitCount := 32;
6969 Info.biCompression := BMP_COMP_BITFIELDS;
6972 raise EglBitmapUnsupportedFormat.Create(Format);
6974 Info.biXPelsPerMeter := 2835;
6975 Info.biYPelsPerMeter := 2835;
6978 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6979 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
6980 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
6982 RedMask := FormatDesc.RedMask;
6983 GreenMask := FormatDesc.GreenMask;
6984 BlueMask := FormatDesc.BlueMask;
6985 AlphaMask := FormatDesc.AlphaMask;
6989 aStream.Write(Header, SizeOf(Header));
6990 aStream.Write(Info, SizeOf(Info));
6993 if Assigned(Converter) then
6994 aStream.Write(Converter.ColorTable[0].b,
6995 SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable));
6998 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6999 aStream.Write(RedMask, SizeOf(Cardinal));
7000 aStream.Write(GreenMask, SizeOf(Cardinal));
7001 aStream.Write(BlueMask, SizeOf(Cardinal));
7002 aStream.Write(AlphaMask, SizeOf(Cardinal));
7006 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
7007 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
7008 Padding := GetLineWidth - wbLineSize;
7012 inc(pData, (Height-1) * rbLineSize);
7014 // prepare row buffer. But only for RGB because RGBA supports color masks
7015 // so it's possible to change color within the image.
7016 if Assigned(Converter) then begin
7017 FormatDesc.PreparePixel(Pixel);
7018 GetMem(ConvertBuffer, wbLineSize);
7019 SourceFD := FormatDesc.CreateMappingData;
7020 DestFD := Converter.CreateMappingData;
7022 ConvertBuffer := nil;
7025 for LineIdx := 0 to Height - 1 do begin
7027 if Assigned(Converter) then begin
7029 dstData := ConvertBuffer;
7030 for PixelIdx := 0 to Info.biWidth-1 do begin
7031 FormatDesc.Unmap(srcData, Pixel, SourceFD);
7032 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
7033 Converter.Map(Pixel, dstData, DestFD);
7035 aStream.Write(ConvertBuffer^, wbLineSize);
7037 aStream.Write(pData^, rbLineSize);
7039 dec(pData, rbLineSize);
7040 if (Padding > 0) then
7041 aStream.Write(PaddingBuff, Padding);
7044 // destroy row buffer
7045 if Assigned(ConvertBuffer) then begin
7046 FormatDesc.FreeMappingData(SourceFD);
7047 Converter.FreeMappingData(DestFD);
7048 FreeMem(ConvertBuffer);
7052 if Assigned(Converter) then
7057 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7058 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7059 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7061 TTGAHeader = packed record
7065 //ColorMapSpec: Array[0..4] of Byte;
7066 ColorMapStart: Word;
7067 ColorMapLength: Word;
7068 ColorMapEntrySize: Byte;
7078 TGA_UNCOMPRESSED_RGB = 2;
7079 TGA_UNCOMPRESSED_GRAY = 3;
7080 TGA_COMPRESSED_RGB = 10;
7081 TGA_COMPRESSED_GRAY = 11;
7083 TGA_NONE_COLOR_TABLE = 0;
7085 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7086 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
7089 ImageData: System.PByte;
7090 StartPosition: Int64;
7091 PixelSize, LineSize: Integer;
7092 tgaFormat: TglBitmapFormat;
7093 FormatDesc: TFormatDescriptor;
7094 Counter: packed record
7096 low, high, dir: Integer;
7103 ////////////////////////////////////////////////////////////////////////////////////////
7104 procedure ReadUncompressed;
7107 buf, tmp1, tmp2: System.PByte;
7110 if (Counter.X.dir < 0) then
7111 GetMem(buf, LineSize);
7113 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
7115 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
7116 if (Counter.X.dir < 0) then begin //flip X
7117 aStream.Read(buf^, LineSize);
7119 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
7120 for i := 0 to Header.Width-1 do begin //for all pixels in line
7121 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
7126 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
7129 aStream.Read(tmp1^, LineSize);
7130 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
7133 if Assigned(buf) then
7138 ////////////////////////////////////////////////////////////////////////////////////////
7139 procedure ReadCompressed;
7141 /////////////////////////////////////////////////////////////////
7143 TmpData: System.PByte;
7144 LinePixelsRead: Integer;
7145 procedure CheckLine;
7147 if (LinePixelsRead >= Header.Width) then begin
7148 LinePixelsRead := 0;
7149 inc(Counter.Y.low, Counter.Y.dir); //next line index
7150 TmpData := ImageData;
7151 inc(TmpData, Counter.Y.low * LineSize); //set line
7152 if (Counter.X.dir < 0) then //if x flipped then
7153 inc(TmpData, LineSize - PixelSize); //set last pixel
7157 /////////////////////////////////////////////////////////////////
7160 CacheSize, CachePos: Integer;
7161 procedure CachedRead(out Buffer; Count: Integer);
7165 if (CachePos + Count > CacheSize) then begin
7166 //if buffer overflow save non read bytes
7168 if (CacheSize - CachePos > 0) then begin
7169 BytesRead := CacheSize - CachePos;
7170 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
7171 inc(CachePos, BytesRead);
7174 //load cache from file
7175 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
7176 aStream.Read(Cache^, CacheSize);
7179 //read rest of requested bytes
7180 if (Count - BytesRead > 0) then begin
7181 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
7182 inc(CachePos, Count - BytesRead);
7185 //if no buffer overflow just read the data
7186 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
7187 inc(CachePos, Count);
7191 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
7196 inc(aBuffer, Counter.X.dir);
7199 PWord(aBuffer)^ := PWord(aData)^;
7200 inc(aBuffer, 2 * Counter.X.dir);
7203 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
7204 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
7205 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
7206 inc(aBuffer, 3 * Counter.X.dir);
7209 PCardinal(aBuffer)^ := PCardinal(aData)^;
7210 inc(aBuffer, 4 * Counter.X.dir);
7216 TotalPixelsToRead, TotalPixelsRead: Integer;
7218 buf: array [0..3] of Byte; //1 pixel is max 32bit long
7219 PixelRepeat: Boolean;
7220 PixelsToRead, PixelCount: Integer;
7225 TotalPixelsToRead := Header.Width * Header.Height;
7226 TotalPixelsRead := 0;
7227 LinePixelsRead := 0;
7229 GetMem(Cache, CACHE_SIZE);
7231 TmpData := ImageData;
7232 inc(TmpData, Counter.Y.low * LineSize); //set line
7233 if (Counter.X.dir < 0) then //if x flipped then
7234 inc(TmpData, LineSize - PixelSize); //set last pixel
7238 CachedRead(Temp, 1);
7239 PixelRepeat := (Temp and $80) > 0;
7240 PixelsToRead := (Temp and $7F) + 1;
7241 inc(TotalPixelsRead, PixelsToRead);
7244 CachedRead(buf[0], PixelSize);
7245 while (PixelsToRead > 0) do begin
7247 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
7248 while (PixelCount > 0) do begin
7249 if not PixelRepeat then
7250 CachedRead(buf[0], PixelSize);
7251 PixelToBuffer(@buf[0], TmpData);
7252 inc(LinePixelsRead);
7257 until (TotalPixelsRead >= TotalPixelsToRead);
7263 function IsGrayFormat: Boolean;
7265 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
7271 // reading header to test file and set cursor back to begin
7272 StartPosition := aStream.Position;
7273 aStream.Read(Header{%H-}, SizeOf(Header));
7275 // no colormapped files
7276 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
7277 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
7280 if Header.ImageID <> 0 then // skip image ID
7281 aStream.Position := aStream.Position + Header.ImageID;
7283 tgaFormat := tfEmpty;
7285 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
7286 0: tgaFormat := tfLuminance8;
7287 8: tgaFormat := tfAlpha8;
7290 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
7291 0: tgaFormat := tfLuminance16;
7292 8: tgaFormat := tfLuminance8Alpha8;
7293 end else case (Header.ImageDesc and $F) of
7294 0: tgaFormat := tfBGR5;
7295 1: tgaFormat := tfBGR5A1;
7296 4: tgaFormat := tfBGRA4;
7299 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7300 0: tgaFormat := tfBGR8;
7303 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7304 2: tgaFormat := tfBGR10A2;
7305 8: tgaFormat := tfBGRA8;
7309 if (tgaFormat = tfEmpty) then
7310 raise EglBitmap.Create('LoadTga - unsupported format');
7312 FormatDesc := TFormatDescriptor.Get(tgaFormat);
7313 PixelSize := FormatDesc.GetSize(1, 1);
7314 LineSize := FormatDesc.GetSize(Header.Width, 1);
7316 GetMem(ImageData, LineSize * Header.Height);
7319 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7320 Counter.X.low := Header.Height-1;;
7321 Counter.X.high := 0;
7322 Counter.X.dir := -1;
7325 Counter.X.high := Header.Height-1;
7330 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7332 Counter.Y.high := Header.Height-1;
7335 Counter.Y.low := Header.Height-1;;
7336 Counter.Y.high := 0;
7337 Counter.Y.dir := -1;
7341 case Header.ImageType of
7342 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7344 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7348 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method
7351 if Assigned(ImageData) then
7356 aStream.Position := StartPosition;
7359 else aStream.Position := StartPosition;
7362 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7363 procedure TglBitmap.SaveTGA(const aStream: TStream);
7366 LineSize, Size, x, y: Integer;
7367 Pixel: TglBitmapPixelData;
7368 LineBuf, SourceData, DestData: PByte;
7369 SourceMD, DestMD: Pointer;
7370 FormatDesc: TFormatDescriptor;
7371 Converter: TFormatDescriptor;
7373 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7374 raise EglBitmapUnsupportedFormat.Create(Format);
7377 FillChar(Header{%H-}, SizeOf(Header), 0);
7380 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7381 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7382 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7384 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7387 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7389 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7390 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7392 else if (Format in [tfBGR8, tfRGB8]) then
7400 Header.ImageDesc := 1 and $F;
7401 tfRGB10A2, tfBGR10A2:
7402 Header.ImageDesc := 2 and $F;
7404 Header.ImageDesc := 4 and $F;
7405 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7406 Header.ImageDesc := 8 and $F;
7409 Header.Width := Width;
7410 Header.Height := Height;
7411 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7412 aStream.Write(Header, SizeOf(Header));
7414 // convert RGB(A) to BGR(A)
7416 FormatDesc := TFormatDescriptor.Get(Format);
7417 Size := FormatDesc.GetSize(Dimension);
7418 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7419 if (FormatDesc.RGBInverted = tfEmpty) then
7420 raise EglBitmap.Create('inverted RGB format is empty');
7421 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7422 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7423 (Converter.PixelSize <> FormatDesc.PixelSize) then
7424 raise EglBitmap.Create('invalid inverted RGB format');
7427 if Assigned(Converter) then begin
7428 LineSize := FormatDesc.GetSize(Width, 1);
7429 GetMem(LineBuf, LineSize);
7430 SourceMD := FormatDesc.CreateMappingData;
7431 DestMD := Converter.CreateMappingData;
7434 for y := 0 to Height-1 do begin
7435 DestData := LineBuf;
7436 for x := 0 to Width-1 do begin
7437 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7438 Converter.Map(Pixel, DestData, DestMD);
7440 aStream.Write(LineBuf^, LineSize);
7444 FormatDesc.FreeMappingData(SourceMD);
7445 FormatDesc.FreeMappingData(DestMD);
7448 aStream.Write(Data^, Size);
7451 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7452 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7453 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7455 DDS_MAGIC: Cardinal = $20534444;
7457 // DDS_header.dwFlags
7458 DDSD_CAPS = $00000001;
7459 DDSD_HEIGHT = $00000002;
7460 DDSD_WIDTH = $00000004;
7461 DDSD_PIXELFORMAT = $00001000;
7463 // DDS_header.sPixelFormat.dwFlags
7464 DDPF_ALPHAPIXELS = $00000001;
7465 DDPF_ALPHA = $00000002;
7466 DDPF_FOURCC = $00000004;
7467 DDPF_RGB = $00000040;
7468 DDPF_LUMINANCE = $00020000;
7470 // DDS_header.sCaps.dwCaps1
7471 DDSCAPS_TEXTURE = $00001000;
7473 // DDS_header.sCaps.dwCaps2
7474 DDSCAPS2_CUBEMAP = $00000200;
7476 D3DFMT_DXT1 = $31545844;
7477 D3DFMT_DXT3 = $33545844;
7478 D3DFMT_DXT5 = $35545844;
7481 TDDSPixelFormat = packed record
7485 dwRGBBitCount: Cardinal;
7486 dwRBitMask: Cardinal;
7487 dwGBitMask: Cardinal;
7488 dwBBitMask: Cardinal;
7489 dwABitMask: Cardinal;
7492 TDDSCaps = packed record
7496 dwReserved: Cardinal;
7499 TDDSHeader = packed record
7504 dwPitchOrLinearSize: Cardinal;
7506 dwMipMapCount: Cardinal;
7507 dwReserved: array[0..10] of Cardinal;
7508 PixelFormat: TDDSPixelFormat;
7510 dwReserved2: Cardinal;
7513 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7514 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7517 Converter: TbmpBitfieldFormat;
7519 function GetDDSFormat: TglBitmapFormat;
7521 fd: TFormatDescriptor;
7523 Range: TglBitmapColorRec;
7527 with Header.PixelFormat do begin
7529 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7530 case Header.PixelFormat.dwFourCC of
7531 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7532 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7533 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7535 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7537 //find matching format
7538 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7539 fd := TFormatDescriptor.Get(result);
7540 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7541 (8 * fd.PixelSize = dwRGBBitCount) then
7545 //find format with same Range
7546 Range.r := dwRBitMask;
7547 Range.g := dwGBitMask;
7548 Range.b := dwBBitMask;
7549 Range.a := dwABitMask;
7550 for i := 0 to 3 do begin
7551 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7552 Range.arr[i] := Range.arr[i] shr 1;
7554 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7555 fd := TFormatDescriptor.Get(result);
7558 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7566 //no format with same range found -> use default
7567 if (result = tfEmpty) then begin
7568 if (dwABitMask > 0) then
7574 Converter := TbmpBitfieldFormat.Create;
7575 Converter.RedMask := dwRBitMask;
7576 Converter.GreenMask := dwGBitMask;
7577 Converter.BlueMask := dwBBitMask;
7578 Converter.AlphaMask := dwABitMask;
7579 Converter.PixelSize := dwRGBBitCount / 8;
7586 x, y, LineSize, RowSize, Magic: Cardinal;
7587 NewImage, TmpData, RowData, SrcData: System.PByte;
7588 SourceMD, DestMD: Pointer;
7589 Pixel: TglBitmapPixelData;
7590 ddsFormat: TglBitmapFormat;
7591 FormatDesc: TFormatDescriptor;
7596 StreamPos := aStream.Position;
7599 aStream.Read(Magic{%H-}, sizeof(Magic));
7600 if (Magic <> DDS_MAGIC) then begin
7601 aStream.Position := StreamPos;
7606 aStream.Read(Header{%H-}, sizeof(Header));
7607 if (Header.dwSize <> SizeOf(Header)) or
7608 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7609 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7611 aStream.Position := StreamPos;
7615 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7616 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
7618 ddsFormat := GetDDSFormat;
7620 if (ddsFormat = tfEmpty) then
7621 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7623 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7624 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7625 GetMem(NewImage, Header.dwHeight * LineSize);
7627 TmpData := NewImage;
7630 if Assigned(Converter) then begin
7631 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7632 GetMem(RowData, RowSize);
7633 SourceMD := Converter.CreateMappingData;
7634 DestMD := FormatDesc.CreateMappingData;
7636 for y := 0 to Header.dwHeight-1 do begin
7637 TmpData := NewImage;
7638 inc(TmpData, y * LineSize);
7640 aStream.Read(SrcData^, RowSize);
7641 for x := 0 to Header.dwWidth-1 do begin
7642 Converter.Unmap(SrcData, Pixel, SourceMD);
7643 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7644 FormatDesc.Map(Pixel, TmpData, DestMD);
7648 Converter.FreeMappingData(SourceMD);
7649 FormatDesc.FreeMappingData(DestMD);
7655 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7656 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7657 for Y := 0 to Header.dwHeight-1 do begin
7658 aStream.Read(TmpData^, RowSize);
7659 Inc(TmpData, LineSize);
7664 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7665 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7666 for Y := 0 to Header.dwHeight-1 do begin
7667 aStream.Read(TmpData^, RowSize);
7668 Inc(TmpData, LineSize);
7671 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7673 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method
7676 if Assigned(NewImage) then
7681 FreeAndNil(Converter);
7685 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7686 procedure TglBitmap.SaveDDS(const aStream: TStream);
7689 FormatDesc: TFormatDescriptor;
7691 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7692 raise EglBitmapUnsupportedFormat.Create(Format);
7694 FormatDesc := TFormatDescriptor.Get(Format);
7697 FillChar(Header{%H-}, SizeOf(Header), 0);
7698 Header.dwSize := SizeOf(Header);
7699 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7701 Header.dwWidth := Max(1, Width);
7702 Header.dwHeight := Max(1, Height);
7705 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7708 Header.PixelFormat.dwSize := sizeof(Header);
7709 if (FormatDesc.IsCompressed) then begin
7710 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7712 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7713 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7714 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7716 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7717 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7718 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7719 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7720 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7721 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7722 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7723 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7724 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7726 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7727 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7728 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7729 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7730 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7731 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7734 if (FormatDesc.HasAlpha) then
7735 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7737 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7738 aStream.Write(Header, SizeOf(Header));
7739 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7742 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7743 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7744 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7745 procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7746 const aWidth: Integer; const aHeight: Integer);
7751 if (aHeight > 1) then begin
7752 Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1);
7753 GetMem(pTemp, Size);
7755 Move(aData^, pTemp^, Size);
7764 inherited SetDataPointer(pTemp, aFormat, aWidth);
7767 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7768 function TglBitmap1D.FlipHorz: Boolean;
7771 pTempDest, pDest, pSource: PByte;
7773 result := inherited FlipHorz;
7774 if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin
7776 GetMem(pDest, fRowSize);
7779 Inc(pTempDest, fRowSize);
7780 for Col := 0 to Width-1 do begin
7781 dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data
7782 Move(pSource^, pTempDest^, fPixelSize);
7783 Inc(pSource, fPixelSize);
7785 SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method
7788 if Assigned(pDest) then
7795 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7796 procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean);
7798 FormatDesc: TFormatDescriptor;
7801 FormatDesc := TFormatDescriptor.Get(Format);
7802 if FormatDesc.IsCompressed then
7803 glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
7804 else if aBuildWithGlu then
7805 gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7807 glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7810 if (FreeDataAfterGenTexture) then
7814 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7815 procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean);
7817 BuildWithGlu, TexRec: Boolean;
7820 if Assigned(Data) then begin
7821 // Check Texture Size
7822 if (aTestTextureSize) then begin
7823 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7825 if (Width > TexSize) then
7826 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7828 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7829 (Target = GL_TEXTURE_RECTANGLE);
7830 if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7831 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7835 SetupParameters(BuildWithGlu);
7836 UploadData(BuildWithGlu);
7837 glAreTexturesResident(1, @fID, @fIsResident);
7841 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7842 procedure TglBitmap1D.AfterConstruction;
7845 Target := GL_TEXTURE_1D;
7848 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7849 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7850 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7851 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7853 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7854 result := fLines[aIndex]
7859 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7860 procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7861 const aWidth: Integer; const aHeight: Integer);
7863 Idx, LineWidth: Integer;
7865 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7867 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7869 if Assigned(Data) then begin
7870 SetLength(fLines, GetHeight);
7871 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7873 for Idx := 0 to GetHeight-1 do begin
7874 fLines[Idx] := Data;
7875 Inc(fLines[Idx], Idx * LineWidth);
7878 else SetLength(fLines, 0);
7880 SetLength(fLines, 0);
7884 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7885 procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
7887 FormatDesc: TFormatDescriptor;
7889 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7891 FormatDesc := TFormatDescriptor.Get(Format);
7892 if FormatDesc.IsCompressed then begin
7893 glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7894 end else if aBuildWithGlu then begin
7895 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7896 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7898 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7899 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7903 if (FreeDataAfterGenTexture) then
7907 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7908 procedure TglBitmap2D.AfterConstruction;
7911 Target := GL_TEXTURE_2D;
7914 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7915 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7918 Size, w, h: Integer;
7919 FormatDesc: TFormatDescriptor;
7921 FormatDesc := TFormatDescriptor.Get(aFormat);
7922 if FormatDesc.IsCompressed then
7923 raise EglBitmapUnsupportedFormat.Create(aFormat);
7925 w := aRight - aLeft;
7926 h := aBottom - aTop;
7927 Size := FormatDesc.GetSize(w, h);
7930 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7931 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7932 SetDataPointer(Temp, aFormat, w, h); //be careful, Data could be freed by this method
7935 if Assigned(Temp) then
7941 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7942 procedure TglBitmap2D.GetDataFromTexture;
7945 TempWidth, TempHeight: Integer;
7946 TempIntFormat: Cardinal;
7947 IntFormat, f: TglBitmapFormat;
7948 FormatDesc: TFormatDescriptor;
7953 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7954 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7955 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7957 IntFormat := tfEmpty;
7958 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
7959 FormatDesc := TFormatDescriptor.Get(f);
7960 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
7961 IntFormat := FormatDesc.Format;
7966 // Getting data from OpenGL
7967 FormatDesc := TFormatDescriptor.Get(IntFormat);
7968 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
7970 if FormatDesc.IsCompressed then
7971 glGetCompressedTexImage(Target, 0, Temp)
7973 glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
7974 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
7976 if Assigned(Temp) then
7982 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7983 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
7985 BuildWithGlu, PotTex, TexRec: Boolean;
7988 if Assigned(Data) then begin
7989 // Check Texture Size
7990 if (aTestTextureSize) then begin
7991 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7993 if ((Height > TexSize) or (Width > TexSize)) then
7994 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7996 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
7997 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
7998 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7999 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8003 SetupParameters(BuildWithGlu);
8004 UploadData(Target, BuildWithGlu);
8005 glAreTexturesResident(1, @fID, @fIsResident);
8009 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8010 function TglBitmap2D.FlipHorz: Boolean;
8013 TempDestData, DestData, SourceData: PByte;
8016 result := inherited FlipHorz;
8017 if Assigned(Data) then begin
8019 ImgSize := Height * fRowSize;
8020 GetMem(DestData, ImgSize);
8022 TempDestData := DestData;
8023 Dec(TempDestData, fRowSize + fPixelSize);
8024 for Row := 0 to Height -1 do begin
8025 Inc(TempDestData, fRowSize * 2);
8026 for Col := 0 to Width -1 do begin
8027 Move(SourceData^, TempDestData^, fPixelSize);
8028 Inc(SourceData, fPixelSize);
8029 Dec(TempDestData, fPixelSize);
8032 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8035 if Assigned(DestData) then
8042 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8043 function TglBitmap2D.FlipVert: Boolean;
8046 TempDestData, DestData, SourceData: PByte;
8048 result := inherited FlipVert;
8049 if Assigned(Data) then begin
8051 GetMem(DestData, Height * fRowSize);
8053 TempDestData := DestData;
8054 Inc(TempDestData, Width * (Height -1) * fPixelSize);
8055 for Row := 0 to Height -1 do begin
8056 Move(SourceData^, TempDestData^, fRowSize);
8057 Dec(TempDestData, fRowSize);
8058 Inc(SourceData, fRowSize);
8060 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8063 if Assigned(DestData) then
8070 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8071 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8072 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8074 TMatrixItem = record
8079 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
8080 TglBitmapToNormalMapRec = Record
8082 Heights: array of Single;
8083 MatrixU : array of TMatrixItem;
8084 MatrixV : array of TMatrixItem;
8088 ONE_OVER_255 = 1 / 255;
8090 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8091 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
8095 with FuncRec do begin
8097 Source.Data.r * LUMINANCE_WEIGHT_R +
8098 Source.Data.g * LUMINANCE_WEIGHT_G +
8099 Source.Data.b * LUMINANCE_WEIGHT_B;
8100 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
8104 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8105 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
8108 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
8111 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8112 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
8114 TVec = Array[0..2] of Single;
8121 function GetHeight(X, Y: Integer): Single;
8123 with FuncRec do begin
8124 X := Max(0, Min(Size.X -1, X));
8125 Y := Max(0, Min(Size.Y -1, Y));
8126 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
8131 with FuncRec do begin
8132 with PglBitmapToNormalMapRec(Args)^ do begin
8134 for Idx := Low(MatrixU) to High(MatrixU) do
8135 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
8138 for Idx := Low(MatrixU) to High(MatrixU) do
8139 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
8141 Vec[0] := -du * Scale;
8142 Vec[1] := -dv * Scale;
8147 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8148 if Len <> 0 then begin
8149 Vec[0] := Vec[0] * Len;
8150 Vec[1] := Vec[1] * Len;
8151 Vec[2] := Vec[2] * Len;
8155 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
8156 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
8157 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
8161 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8162 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
8164 Rec: TglBitmapToNormalMapRec;
8166 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
8168 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
8169 Matrix[Index].X := X;
8170 Matrix[Index].Y := Y;
8171 Matrix[Index].W := W;
8176 if TFormatDescriptor.Get(Format).IsCompressed then
8177 raise EglBitmapUnsupportedFormat.Create(Format);
8179 if aScale > 100 then
8181 else if aScale < -100 then
8184 Rec.Scale := aScale;
8186 SetLength(Rec.Heights, Width * Height);
8190 SetLength(Rec.MatrixU, 2);
8191 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
8192 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
8194 SetLength(Rec.MatrixV, 2);
8195 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
8196 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
8200 SetLength(Rec.MatrixU, 6);
8201 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
8202 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
8203 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
8204 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
8205 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
8206 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
8208 SetLength(Rec.MatrixV, 6);
8209 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
8210 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
8211 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
8212 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
8213 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
8214 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
8218 SetLength(Rec.MatrixU, 6);
8219 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
8220 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
8221 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
8222 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
8223 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
8224 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
8226 SetLength(Rec.MatrixV, 6);
8227 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
8228 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
8229 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
8230 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
8231 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
8232 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
8236 SetLength(Rec.MatrixU, 20);
8237 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
8238 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
8239 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
8240 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
8241 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
8242 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
8243 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
8244 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
8245 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
8246 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
8247 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
8248 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
8249 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
8250 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
8251 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
8252 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
8253 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
8254 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
8255 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
8256 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
8258 SetLength(Rec.MatrixV, 20);
8259 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
8260 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
8261 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
8262 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
8263 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
8264 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
8265 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
8266 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
8267 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
8268 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
8269 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
8270 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
8271 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
8272 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
8273 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
8274 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
8275 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
8276 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
8277 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
8278 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
8283 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
8284 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
8286 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
8287 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
8289 SetLength(Rec.Heights, 0);
8293 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8294 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8295 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8296 procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean);
8298 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8301 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8302 procedure TglBitmapCubeMap.AfterConstruction;
8306 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8307 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8310 Target := GL_TEXTURE_CUBE_MAP;
8311 fGenMode := GL_REFLECTION_MAP;
8314 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8315 procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean);
8317 BuildWithGlu: Boolean;
8320 if (aTestTextureSize) then begin
8321 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8323 if (Height > TexSize) or (Width > TexSize) then
8324 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8326 if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8327 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8332 SetupParameters(BuildWithGlu);
8333 UploadData(aCubeTarget, BuildWithGlu);
8336 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8337 procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean);
8339 inherited Bind (aEnableTextureUnit);
8340 if aEnableTexCoordsGen then begin
8341 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8342 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8343 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8344 glEnable(GL_TEXTURE_GEN_S);
8345 glEnable(GL_TEXTURE_GEN_T);
8346 glEnable(GL_TEXTURE_GEN_R);
8350 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8351 procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean);
8353 inherited Unbind(aDisableTextureUnit);
8354 if aDisableTexCoordsGen then begin
8355 glDisable(GL_TEXTURE_GEN_S);
8356 glDisable(GL_TEXTURE_GEN_T);
8357 glDisable(GL_TEXTURE_GEN_R);
8361 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8362 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8363 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8365 TVec = Array[0..2] of Single;
8366 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8368 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8369 TglBitmapNormalMapRec = record
8371 Func: TglBitmapNormalMapGetVectorFunc;
8374 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8375 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8377 aVec[0] := aHalfSize;
8378 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8379 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8382 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8383 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8385 aVec[0] := - aHalfSize;
8386 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8387 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8390 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8391 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8393 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8394 aVec[1] := aHalfSize;
8395 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8398 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8399 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8401 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8402 aVec[1] := - aHalfSize;
8403 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8406 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8407 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8409 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8410 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8411 aVec[2] := aHalfSize;
8414 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8415 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8417 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8418 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8419 aVec[2] := - aHalfSize;
8422 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8423 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8429 with FuncRec do begin
8430 with PglBitmapNormalMapRec(Args)^ do begin
8431 Func(Vec, Position, HalfSize);
8434 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8435 if Len <> 0 then begin
8436 Vec[0] := Vec[0] * Len;
8437 Vec[1] := Vec[1] * Len;
8438 Vec[2] := Vec[2] * Len;
8441 // Scale Vector and AddVectro
8442 Vec[0] := Vec[0] * 0.5 + 0.5;
8443 Vec[1] := Vec[1] * 0.5 + 0.5;
8444 Vec[2] := Vec[2] * 0.5 + 0.5;
8449 Dest.Data.arr[i] := Round(Vec[i] * 255);
8453 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8454 procedure TglBitmapNormalMap.AfterConstruction;
8457 fGenMode := GL_NORMAL_MAP;
8460 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8461 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean);
8463 Rec: TglBitmapNormalMapRec;
8464 SizeRec: TglBitmapPixelPosition;
8466 Rec.HalfSize := aSize div 2;
8467 FreeDataAfterGenTexture := false;
8469 SizeRec.Fields := [ffX, ffY];
8474 Rec.Func := glBitmapNormalMapPosX;
8475 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8476 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize);
8479 Rec.Func := glBitmapNormalMapNegX;
8480 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8481 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize);
8484 Rec.Func := glBitmapNormalMapPosY;
8485 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8486 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize);
8489 Rec.Func := glBitmapNormalMapNegY;
8490 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8491 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize);
8494 Rec.Func := glBitmapNormalMapPosZ;
8495 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8496 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize);
8499 Rec.Func := glBitmapNormalMapNegZ;
8500 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8501 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize);
8506 glBitmapSetDefaultFormat (tfEmpty);
8507 glBitmapSetDefaultMipmap (mmMipmap);
8508 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8509 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8510 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8512 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8513 glBitmapSetDefaultDeleteTextureOnFree (true);
8515 TFormatDescriptor.Init;
8517 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8518 OpenGLInitialized := false;
8519 InitOpenGLCS := TCriticalSection.Create;
8523 TFormatDescriptor.Finalize;
8525 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8526 FreeAndNil(InitOpenGLCS);