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: PAnsiChar; aLibHandle: Pointer = nil; const aRaiseOnErr: Boolean = true): 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) and aRaiseOnErr 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);
2028 {$IF DEFINED(GLB_WIN)}
2029 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
2030 {$ELSEIF DEFINED(GLB_LINUX)}
2031 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
2032 glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
2035 glEnable := glbGetProcAddress('glEnable');
2036 glDisable := glbGetProcAddress('glDisable');
2037 glGetString := glbGetProcAddress('glGetString');
2038 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
2039 glTexParameteri := glbGetProcAddress('glTexParameteri');
2040 glTexParameteriv := glbGetProcAddress('glTexParameteriv');
2041 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
2042 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
2043 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
2044 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
2045 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
2046 glTexGeni := glbGetProcAddress('glTexGeni');
2047 glGenTextures := glbGetProcAddress('glGenTextures');
2048 glBindTexture := glbGetProcAddress('glBindTexture');
2049 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
2050 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
2051 glReadPixels := glbGetProcAddress('glReadPixels');
2052 glPixelStorei := glbGetProcAddress('glPixelStorei');
2053 glTexImage1D := glbGetProcAddress('glTexImage1D');
2054 glTexImage2D := glbGetProcAddress('glTexImage2D');
2055 glGetTexImage := glbGetProcAddress('glGetTexImage');
2057 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
2058 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
2062 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2063 procedure glbReadOpenGLExtensions;
2066 MajorVersion, MinorVersion: Integer;
2068 ///////////////////////////////////////////////////////////////////////////////////////////
2069 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
2076 Separator := Pos(AnsiString('.'), aBuffer);
2077 if (Separator > 1) and (Separator < Length(aBuffer)) and
2078 (aBuffer[Separator - 1] in ['0'..'9']) and
2079 (aBuffer[Separator + 1] in ['0'..'9']) then begin
2082 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
2085 Delete(aBuffer, 1, Separator);
2086 Separator := Pos(AnsiString('.'), aBuffer) + 1;
2088 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
2091 Delete(aBuffer, Separator, 255);
2092 Separator := Pos(AnsiString('.'), aBuffer);
2094 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
2095 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2099 ///////////////////////////////////////////////////////////////////////////////////////////
2100 function CheckExtension(const Extension: AnsiString): Boolean;
2104 ExtPos := Pos(Extension, Buffer);
2105 result := ExtPos > 0;
2107 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2110 ///////////////////////////////////////////////////////////////////////////////////////////
2111 function CheckVersion(const aMajor, aMinor: Integer): Boolean;
2113 result := (MajorVersion > aMajor) or ((MajorVersion = aMajor) and (MinorVersion >= aMinor));
2117 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2120 if not OpenGLInitialized then begin
2122 OpenGLInitialized := true;
2130 Buffer := glGetString(GL_VERSION);
2131 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2133 GL_VERSION_1_2 := CheckVersion(1, 2);
2134 GL_VERSION_1_3 := CheckVersion(1, 3);
2135 GL_VERSION_1_4 := CheckVersion(1, 4);
2136 GL_VERSION_2_0 := CheckVersion(2, 0);
2137 GL_VERSION_3_3 := CheckVersion(3, 3);
2140 Buffer := glGetString(GL_EXTENSIONS);
2141 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2142 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2143 GL_ARB_texture_swizzle := CheckExtension('GL_ARB_texture_swizzle');
2144 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
2145 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2146 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2147 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2148 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2149 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2150 GL_EXT_texture_swizzle := CheckExtension('GL_EXT_texture_swizzle');
2151 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
2152 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2153 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2154 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2156 if GL_VERSION_1_3 then begin
2157 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2158 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2159 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2161 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB', nil, false);
2162 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB', nil, false);
2163 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB', nil, false);
2168 {$IFDEF GLB_SDL_IMAGE}
2169 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2170 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2171 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2172 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2174 result := TStream(context^.unknown.data1).Seek(offset, whence);
2177 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2179 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2182 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2184 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2187 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2192 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2194 result := SDL_AllocRW;
2196 if result = nil then
2197 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2199 result^.seek := glBitmapRWseek;
2200 result^.read := glBitmapRWread;
2201 result^.write := glBitmapRWwrite;
2202 result^.close := glBitmapRWclose;
2203 result^.unknown.data1 := Stream;
2207 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2208 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2210 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2213 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2214 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2216 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2219 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2220 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2222 glBitmapDefaultMipmap := aValue;
2225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2226 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2228 glBitmapDefaultFormat := aFormat;
2231 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2232 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2234 glBitmapDefaultFilterMin := aMin;
2235 glBitmapDefaultFilterMag := aMag;
2238 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2239 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2241 glBitmapDefaultWrapS := S;
2242 glBitmapDefaultWrapT := T;
2243 glBitmapDefaultWrapR := R;
2246 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2247 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
2249 glDefaultSwizzle[0] := r;
2250 glDefaultSwizzle[1] := g;
2251 glDefaultSwizzle[2] := b;
2252 glDefaultSwizzle[3] := a;
2255 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2256 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2258 result := glBitmapDefaultDeleteTextureOnFree;
2261 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2262 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2264 result := glBitmapDefaultFreeDataAfterGenTextures;
2267 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2268 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2270 result := glBitmapDefaultMipmap;
2273 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2274 function glBitmapGetDefaultFormat: TglBitmapFormat;
2276 result := glBitmapDefaultFormat;
2279 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2280 procedure glBitmapGetDefaultFilter(var aMin, aMag: GLenum);
2282 aMin := glBitmapDefaultFilterMin;
2283 aMag := glBitmapDefaultFilterMag;
2286 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2287 procedure glBitmapGetDefaultTextureWrap(var S, T, R: GLenum);
2289 S := glBitmapDefaultWrapS;
2290 T := glBitmapDefaultWrapT;
2291 R := glBitmapDefaultWrapR;
2294 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2295 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
2297 r := glDefaultSwizzle[0];
2298 g := glDefaultSwizzle[1];
2299 b := glDefaultSwizzle[2];
2300 a := glDefaultSwizzle[3];
2303 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2304 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2305 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2306 function TFormatDescriptor.GetRedMask: QWord;
2308 result := fRange.r shl fShift.r;
2311 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2312 function TFormatDescriptor.GetGreenMask: QWord;
2314 result := fRange.g shl fShift.g;
2317 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2318 function TFormatDescriptor.GetBlueMask: QWord;
2320 result := fRange.b shl fShift.b;
2323 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2324 function TFormatDescriptor.GetAlphaMask: QWord;
2326 result := fRange.a shl fShift.a;
2329 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2330 function TFormatDescriptor.GetIsCompressed: Boolean;
2332 result := fIsCompressed;
2335 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2336 function TFormatDescriptor.GetHasAlpha: Boolean;
2338 result := (fRange.a > 0);
2341 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2342 function TFormatDescriptor.GetglFormat: GLenum;
2344 result := fglFormat;
2347 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2348 function TFormatDescriptor.GetglInternalFormat: GLenum;
2350 result := fglInternalFormat;
2353 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2354 function TFormatDescriptor.GetglDataFormat: GLenum;
2356 result := fglDataFormat;
2359 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2360 function TFormatDescriptor.GetComponents: Integer;
2366 if (fRange.arr[i] > 0) then
2370 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2371 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2375 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2376 w := Max(1, aSize.X);
2377 h := Max(1, aSize.Y);
2378 result := GetSize(w, h);
2383 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2384 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2387 if (aWidth <= 0) or (aHeight <= 0) then
2389 result := Ceil(aWidth * aHeight * fPixelSize);
2392 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2393 function TFormatDescriptor.CreateMappingData: Pointer;
2398 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2399 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2404 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2405 function TFormatDescriptor.IsEmpty: Boolean;
2407 result := (fFormat = tfEmpty);
2410 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2411 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2414 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2415 raise EglBitmap.Create('FormatCheckFormat - All Masks are 0');
2416 if (aRedMask <> RedMask) then
2418 if (aGreenMask <> GreenMask) then
2420 if (aBlueMask <> BlueMask) then
2422 if (aAlphaMask <> AlphaMask) then
2427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2428 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2430 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2431 aPixel.Data := fRange;
2432 aPixel.Range := fRange;
2433 aPixel.Format := fFormat;
2436 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2437 constructor TFormatDescriptor.Create;
2442 fWithAlpha := tfEmpty;
2443 fWithoutAlpha := tfEmpty;
2444 fRGBInverted := tfEmpty;
2445 fUncompressed := tfEmpty;
2447 fIsCompressed := false;
2450 fglInternalFormat := 0;
2453 FillChar(fRange, 0, SizeOf(fRange));
2454 FillChar(fShift, 0, SizeOf(fShift));
2457 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2458 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2459 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2460 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2462 aData^ := aPixel.Data.a;
2466 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2471 aPixel.Data.a := aData^;
2475 constructor TfdAlpha_UB1.Create;
2480 fglFormat := GL_ALPHA;
2481 fglDataFormat := GL_UNSIGNED_BYTE;
2484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2485 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2486 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2487 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2489 aData^ := LuminanceWeight(aPixel);
2493 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2495 aPixel.Data.r := aData^;
2496 aPixel.Data.g := aData^;
2497 aPixel.Data.b := aData^;
2502 constructor TfdLuminance_UB1.Create;
2509 fglFormat := GL_LUMINANCE;
2510 fglDataFormat := GL_UNSIGNED_BYTE;
2513 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2514 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2515 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2516 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2522 if (fRange.arr[i] > 0) then
2523 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2527 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2532 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2536 constructor TfdUniversal_UB1.Create;
2542 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2543 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2544 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2545 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2547 inherited Map(aPixel, aData, aMapData);
2548 aData^ := aPixel.Data.a;
2552 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2554 inherited Unmap(aData, aPixel, aMapData);
2555 aPixel.Data.a := aData^;
2559 constructor TfdLuminanceAlpha_UB2.Create;
2565 fglFormat := GL_LUMINANCE_ALPHA;
2566 fglDataFormat := GL_UNSIGNED_BYTE;
2569 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2570 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2571 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2572 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2574 aData^ := aPixel.Data.r;
2576 aData^ := aPixel.Data.g;
2578 aData^ := aPixel.Data.b;
2582 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2584 aPixel.Data.r := aData^;
2586 aPixel.Data.g := aData^;
2588 aPixel.Data.b := aData^;
2593 constructor TfdRGB_UB3.Create;
2603 fglFormat := GL_RGB;
2604 fglDataFormat := GL_UNSIGNED_BYTE;
2607 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2608 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2609 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2610 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2612 aData^ := aPixel.Data.b;
2614 aData^ := aPixel.Data.g;
2616 aData^ := aPixel.Data.r;
2620 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2622 aPixel.Data.b := aData^;
2624 aPixel.Data.g := aData^;
2626 aPixel.Data.r := aData^;
2631 constructor TfdBGR_UB3.Create;
2640 fglFormat := GL_BGR;
2641 fglDataFormat := GL_UNSIGNED_BYTE;
2644 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2645 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2646 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2647 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2649 inherited Map(aPixel, aData, aMapData);
2650 aData^ := aPixel.Data.a;
2654 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2656 inherited Unmap(aData, aPixel, aMapData);
2657 aPixel.Data.a := aData^;
2661 constructor TfdRGBA_UB4.Create;
2667 fglFormat := GL_RGBA;
2668 fglDataFormat := GL_UNSIGNED_BYTE;
2671 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2672 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2673 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2674 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2676 inherited Map(aPixel, aData, aMapData);
2677 aData^ := aPixel.Data.a;
2681 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2683 inherited Unmap(aData, aPixel, aMapData);
2684 aPixel.Data.a := aData^;
2688 constructor TfdBGRA_UB4.Create;
2694 fglFormat := GL_BGRA;
2695 fglDataFormat := GL_UNSIGNED_BYTE;
2698 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2699 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2700 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2701 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2703 PWord(aData)^ := aPixel.Data.a;
2707 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2712 aPixel.Data.a := PWord(aData)^;
2716 constructor TfdAlpha_US1.Create;
2721 fglFormat := GL_ALPHA;
2722 fglDataFormat := GL_UNSIGNED_SHORT;
2725 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2726 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2727 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2728 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2730 PWord(aData)^ := LuminanceWeight(aPixel);
2734 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2736 aPixel.Data.r := PWord(aData)^;
2737 aPixel.Data.g := PWord(aData)^;
2738 aPixel.Data.b := PWord(aData)^;
2743 constructor TfdLuminance_US1.Create;
2750 fglFormat := GL_LUMINANCE;
2751 fglDataFormat := GL_UNSIGNED_SHORT;
2754 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2755 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2756 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2757 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2763 if (fRange.arr[i] > 0) then
2764 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2768 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2773 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2777 constructor TfdUniversal_US1.Create;
2783 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2784 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2785 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2786 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2788 PWord(aData)^ := DepthWeight(aPixel);
2792 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2794 aPixel.Data.r := PWord(aData)^;
2795 aPixel.Data.g := PWord(aData)^;
2796 aPixel.Data.b := PWord(aData)^;
2801 constructor TfdDepth_US1.Create;
2808 fglFormat := GL_DEPTH_COMPONENT;
2809 fglDataFormat := GL_UNSIGNED_SHORT;
2812 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2813 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2814 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2815 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2817 inherited Map(aPixel, aData, aMapData);
2818 PWord(aData)^ := aPixel.Data.a;
2822 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2824 inherited Unmap(aData, aPixel, aMapData);
2825 aPixel.Data.a := PWord(aData)^;
2829 constructor TfdLuminanceAlpha_US2.Create;
2835 fglFormat := GL_LUMINANCE_ALPHA;
2836 fglDataFormat := GL_UNSIGNED_SHORT;
2839 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2840 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2841 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2842 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2844 PWord(aData)^ := aPixel.Data.r;
2846 PWord(aData)^ := aPixel.Data.g;
2848 PWord(aData)^ := aPixel.Data.b;
2852 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2854 aPixel.Data.r := PWord(aData)^;
2856 aPixel.Data.g := PWord(aData)^;
2858 aPixel.Data.b := PWord(aData)^;
2863 constructor TfdRGB_US3.Create;
2873 fglFormat := GL_RGB;
2874 fglDataFormat := GL_UNSIGNED_SHORT;
2877 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2878 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2879 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2880 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2882 PWord(aData)^ := aPixel.Data.b;
2884 PWord(aData)^ := aPixel.Data.g;
2886 PWord(aData)^ := aPixel.Data.r;
2890 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2892 aPixel.Data.b := PWord(aData)^;
2894 aPixel.Data.g := PWord(aData)^;
2896 aPixel.Data.r := PWord(aData)^;
2901 constructor TfdBGR_US3.Create;
2911 fglFormat := GL_BGR;
2912 fglDataFormat := GL_UNSIGNED_SHORT;
2915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2916 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2917 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2918 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2920 inherited Map(aPixel, aData, aMapData);
2921 PWord(aData)^ := aPixel.Data.a;
2925 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2927 inherited Unmap(aData, aPixel, aMapData);
2928 aPixel.Data.a := PWord(aData)^;
2932 constructor TfdRGBA_US4.Create;
2938 fglFormat := GL_RGBA;
2939 fglDataFormat := GL_UNSIGNED_SHORT;
2942 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2943 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2944 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2945 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2947 inherited Map(aPixel, aData, aMapData);
2948 PWord(aData)^ := aPixel.Data.a;
2952 procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2954 inherited Unmap(aData, aPixel, aMapData);
2955 aPixel.Data.a := PWord(aData)^;
2959 constructor TfdBGRA_US4.Create;
2965 fglFormat := GL_BGRA;
2966 fglDataFormat := GL_UNSIGNED_SHORT;
2969 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2970 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2971 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2972 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2976 PCardinal(aData)^ := 0;
2978 if (fRange.arr[i] > 0) then
2979 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2983 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2988 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2992 constructor TfdUniversal_UI1.Create;
2998 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2999 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3001 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3003 PCardinal(aData)^ := DepthWeight(aPixel);
3007 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3009 aPixel.Data.r := PCardinal(aData)^;
3010 aPixel.Data.g := PCardinal(aData)^;
3011 aPixel.Data.b := PCardinal(aData)^;
3016 constructor TfdDepth_UI1.Create;
3020 fRange.r := $FFFFFFFF;
3021 fRange.g := $FFFFFFFF;
3022 fRange.b := $FFFFFFFF;
3023 fglFormat := GL_DEPTH_COMPONENT;
3024 fglDataFormat := GL_UNSIGNED_INT;
3027 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3028 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3029 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3030 constructor TfdAlpha4.Create;
3033 fFormat := tfAlpha4;
3034 fWithAlpha := tfAlpha4;
3035 fglInternalFormat := GL_ALPHA4;
3038 constructor TfdAlpha8.Create;
3041 fFormat := tfAlpha8;
3042 fWithAlpha := tfAlpha8;
3043 fglInternalFormat := GL_ALPHA8;
3046 constructor TfdAlpha12.Create;
3049 fFormat := tfAlpha12;
3050 fWithAlpha := tfAlpha12;
3051 fglInternalFormat := GL_ALPHA12;
3054 constructor TfdAlpha16.Create;
3057 fFormat := tfAlpha16;
3058 fWithAlpha := tfAlpha16;
3059 fglInternalFormat := GL_ALPHA16;
3062 constructor TfdLuminance4.Create;
3065 fFormat := tfLuminance4;
3066 fWithAlpha := tfLuminance4Alpha4;
3067 fWithoutAlpha := tfLuminance4;
3068 fglInternalFormat := GL_LUMINANCE4;
3071 constructor TfdLuminance8.Create;
3074 fFormat := tfLuminance8;
3075 fWithAlpha := tfLuminance8Alpha8;
3076 fWithoutAlpha := tfLuminance8;
3077 fglInternalFormat := GL_LUMINANCE8;
3080 constructor TfdLuminance12.Create;
3083 fFormat := tfLuminance12;
3084 fWithAlpha := tfLuminance12Alpha12;
3085 fWithoutAlpha := tfLuminance12;
3086 fglInternalFormat := GL_LUMINANCE12;
3089 constructor TfdLuminance16.Create;
3092 fFormat := tfLuminance16;
3093 fWithAlpha := tfLuminance16Alpha16;
3094 fWithoutAlpha := tfLuminance16;
3095 fglInternalFormat := GL_LUMINANCE16;
3098 constructor TfdLuminance4Alpha4.Create;
3101 fFormat := tfLuminance4Alpha4;
3102 fWithAlpha := tfLuminance4Alpha4;
3103 fWithoutAlpha := tfLuminance4;
3104 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3107 constructor TfdLuminance6Alpha2.Create;
3110 fFormat := tfLuminance6Alpha2;
3111 fWithAlpha := tfLuminance6Alpha2;
3112 fWithoutAlpha := tfLuminance8;
3113 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3116 constructor TfdLuminance8Alpha8.Create;
3119 fFormat := tfLuminance8Alpha8;
3120 fWithAlpha := tfLuminance8Alpha8;
3121 fWithoutAlpha := tfLuminance8;
3122 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3125 constructor TfdLuminance12Alpha4.Create;
3128 fFormat := tfLuminance12Alpha4;
3129 fWithAlpha := tfLuminance12Alpha4;
3130 fWithoutAlpha := tfLuminance12;
3131 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3134 constructor TfdLuminance12Alpha12.Create;
3137 fFormat := tfLuminance12Alpha12;
3138 fWithAlpha := tfLuminance12Alpha12;
3139 fWithoutAlpha := tfLuminance12;
3140 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3143 constructor TfdLuminance16Alpha16.Create;
3146 fFormat := tfLuminance16Alpha16;
3147 fWithAlpha := tfLuminance16Alpha16;
3148 fWithoutAlpha := tfLuminance16;
3149 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3152 constructor TfdR3G3B2.Create;
3155 fFormat := tfR3G3B2;
3156 fWithAlpha := tfRGBA2;
3157 fWithoutAlpha := tfR3G3B2;
3164 fglFormat := GL_RGB;
3165 fglInternalFormat := GL_R3_G3_B2;
3166 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3169 constructor TfdRGB4.Create;
3173 fWithAlpha := tfRGBA4;
3174 fWithoutAlpha := tfRGB4;
3175 fRGBInverted := tfBGR4;
3182 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3183 fglInternalFormat := GL_RGB4;
3184 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3187 constructor TfdR5G6B5.Create;
3190 fFormat := tfR5G6B5;
3191 fWithAlpha := tfRGBA4;
3192 fWithoutAlpha := tfR5G6B5;
3193 fRGBInverted := tfB5G6R5;
3200 fglFormat := GL_RGB;
3201 fglInternalFormat := GL_RGB565;
3202 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3205 constructor TfdRGB5.Create;
3209 fWithAlpha := tfRGB5A1;
3210 fWithoutAlpha := tfRGB5;
3211 fRGBInverted := tfBGR5;
3218 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3219 fglInternalFormat := GL_RGB5;
3220 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3223 constructor TfdRGB8.Create;
3227 fWithAlpha := tfRGBA8;
3228 fWithoutAlpha := tfRGB8;
3229 fRGBInverted := tfBGR8;
3230 fglInternalFormat := GL_RGB8;
3233 constructor TfdRGB10.Create;
3237 fWithAlpha := tfRGB10A2;
3238 fWithoutAlpha := tfRGB10;
3239 fRGBInverted := tfBGR10;
3246 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3247 fglInternalFormat := GL_RGB10;
3248 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3251 constructor TfdRGB12.Create;
3255 fWithAlpha := tfRGBA12;
3256 fWithoutAlpha := tfRGB12;
3257 fRGBInverted := tfBGR12;
3258 fglInternalFormat := GL_RGB12;
3261 constructor TfdRGB16.Create;
3265 fWithAlpha := tfRGBA16;
3266 fWithoutAlpha := tfRGB16;
3267 fRGBInverted := tfBGR16;
3268 fglInternalFormat := GL_RGB16;
3271 constructor TfdRGBA2.Create;
3275 fWithAlpha := tfRGBA2;
3276 fWithoutAlpha := tfR3G3B2;
3277 fRGBInverted := tfBGRA2;
3278 fglInternalFormat := GL_RGBA2;
3281 constructor TfdRGBA4.Create;
3285 fWithAlpha := tfRGBA4;
3286 fWithoutAlpha := tfRGB4;
3287 fRGBInverted := tfBGRA4;
3296 fglFormat := GL_RGBA;
3297 fglInternalFormat := GL_RGBA4;
3298 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3301 constructor TfdRGB5A1.Create;
3304 fFormat := tfRGB5A1;
3305 fWithAlpha := tfRGB5A1;
3306 fWithoutAlpha := tfRGB5;
3307 fRGBInverted := tfBGR5A1;
3316 fglFormat := GL_RGBA;
3317 fglInternalFormat := GL_RGB5_A1;
3318 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3321 constructor TfdRGBA8.Create;
3325 fWithAlpha := tfRGBA8;
3326 fWithoutAlpha := tfRGB8;
3327 fRGBInverted := tfBGRA8;
3328 fglInternalFormat := GL_RGBA8;
3331 constructor TfdRGB10A2.Create;
3334 fFormat := tfRGB10A2;
3335 fWithAlpha := tfRGB10A2;
3336 fWithoutAlpha := tfRGB10;
3337 fRGBInverted := tfBGR10A2;
3346 fglFormat := GL_RGBA;
3347 fglInternalFormat := GL_RGB10_A2;
3348 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3351 constructor TfdRGBA12.Create;
3354 fFormat := tfRGBA12;
3355 fWithAlpha := tfRGBA12;
3356 fWithoutAlpha := tfRGB12;
3357 fRGBInverted := tfBGRA12;
3358 fglInternalFormat := GL_RGBA12;
3361 constructor TfdRGBA16.Create;
3364 fFormat := tfRGBA16;
3365 fWithAlpha := tfRGBA16;
3366 fWithoutAlpha := tfRGB16;
3367 fRGBInverted := tfBGRA16;
3368 fglInternalFormat := GL_RGBA16;
3371 constructor TfdBGR4.Create;
3376 fWithAlpha := tfBGRA4;
3377 fWithoutAlpha := tfBGR4;
3378 fRGBInverted := tfRGB4;
3387 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3388 fglInternalFormat := GL_RGB4;
3389 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3392 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3393 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3394 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3395 constructor TfdB5G6R5.Create;
3398 fFormat := tfB5G6R5;
3399 fWithAlpha := tfBGRA4;
3400 fWithoutAlpha := tfB5G6R5;
3401 fRGBInverted := tfR5G6B5;
3408 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3409 fglInternalFormat := GL_RGB8;
3410 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3413 constructor TfdBGR5.Create;
3418 fWithAlpha := tfBGR5A1;
3419 fWithoutAlpha := tfBGR5;
3420 fRGBInverted := tfRGB5;
3429 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3430 fglInternalFormat := GL_RGB5;
3431 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3434 constructor TfdBGR8.Create;
3438 fWithAlpha := tfBGRA8;
3439 fWithoutAlpha := tfBGR8;
3440 fRGBInverted := tfRGB8;
3441 fglInternalFormat := GL_RGB8;
3444 constructor TfdBGR10.Create;
3448 fWithAlpha := tfBGR10A2;
3449 fWithoutAlpha := tfBGR10;
3450 fRGBInverted := tfRGB10;
3459 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3460 fglInternalFormat := GL_RGB10;
3461 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3464 constructor TfdBGR12.Create;
3468 fWithAlpha := tfBGRA12;
3469 fWithoutAlpha := tfBGR12;
3470 fRGBInverted := tfRGB12;
3471 fglInternalFormat := GL_RGB12;
3474 constructor TfdBGR16.Create;
3478 fWithAlpha := tfBGRA16;
3479 fWithoutAlpha := tfBGR16;
3480 fRGBInverted := tfRGB16;
3481 fglInternalFormat := GL_RGB16;
3484 constructor TfdBGRA2.Create;
3488 fWithAlpha := tfBGRA4;
3489 fWithoutAlpha := tfBGR4;
3490 fRGBInverted := tfRGBA2;
3491 fglInternalFormat := GL_RGBA2;
3494 constructor TfdBGRA4.Create;
3498 fWithAlpha := tfBGRA4;
3499 fWithoutAlpha := tfBGR4;
3500 fRGBInverted := tfRGBA4;
3509 fglFormat := GL_BGRA;
3510 fglInternalFormat := GL_RGBA4;
3511 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3514 constructor TfdBGR5A1.Create;
3517 fFormat := tfBGR5A1;
3518 fWithAlpha := tfBGR5A1;
3519 fWithoutAlpha := tfBGR5;
3520 fRGBInverted := tfRGB5A1;
3529 fglFormat := GL_BGRA;
3530 fglInternalFormat := GL_RGB5_A1;
3531 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3534 constructor TfdBGRA8.Create;
3538 fWithAlpha := tfBGRA8;
3539 fWithoutAlpha := tfBGR8;
3540 fRGBInverted := tfRGBA8;
3541 fglInternalFormat := GL_RGBA8;
3544 constructor TfdBGR10A2.Create;
3547 fFormat := tfBGR10A2;
3548 fWithAlpha := tfBGR10A2;
3549 fWithoutAlpha := tfBGR10;
3550 fRGBInverted := tfRGB10A2;
3559 fglFormat := GL_BGRA;
3560 fglInternalFormat := GL_RGB10_A2;
3561 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3564 constructor TfdBGRA12.Create;
3567 fFormat := tfBGRA12;
3568 fWithAlpha := tfBGRA12;
3569 fWithoutAlpha := tfBGR12;
3570 fRGBInverted := tfRGBA12;
3571 fglInternalFormat := GL_RGBA12;
3574 constructor TfdBGRA16.Create;
3577 fFormat := tfBGRA16;
3578 fWithAlpha := tfBGRA16;
3579 fWithoutAlpha := tfBGR16;
3580 fRGBInverted := tfRGBA16;
3581 fglInternalFormat := GL_RGBA16;
3584 constructor TfdDepth16.Create;
3587 fFormat := tfDepth16;
3588 fWithAlpha := tfEmpty;
3589 fWithoutAlpha := tfDepth16;
3590 fglInternalFormat := GL_DEPTH_COMPONENT16;
3593 constructor TfdDepth24.Create;
3596 fFormat := tfDepth24;
3597 fWithAlpha := tfEmpty;
3598 fWithoutAlpha := tfDepth24;
3599 fglInternalFormat := GL_DEPTH_COMPONENT24;
3602 constructor TfdDepth32.Create;
3605 fFormat := tfDepth32;
3606 fWithAlpha := tfEmpty;
3607 fWithoutAlpha := tfDepth32;
3608 fglInternalFormat := GL_DEPTH_COMPONENT32;
3611 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3612 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3613 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3614 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3616 raise EglBitmap.Create('mapping for compressed formats is not supported');
3619 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3621 raise EglBitmap.Create('mapping for compressed formats is not supported');
3624 constructor TfdS3tcDtx1RGBA.Create;
3627 fFormat := tfS3tcDtx1RGBA;
3628 fWithAlpha := tfS3tcDtx1RGBA;
3629 fUncompressed := tfRGB5A1;
3631 fIsCompressed := true;
3632 fglFormat := GL_COMPRESSED_RGBA;
3633 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3634 fglDataFormat := GL_UNSIGNED_BYTE;
3637 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3638 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3639 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3640 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3642 raise EglBitmap.Create('mapping for compressed formats is not supported');
3645 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3647 raise EglBitmap.Create('mapping for compressed formats is not supported');
3650 constructor TfdS3tcDtx3RGBA.Create;
3653 fFormat := tfS3tcDtx3RGBA;
3654 fWithAlpha := tfS3tcDtx3RGBA;
3655 fUncompressed := tfRGBA8;
3657 fIsCompressed := true;
3658 fglFormat := GL_COMPRESSED_RGBA;
3659 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3660 fglDataFormat := GL_UNSIGNED_BYTE;
3663 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3664 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3665 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3666 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3668 raise EglBitmap.Create('mapping for compressed formats is not supported');
3671 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3673 raise EglBitmap.Create('mapping for compressed formats is not supported');
3676 constructor TfdS3tcDtx5RGBA.Create;
3679 fFormat := tfS3tcDtx3RGBA;
3680 fWithAlpha := tfS3tcDtx3RGBA;
3681 fUncompressed := tfRGBA8;
3683 fIsCompressed := true;
3684 fglFormat := GL_COMPRESSED_RGBA;
3685 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3686 fglDataFormat := GL_UNSIGNED_BYTE;
3689 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3690 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3691 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3692 class procedure TFormatDescriptor.Init;
3694 if not Assigned(FormatDescriptorCS) then
3695 FormatDescriptorCS := TCriticalSection.Create;
3698 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3699 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3701 FormatDescriptorCS.Enter;
3703 result := FormatDescriptors[aFormat];
3704 if not Assigned(result) then begin
3705 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3706 FormatDescriptors[aFormat] := result;
3709 FormatDescriptorCS.Leave;
3713 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3714 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3716 result := Get(Get(aFormat).WithAlpha);
3719 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3720 class procedure TFormatDescriptor.Clear;
3724 FormatDescriptorCS.Enter;
3726 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3727 FreeAndNil(FormatDescriptors[f]);
3729 FormatDescriptorCS.Leave;
3733 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3734 class procedure TFormatDescriptor.Finalize;
3737 FreeAndNil(FormatDescriptorCS);
3740 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3741 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3742 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3743 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3745 Update(aValue, fRange.r, fShift.r);
3748 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3749 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3751 Update(aValue, fRange.g, fShift.g);
3754 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3755 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3757 Update(aValue, fRange.b, fShift.b);
3760 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3761 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3763 Update(aValue, fRange.a, fShift.a);
3766 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3767 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3774 while (aMask > 0) and ((aMask and 1) = 0) do begin
3776 aMask := aMask shr 1;
3779 while (aMask > 0) do begin
3780 aRange := aRange shl 1;
3781 aMask := aMask shr 1;
3785 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3788 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3789 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3795 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3796 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3797 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3798 ((aPixel.Data.a and fRange.a) shl fShift.a);
3799 s := Round(fPixelSize);
3802 2: PWord(aData)^ := data;
3803 4: PCardinal(aData)^ := data;
3804 8: PQWord(aData)^ := data;
3806 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3811 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3812 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3817 s := Round(fPixelSize);
3820 2: data := PWord(aData)^;
3821 4: data := PCardinal(aData)^;
3822 8: data := PQWord(aData)^;
3824 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3827 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3831 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3832 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3833 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3834 procedure TbmpColorTableFormat.CreateColorTable;
3838 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3839 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3841 if (Format = tfLuminance4) then
3842 SetLength(fColorTable, 16)
3844 SetLength(fColorTable, 256);
3848 for i := 0 to High(fColorTable) do begin
3849 fColorTable[i].r := 16 * i;
3850 fColorTable[i].g := 16 * i;
3851 fColorTable[i].b := 16 * i;
3852 fColorTable[i].a := 0;
3857 for i := 0 to High(fColorTable) do begin
3858 fColorTable[i].r := i;
3859 fColorTable[i].g := i;
3860 fColorTable[i].b := i;
3861 fColorTable[i].a := 0;
3866 for i := 0 to High(fColorTable) do begin
3867 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3868 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3869 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3870 fColorTable[i].a := 0;
3876 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3877 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3881 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3882 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3886 if (aMapData = nil) then
3888 d := LuminanceWeight(aPixel) and Range.r;
3889 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3890 inc(PByte(aMapData), 4);
3891 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3898 aData^ := LuminanceWeight(aPixel) and Range.r;
3904 ((aPixel.Data.r and Range.r) shl Shift.r) or
3905 ((aPixel.Data.g and Range.g) shl Shift.g) or
3906 ((aPixel.Data.b and Range.b) shl Shift.b));
3912 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3913 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3920 s := Trunc(fPixelSize);
3921 f := fPixelSize - s;
3922 bits := Round(8 * f);
3924 0: idx := (aData^ shr (8 - bits - {%H-}PtrInt(aMapData))) and ((1 shl bits) - 1);
3926 2: idx := PWord(aData)^;
3927 4: idx := PCardinal(aData)^;
3928 8: idx := PQWord(aData)^;
3930 raise EglBitmap.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3932 if (idx >= Length(fColorTable)) then
3933 raise EglBitmap.CreateFmt('invalid color index: %d', [idx]);
3934 with fColorTable[idx] do begin
3940 inc(PByte(aMapData), bits);
3941 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3943 dec(PByte(aMapData), 8);
3948 destructor TbmpColorTableFormat.Destroy;
3950 SetLength(fColorTable, 0);
3954 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3955 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3956 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3957 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
3961 for i := 0 to 3 do begin
3962 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
3963 if (aSourceFD.Range.arr[i] > 0) then
3964 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
3966 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
3971 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3972 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
3974 with aFuncRec do begin
3975 if (Source.Range.r > 0) then
3976 Dest.Data.r := Source.Data.r;
3977 if (Source.Range.g > 0) then
3978 Dest.Data.g := Source.Data.g;
3979 if (Source.Range.b > 0) then
3980 Dest.Data.b := Source.Data.b;
3981 if (Source.Range.a > 0) then
3982 Dest.Data.a := Source.Data.a;
3986 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3987 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3991 with aFuncRec do begin
3993 if (Source.Range.arr[i] > 0) then
3994 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
3999 TShiftData = packed record
4001 0: (r, g, b, a: SmallInt);
4002 1: (arr: array[0..3] of SmallInt);
4004 PShiftData = ^TShiftData;
4006 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4007 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4013 if (Source.Range.arr[i] > 0) then
4014 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4017 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4018 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4020 with aFuncRec do begin
4021 Dest.Data := Source.Data;
4022 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4023 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4024 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4025 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4027 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4028 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4033 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4034 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4038 with aFuncRec do begin
4040 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4044 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4045 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4049 with FuncRec do begin
4050 if (FuncRec.Args = nil) then begin //source has no alpha
4052 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4053 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4054 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4055 Dest.Data.a := Round(Dest.Range.a * Temp);
4057 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4061 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4062 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4064 PglBitmapPixelData = ^TglBitmapPixelData;
4066 with FuncRec do begin
4067 Dest.Data.r := Source.Data.r;
4068 Dest.Data.g := Source.Data.g;
4069 Dest.Data.b := Source.Data.b;
4071 with PglBitmapPixelData(Args)^ do
4072 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4073 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4074 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4077 Dest.Data.a := Dest.Range.a;
4081 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4082 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4084 with FuncRec do begin
4085 Dest.Data.r := Source.Data.r;
4086 Dest.Data.g := Source.Data.g;
4087 Dest.Data.b := Source.Data.b;
4088 Dest.Data.a := PCardinal(Args)^;
4092 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4093 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4096 TRGBPix = array [0..2] of byte;
4100 while aWidth > 0 do begin
4101 Temp := PRGBPix(aData)^[0];
4102 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4103 PRGBPix(aData)^[2] := Temp;
4113 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4114 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4116 function TglBitmap.GetFormatDesc: TglBitmapFormatDescriptor;
4118 result := TFormatDescriptor.Get(Format);
4121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4122 function TglBitmap.GetWidth: Integer;
4124 if (ffX in fDimension.Fields) then
4125 result := fDimension.X
4130 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4131 function TglBitmap.GetHeight: Integer;
4133 if (ffY in fDimension.Fields) then
4134 result := fDimension.Y
4139 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4140 function TglBitmap.GetFileWidth: Integer;
4142 result := Max(1, Width);
4145 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4146 function TglBitmap.GetFileHeight: Integer;
4148 result := Max(1, Height);
4151 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4152 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4154 if fCustomData = aValue then
4156 fCustomData := aValue;
4159 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4160 procedure TglBitmap.SetCustomName(const aValue: String);
4162 if fCustomName = aValue then
4164 fCustomName := aValue;
4167 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4168 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4170 if fCustomNameW = aValue then
4172 fCustomNameW := aValue;
4175 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4176 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4178 if fDeleteTextureOnFree = aValue then
4180 fDeleteTextureOnFree := aValue;
4183 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4184 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4186 if fFormat = aValue then
4188 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4189 raise EglBitmapUnsupportedFormat.Create(Format);
4190 SetDataPointer(fData, aValue, Width, Height); //be careful, Data could be freed by this method
4193 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4194 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4196 if fFreeDataAfterGenTexture = aValue then
4198 fFreeDataAfterGenTexture := aValue;
4201 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4202 procedure TglBitmap.SetID(const aValue: Cardinal);
4204 if fID = aValue then
4209 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4210 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4212 if fMipMap = aValue then
4217 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4218 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4220 if fTarget = aValue then
4225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4226 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4228 MaxAnisotropic: Integer;
4230 fAnisotropic := aValue;
4231 if (ID > 0) then begin
4232 if GL_EXT_texture_filter_anisotropic then begin
4233 if fAnisotropic > 0 then begin
4235 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4236 if aValue > MaxAnisotropic then
4237 fAnisotropic := MaxAnisotropic;
4238 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4246 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4247 procedure TglBitmap.CreateID;
4250 glDeleteTextures(1, @fID);
4251 glGenTextures(1, @fID);
4255 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4256 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4258 // Set Up Parameters
4259 SetWrap(fWrapS, fWrapT, fWrapR);
4260 SetFilter(fFilterMin, fFilterMag);
4261 SetAnisotropic(fAnisotropic);
4262 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4264 if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
4265 SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4267 // Mip Maps Generation Mode
4268 aBuildWithGlu := false;
4269 if (MipMap = mmMipmap) then begin
4270 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4271 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4273 aBuildWithGlu := true;
4274 end else if (MipMap = mmMipmapGlu) then
4275 aBuildWithGlu := true;
4278 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4279 procedure TglBitmap.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
4280 const aWidth: Integer; const aHeight: Integer);
4284 if (Data <> aData) then begin
4285 if (Assigned(Data)) then
4290 if not Assigned(fData) then begin
4294 FillChar(fDimension, SizeOf(fDimension), 0);
4295 if aWidth <> -1 then begin
4296 fDimension.Fields := fDimension.Fields + [ffX];
4297 fDimension.X := aWidth;
4300 if aHeight <> -1 then begin
4301 fDimension.Fields := fDimension.Fields + [ffY];
4302 fDimension.Y := aHeight;
4305 s := TFormatDescriptor.Get(aFormat).PixelSize;
4307 fPixelSize := Ceil(s);
4308 fRowSize := Ceil(s * aWidth);
4312 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4313 function TglBitmap.FlipHorz: Boolean;
4318 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4319 function TglBitmap.FlipVert: Boolean;
4324 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4325 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4326 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4327 procedure TglBitmap.AfterConstruction;
4329 inherited AfterConstruction;
4333 fIsResident := false;
4335 fFormat := glBitmapGetDefaultFormat;
4336 fMipMap := glBitmapDefaultMipmap;
4337 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4338 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4340 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4341 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4342 glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4345 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4346 procedure TglBitmap.BeforeDestruction;
4351 SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
4352 if (fID > 0) and fDeleteTextureOnFree then
4353 glDeleteTextures(1, @fID);
4354 inherited BeforeDestruction;
4357 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4358 procedure TglBitmap.PrepareResType(var aResource: String; var aResType: PChar);
4362 if not Assigned(aResType) then begin
4363 TempPos := Pos('.', aResource);
4364 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4365 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4369 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4370 procedure TglBitmap.LoadFromFile(const aFilename: String);
4374 if not FileExists(aFilename) then
4375 raise EglBitmap.Create('file does not exist: ' + aFilename);
4376 fFilename := aFilename;
4377 fs := TFileStream.Create(fFilename, fmOpenRead);
4386 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4387 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4389 {$IFDEF GLB_SUPPORT_PNG_READ}
4390 if not LoadPNG(aStream) then
4392 {$IFDEF GLB_SUPPORT_JPEG_READ}
4393 if not LoadJPEG(aStream) then
4395 if not LoadDDS(aStream) then
4396 if not LoadTGA(aStream) then
4397 if not LoadBMP(aStream) then
4398 raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4401 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4402 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4403 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4408 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4409 GetMem(tmpData, size);
4411 FillChar(tmpData^, size, #$FF);
4412 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
4414 if Assigned(tmpData) then
4418 AddFunc(Self, aFunc, false, Format, aArgs);
4421 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4422 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
4424 rs: TResourceStream;
4426 PrepareResType(aResource, aResType);
4427 rs := TResourceStream.Create(aInstance, aResource, aResType);
4435 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4436 procedure TglBitmap.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4438 rs: TResourceStream;
4440 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
4448 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4449 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4453 fs := TFileStream.Create(aFileName, fmCreate);
4456 SaveToStream(fs, aFileType);
4462 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4463 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4466 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4467 ftPNG: SavePNG(aStream);
4469 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4470 ftJPEG: SaveJPEG(aStream);
4472 ftDDS: SaveDDS(aStream);
4473 ftTGA: SaveTGA(aStream);
4474 ftBMP: SaveBMP(aStream);
4478 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4479 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4481 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4485 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4486 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4488 DestData, TmpData, SourceData: pByte;
4489 TempHeight, TempWidth: Integer;
4490 SourceFD, DestFD: TFormatDescriptor;
4491 SourceMD, DestMD: Pointer;
4493 FuncRec: TglBitmapFunctionRec;
4495 Assert(Assigned(Data));
4496 Assert(Assigned(aSource));
4497 Assert(Assigned(aSource.Data));
4500 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4501 SourceFD := TFormatDescriptor.Get(aSource.Format);
4502 DestFD := TFormatDescriptor.Get(aFormat);
4504 if (SourceFD.IsCompressed) then
4505 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
4506 if (DestFD.IsCompressed) then
4507 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
4509 // inkompatible Formats so CreateTemp
4510 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4511 aCreateTemp := true;
4514 TempHeight := Max(1, aSource.Height);
4515 TempWidth := Max(1, aSource.Width);
4517 FuncRec.Sender := Self;
4518 FuncRec.Args := aArgs;
4521 if aCreateTemp then begin
4522 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
4523 DestData := TmpData;
4528 SourceFD.PreparePixel(FuncRec.Source);
4529 DestFD.PreparePixel (FuncRec.Dest);
4531 SourceMD := SourceFD.CreateMappingData;
4532 DestMD := DestFD.CreateMappingData;
4534 FuncRec.Size := aSource.Dimension;
4535 FuncRec.Position.Fields := FuncRec.Size.Fields;
4538 SourceData := aSource.Data;
4539 FuncRec.Position.Y := 0;
4540 while FuncRec.Position.Y < TempHeight do begin
4541 FuncRec.Position.X := 0;
4542 while FuncRec.Position.X < TempWidth do begin
4543 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4545 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4546 inc(FuncRec.Position.X);
4548 inc(FuncRec.Position.Y);
4551 // Updating Image or InternalFormat
4553 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) //be careful, Data could be freed by this method
4554 else if (aFormat <> fFormat) then
4559 SourceFD.FreeMappingData(SourceMD);
4560 DestFD.FreeMappingData(DestMD);
4563 if aCreateTemp and Assigned(TmpData) then
4571 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4572 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4574 Row, RowSize: Integer;
4575 SourceData, TmpData: PByte;
4577 FormatDesc: TFormatDescriptor;
4579 function GetRowPointer(Row: Integer): pByte;
4581 result := aSurface.pixels;
4582 Inc(result, Row * RowSize);
4588 FormatDesc := TFormatDescriptor.Get(Format);
4589 if FormatDesc.IsCompressed then
4590 raise EglBitmapUnsupportedFormat.Create(Format);
4592 if Assigned(Data) then begin
4593 case Trunc(FormatDesc.PixelSize) of
4599 raise EglBitmapUnsupportedFormat.Create(Format);
4602 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4603 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4605 RowSize := FormatDesc.GetSize(FileWidth, 1);
4607 for Row := 0 to FileHeight-1 do begin
4608 TmpData := GetRowPointer(Row);
4609 if Assigned(TmpData) then begin
4610 Move(SourceData^, TmpData^, RowSize);
4611 inc(SourceData, RowSize);
4618 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4619 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4621 pSource, pData, pTempData: PByte;
4622 Row, RowSize, TempWidth, TempHeight: Integer;
4623 IntFormat: TglBitmapFormat;
4624 FormatDesc: TFormatDescriptor;
4626 function GetRowPointer(Row: Integer): pByte;
4628 result := aSurface^.pixels;
4629 Inc(result, Row * RowSize);
4634 if (Assigned(aSurface)) then begin
4635 with aSurface^.format^ do begin
4636 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4637 FormatDesc := TFormatDescriptor.Get(IntFormat);
4638 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4641 if (IntFormat = tfEmpty) then
4642 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4645 TempWidth := aSurface^.w;
4646 TempHeight := aSurface^.h;
4647 RowSize := FormatDesc.GetSize(TempWidth, 1);
4648 GetMem(pData, TempHeight * RowSize);
4651 for Row := 0 to TempHeight -1 do begin
4652 pSource := GetRowPointer(Row);
4653 if (Assigned(pSource)) then begin
4654 Move(pSource^, pTempData^, RowSize);
4655 Inc(pTempData, RowSize);
4658 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4661 if Assigned(pData) then
4668 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4669 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4671 Row, Col, AlphaInterleave: Integer;
4672 pSource, pDest: PByte;
4674 function GetRowPointer(Row: Integer): pByte;
4676 result := aSurface.pixels;
4677 Inc(result, Row * Width);
4682 if Assigned(Data) then begin
4683 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4684 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4686 AlphaInterleave := 0;
4689 AlphaInterleave := 1;
4691 AlphaInterleave := 3;
4695 for Row := 0 to Height -1 do begin
4696 pDest := GetRowPointer(Row);
4697 if Assigned(pDest) then begin
4698 for Col := 0 to Width -1 do begin
4699 Inc(pSource, AlphaInterleave);
4711 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4712 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4716 bmp := TglBitmap2D.Create;
4718 bmp.AssignFromSurface(aSurface);
4719 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4727 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4728 function CreateGrayPalette: HPALETTE;
4733 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
4735 Pal.palVersion := $300;
4736 Pal.palNumEntries := 256;
4738 for Idx := 0 to Pal.palNumEntries - 1 do begin
4739 Pal.palPalEntry[Idx].peRed := Idx;
4740 Pal.palPalEntry[Idx].peGreen := Idx;
4741 Pal.palPalEntry[Idx].peBlue := Idx;
4742 Pal.palPalEntry[Idx].peFlags := 0;
4744 Result := CreatePalette(Pal^);
4748 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4749 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4752 pSource, pData: PByte;
4755 if Assigned(Data) then begin
4756 if Assigned(aBitmap) then begin
4757 aBitmap.Width := Width;
4758 aBitmap.Height := Height;
4761 tfAlpha8, tfLuminance8: begin
4762 aBitmap.PixelFormat := pf8bit;
4763 aBitmap.Palette := CreateGrayPalette;
4766 aBitmap.PixelFormat := pf15bit;
4768 aBitmap.PixelFormat := pf16bit;
4770 aBitmap.PixelFormat := pf24bit;
4772 aBitmap.PixelFormat := pf32bit;
4774 raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.');
4778 for Row := 0 to FileHeight -1 do begin
4779 pData := aBitmap.Scanline[Row];
4780 Move(pSource^, pData^, fRowSize);
4781 Inc(pSource, fRowSize);
4782 if (Format in [tfRGB8, tfRGBA8]) then // swap RGB(A) to BGR(A)
4783 SwapRGB(pData, FileWidth, Format = tfRGBA8);
4790 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4791 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4793 pSource, pData, pTempData: PByte;
4794 Row, RowSize, TempWidth, TempHeight: Integer;
4795 IntFormat: TglBitmapFormat;
4799 if (Assigned(aBitmap)) then begin
4800 case aBitmap.PixelFormat of
4802 IntFormat := tfLuminance8;
4804 IntFormat := tfRGB5A1;
4806 IntFormat := tfR5G6B5;
4808 IntFormat := tfBGR8;
4810 IntFormat := tfBGRA8;
4812 raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.');
4815 TempWidth := aBitmap.Width;
4816 TempHeight := aBitmap.Height;
4817 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
4818 GetMem(pData, TempHeight * RowSize);
4821 for Row := 0 to TempHeight -1 do begin
4822 pSource := aBitmap.Scanline[Row];
4823 if (Assigned(pSource)) then begin
4824 Move(pSource^, pTempData^, RowSize);
4825 Inc(pTempData, RowSize);
4828 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4831 if Assigned(pData) then
4838 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4839 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4841 Row, Col, AlphaInterleave: Integer;
4842 pSource, pDest: PByte;
4846 if Assigned(Data) then begin
4847 if (Format in [tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8]) then begin
4848 if Assigned(aBitmap) then begin
4849 aBitmap.PixelFormat := pf8bit;
4850 aBitmap.Palette := CreateGrayPalette;
4851 aBitmap.Width := Width;
4852 aBitmap.Height := Height;
4856 AlphaInterleave := 1;
4858 AlphaInterleave := 3;
4860 AlphaInterleave := 0;
4866 for Row := 0 to Height -1 do begin
4867 pDest := aBitmap.Scanline[Row];
4868 if Assigned(pDest) then begin
4869 for Col := 0 to Width -1 do begin
4870 Inc(pSource, AlphaInterleave);
4883 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4884 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4888 tex := TglBitmap2D.Create;
4890 tex.AssignFromBitmap(ABitmap);
4891 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4898 {$IFDEF GLB_LAZARUS}
4899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4900 function TglBitmap.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4902 rid: TRawImageDescription;
4903 FormatDesc: TFormatDescriptor;
4906 if not Assigned(aImage) or (Format = tfEmpty) then
4908 FormatDesc := TFormatDescriptor.Get(Format);
4909 if FormatDesc.IsCompressed then
4912 FillChar(rid{%H-}, SizeOf(rid), 0);
4914 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
4915 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
4916 tfLuminance4Alpha4, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16]) then
4917 rid.Format := ricfGray
4919 rid.Format := ricfRGBA;
4922 rid.Height := Height;
4923 rid.Depth := CountSetBits(FormatDesc.Range.r or FormatDesc.Range.g or FormatDesc.Range.b or FormatDesc.Range.a);
4924 rid.BitOrder := riboBitsInOrder;
4925 rid.ByteOrder := riboLSBFirst;
4926 rid.LineOrder := riloTopToBottom;
4927 rid.LineEnd := rileTight;
4928 rid.BitsPerPixel := Round(8 * FormatDesc.PixelSize);
4929 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
4930 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
4931 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
4932 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
4933 rid.RedShift := FormatDesc.Shift.r;
4934 rid.GreenShift := FormatDesc.Shift.g;
4935 rid.BlueShift := FormatDesc.Shift.b;
4936 rid.AlphaShift := FormatDesc.Shift.a;
4938 rid.MaskBitsPerPixel := 0;
4939 rid.PaletteColorCount := 0;
4941 aImage.DataDescription := rid;
4944 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
4949 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4950 function TglBitmap.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
4953 FormatDesc: TFormatDescriptor;
4958 if not Assigned(aImage) then
4960 for f := High(f) downto Low(f) do begin
4961 FormatDesc := TFormatDescriptor.Get(f);
4962 with aImage.DataDescription do
4963 if FormatDesc.MaskMatch(
4964 (QWord(1 shl RedPrec )-1) shl RedShift,
4965 (QWord(1 shl GreenPrec)-1) shl GreenShift,
4966 (QWord(1 shl BluePrec )-1) shl BlueShift,
4967 (QWord(1 shl AlphaPrec)-1) shl AlphaShift) then
4971 if (f = tfEmpty) then
4974 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
4975 ImageData := GetMem(ImageSize);
4977 Move(aImage.PixelData^, ImageData^, (aImage.Width * aImage.Height * aImage.DataDescription.BitsPerPixel) shr 3);
4978 SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method
4980 if Assigned(ImageData) then
4988 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4989 function TglBitmap.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4991 rid: TRawImageDescription;
4992 FormatDesc: TFormatDescriptor;
4993 Pixel: TglBitmapPixelData;
4999 if not Assigned(aImage) or (Format = tfEmpty) then
5001 FormatDesc := TFormatDescriptor.Get(Format);
5002 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5005 FillChar(rid{%H-}, SizeOf(rid), 0);
5006 rid.Format := ricfGray;
5008 rid.Height := Height;
5009 rid.Depth := CountSetBits(FormatDesc.Range.a);
5010 rid.BitOrder := riboBitsInOrder;
5011 rid.ByteOrder := riboLSBFirst;
5012 rid.LineOrder := riloTopToBottom;
5013 rid.LineEnd := rileTight;
5014 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
5015 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
5020 rid.GreenShift := 0;
5022 rid.AlphaShift := 0;
5024 rid.MaskBitsPerPixel := 0;
5025 rid.PaletteColorCount := 0;
5027 aImage.DataDescription := rid;
5030 srcMD := FormatDesc.CreateMappingData;
5032 FormatDesc.PreparePixel(Pixel);
5034 dst := aImage.PixelData;
5035 for y := 0 to Height-1 do
5036 for x := 0 to Width-1 do begin
5037 FormatDesc.Unmap(src, Pixel, srcMD);
5038 case rid.BitsPerPixel of
5040 dst^ := Pixel.Data.a;
5044 PWord(dst)^ := Pixel.Data.a;
5048 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
5049 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
5050 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
5054 PCardinal(dst)^ := Pixel.Data.a;
5058 raise EglBitmapUnsupportedFormat.Create(Format);
5062 FormatDesc.FreeMappingData(srcMD);
5067 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5068 function TglBitmap.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5072 tex := TglBitmap2D.Create;
5074 tex.AssignFromLazIntfImage(aImage);
5075 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5082 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5083 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
5084 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5086 rs: TResourceStream;
5088 PrepareResType(aResource, aResType);
5089 rs := TResourceStream.Create(aInstance, aResource, aResType);
5091 result := AddAlphaFromStream(rs, aFunc, aArgs);
5097 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5098 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
5099 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5101 rs: TResourceStream;
5103 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
5105 result := AddAlphaFromStream(rs, aFunc, aArgs);
5111 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5112 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5114 if TFormatDescriptor.Get(Format).IsCompressed then
5115 raise EglBitmapUnsupportedFormat.Create(Format);
5116 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
5119 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5120 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5124 FS := TFileStream.Create(aFileName, fmOpenRead);
5126 result := AddAlphaFromStream(FS, aFunc, aArgs);
5132 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5133 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5137 tex := TglBitmap2D.Create(aStream);
5139 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5145 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5146 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5148 DestData, DestData2, SourceData: pByte;
5149 TempHeight, TempWidth: Integer;
5150 SourceFD, DestFD: TFormatDescriptor;
5151 SourceMD, DestMD, DestMD2: Pointer;
5153 FuncRec: TglBitmapFunctionRec;
5157 Assert(Assigned(Data));
5158 Assert(Assigned(aBitmap));
5159 Assert(Assigned(aBitmap.Data));
5161 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
5162 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
5164 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
5165 DestFD := TFormatDescriptor.Get(Format);
5167 if not Assigned(aFunc) then begin
5168 aFunc := glBitmapAlphaFunc;
5169 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5171 FuncRec.Args := aArgs;
5174 TempHeight := aBitmap.FileHeight;
5175 TempWidth := aBitmap.FileWidth;
5177 FuncRec.Sender := Self;
5178 FuncRec.Size := Dimension;
5179 FuncRec.Position.Fields := FuncRec.Size.Fields;
5183 SourceData := aBitmap.Data;
5186 SourceFD.PreparePixel(FuncRec.Source);
5187 DestFD.PreparePixel (FuncRec.Dest);
5189 SourceMD := SourceFD.CreateMappingData;
5190 DestMD := DestFD.CreateMappingData;
5191 DestMD2 := DestFD.CreateMappingData;
5193 FuncRec.Position.Y := 0;
5194 while FuncRec.Position.Y < TempHeight do begin
5195 FuncRec.Position.X := 0;
5196 while FuncRec.Position.X < TempWidth do begin
5197 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5198 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5200 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5201 inc(FuncRec.Position.X);
5203 inc(FuncRec.Position.Y);
5206 SourceFD.FreeMappingData(SourceMD);
5207 DestFD.FreeMappingData(DestMD);
5208 DestFD.FreeMappingData(DestMD2);
5213 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5214 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5216 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5219 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5220 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5222 PixelData: TglBitmapPixelData;
5224 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5225 result := AddAlphaFromColorKeyFloat(
5226 aRed / PixelData.Range.r,
5227 aGreen / PixelData.Range.g,
5228 aBlue / PixelData.Range.b,
5229 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5232 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5233 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5235 values: array[0..2] of Single;
5238 PixelData: TglBitmapPixelData;
5240 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5241 with PixelData do begin
5243 values[1] := aGreen;
5246 for i := 0 to 2 do begin
5247 tmp := Trunc(Range.arr[i] * aDeviation);
5248 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5249 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5254 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5257 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5258 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5260 result := AddAlphaFromValueFloat(aAlpha / $FF);
5263 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5264 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5266 PixelData: TglBitmapPixelData;
5268 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5269 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5272 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5273 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5275 PixelData: TglBitmapPixelData;
5277 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5279 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5280 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5284 function TglBitmap.RemoveAlpha: Boolean;
5286 FormatDesc: TFormatDescriptor;
5289 FormatDesc := TFormatDescriptor.Get(Format);
5290 if Assigned(Data) then begin
5291 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5292 raise EglBitmapUnsupportedFormat.Create(Format);
5293 result := ConvertTo(FormatDesc.WithoutAlpha);
5297 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5298 function TglBitmap.Clone: TglBitmap;
5305 Temp := (ClassType.Create as TglBitmap);
5307 // copy texture data if assigned
5308 if Assigned(Data) then begin
5309 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5310 GetMem(TempPtr, Size);
5312 Move(Data^, TempPtr^, Size);
5313 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5315 if Assigned(TempPtr) then
5321 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5326 Temp.fTarget := Target;
5327 Temp.fFormat := Format;
5328 Temp.fMipMap := MipMap;
5329 Temp.fAnisotropic := Anisotropic;
5330 Temp.fBorderColor := fBorderColor;
5331 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5332 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5333 Temp.fFilterMin := fFilterMin;
5334 Temp.fFilterMag := fFilterMag;
5335 Temp.fWrapS := fWrapS;
5336 Temp.fWrapT := fWrapT;
5337 Temp.fWrapR := fWrapR;
5338 Temp.fFilename := fFilename;
5339 Temp.fCustomName := fCustomName;
5340 Temp.fCustomNameW := fCustomNameW;
5341 Temp.fCustomData := fCustomData;
5350 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5351 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5353 SourceFD, DestFD: TFormatDescriptor;
5354 SourcePD, DestPD: TglBitmapPixelData;
5355 ShiftData: TShiftData;
5357 function CanCopyDirect: Boolean;
5360 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5361 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5362 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5363 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5366 function CanShift: Boolean;
5369 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5370 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5371 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5372 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5375 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5378 while (aSource > aDest) and (aSource > 0) do begin
5380 aSource := aSource shr 1;
5385 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5386 SourceFD := TFormatDescriptor.Get(Format);
5387 DestFD := TFormatDescriptor.Get(aFormat);
5389 SourceFD.PreparePixel(SourcePD);
5390 DestFD.PreparePixel (DestPD);
5392 if CanCopyDirect then
5393 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5394 else if CanShift then begin
5395 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5396 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5397 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5398 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5399 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5401 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5406 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5407 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5409 if aUseRGB or aUseAlpha then
5410 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5411 ((Byte(aUseAlpha) and 1) shl 1) or
5412 (Byte(aUseRGB) and 1) ));
5415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5416 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5418 fBorderColor[0] := aRed;
5419 fBorderColor[1] := aGreen;
5420 fBorderColor[2] := aBlue;
5421 fBorderColor[3] := aAlpha;
5422 if (ID > 0) then begin
5424 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5428 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5429 procedure TglBitmap.FreeData;
5434 SetDataPointer(TempPtr, tfEmpty); //be careful, Data could be freed by this method
5437 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5438 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5439 const aAlpha: Byte);
5441 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5444 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5445 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5447 PixelData: TglBitmapPixelData;
5449 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5451 aRed / PixelData.Range.r,
5452 aGreen / PixelData.Range.g,
5453 aBlue / PixelData.Range.b,
5454 aAlpha / PixelData.Range.a);
5457 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5458 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5460 PixelData: TglBitmapPixelData;
5462 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5463 with PixelData do begin
5464 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5465 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5466 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5467 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5469 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5472 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5473 procedure TglBitmap.SetFilter(const aMin, aMag: GLenum);
5478 fFilterMin := GL_NEAREST;
5480 fFilterMin := GL_LINEAR;
5481 GL_NEAREST_MIPMAP_NEAREST:
5482 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5483 GL_LINEAR_MIPMAP_NEAREST:
5484 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5485 GL_NEAREST_MIPMAP_LINEAR:
5486 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5487 GL_LINEAR_MIPMAP_LINEAR:
5488 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5490 raise EglBitmap.Create('SetFilter - Unknow MIN filter.');
5496 fFilterMag := GL_NEAREST;
5498 fFilterMag := GL_LINEAR;
5500 raise EglBitmap.Create('SetFilter - Unknow MAG filter.');
5504 if (ID > 0) then begin
5506 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5508 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5510 GL_NEAREST, GL_LINEAR:
5511 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5512 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5513 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5514 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5515 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5518 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5522 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5523 procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum);
5525 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5529 aTarget := GL_CLAMP;
5532 aTarget := GL_REPEAT;
5534 GL_CLAMP_TO_EDGE: begin
5535 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5536 aTarget := GL_CLAMP_TO_EDGE
5538 aTarget := GL_CLAMP;
5541 GL_CLAMP_TO_BORDER: begin
5542 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5543 aTarget := GL_CLAMP_TO_BORDER
5545 aTarget := GL_CLAMP;
5548 GL_MIRRORED_REPEAT: begin
5549 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5550 aTarget := GL_MIRRORED_REPEAT
5552 raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5555 raise EglBitmap.Create('SetWrap - Unknow Texturewrap');
5560 CheckAndSetWrap(S, fWrapS);
5561 CheckAndSetWrap(T, fWrapT);
5562 CheckAndSetWrap(R, fWrapR);
5564 if (ID > 0) then begin
5566 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5567 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5568 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5572 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5573 procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum);
5575 procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer);
5577 if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or
5578 (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then
5579 fSwizzle[aIndex] := aValue
5581 raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value');
5585 if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
5586 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
5587 CheckAndSetValue(r, 0);
5588 CheckAndSetValue(g, 1);
5589 CheckAndSetValue(b, 2);
5590 CheckAndSetValue(a, 3);
5592 if (ID > 0) then begin
5594 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, @fSwizzle[0]);
5598 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5599 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5601 if aEnableTextureUnit then
5604 glBindTexture(Target, ID);
5607 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5608 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5610 if aDisableTextureUnit then
5612 glBindTexture(Target, 0);
5615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5616 constructor TglBitmap.Create;
5618 if (ClassType = TglBitmap) then
5619 raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5620 {$IFDEF GLB_NATIVE_OGL}
5621 glbReadOpenGLExtensions;
5626 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5627 constructor TglBitmap.Create(const aFileName: String);
5630 LoadFromFile(aFileName);
5633 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5634 constructor TglBitmap.Create(const aStream: TStream);
5637 LoadFromStream(aStream);
5640 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5641 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
5647 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5648 GetMem(Image, ImageSize);
5650 FillChar(Image^, ImageSize, #$FF);
5651 SetDataPointer(Image, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5653 if Assigned(Image) then
5659 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5660 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
5661 const aFunc: TglBitmapFunction; const aArgs: Pointer);
5664 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5667 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5668 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5671 LoadFromResource(aInstance, aResource, aResType);
5674 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5675 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5678 LoadFromResourceID(aInstance, aResourceID, aResType);
5681 {$IFDEF GLB_SUPPORT_PNG_READ}
5682 {$IF DEFINED(GLB_LAZ_PNG)}
5683 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5684 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5685 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5686 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5689 PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A;
5691 png: TPortableNetworkGraphic;
5692 intf: TLazIntfImage;
5694 magic: String[MAGIC_LEN];
5697 StreamPos := aStream.Position;
5699 SetLength(magic, MAGIC_LEN);
5700 aStream.Read(magic[1], MAGIC_LEN);
5701 aStream.Position := StreamPos;
5702 if (magic <> PNG_MAGIC) then begin
5707 png := TPortableNetworkGraphic.Create;
5709 png.LoadFromStream(aStream);
5710 intf := png.CreateIntfImage;
5712 AssignFromLazIntfImage(intf);
5715 aStream.Position := StreamPos;
5723 aStream.Position := StreamPos;
5731 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
5732 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5733 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5735 Surface: PSDL_Surface;
5739 RWops := glBitmapCreateRWops(aStream);
5741 if IMG_isPNG(RWops) > 0 then begin
5742 Surface := IMG_LoadPNG_RW(RWops);
5744 AssignFromSurface(Surface);
5747 SDL_FreeSurface(Surface);
5755 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5756 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5757 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5759 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5762 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5763 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5766 signature: array [0..7] of byte;
5768 png_info: png_infop;
5770 TempHeight, TempWidth: Integer;
5771 Format: TglBitmapFormat;
5774 png_rows: array of pByte;
5775 Row, LineSize: Integer;
5779 if not init_libPNG then
5780 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5784 StreamPos := aStream.Position;
5785 aStream.Read(signature{%H-}, 8);
5786 aStream.Position := StreamPos;
5788 if png_check_sig(@signature, 8) <> 0 then begin
5790 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5792 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5795 png_info := png_create_info_struct(png);
5796 if png_info = nil then begin
5797 png_destroy_read_struct(@png, nil, nil);
5798 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5801 // set read callback
5802 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5804 // read informations
5805 png_read_info(png, png_info);
5808 TempHeight := png_get_image_height(png, png_info);
5809 TempWidth := png_get_image_width(png, png_info);
5812 case png_get_color_type(png, png_info) of
5813 PNG_COLOR_TYPE_GRAY:
5814 Format := tfLuminance8;
5815 PNG_COLOR_TYPE_GRAY_ALPHA:
5816 Format := tfLuminance8Alpha8;
5819 PNG_COLOR_TYPE_RGB_ALPHA:
5822 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5825 // cut upper 8 bit from 16 bit formats
5826 if png_get_bit_depth(png, png_info) > 8 then
5827 png_set_strip_16(png);
5829 // expand bitdepth smaller than 8
5830 if png_get_bit_depth(png, png_info) < 8 then
5831 png_set_expand(png);
5833 // allocating mem for scanlines
5834 LineSize := png_get_rowbytes(png, png_info);
5835 GetMem(png_data, TempHeight * LineSize);
5837 SetLength(png_rows, TempHeight);
5838 for Row := Low(png_rows) to High(png_rows) do begin
5839 png_rows[Row] := png_data;
5840 Inc(png_rows[Row], Row * LineSize);
5843 // read complete image into scanlines
5844 png_read_image(png, @png_rows[0]);
5847 png_read_end(png, png_info);
5849 // destroy read struct
5850 png_destroy_read_struct(@png, @png_info, nil);
5852 SetLength(png_rows, 0);
5855 SetDataPointer(png_data, Format, TempWidth, TempHeight); //be careful, Data could be freed by this method
5859 if Assigned(png_data) then
5869 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5870 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5871 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5876 Row, Col, PixSize, LineSize: Integer;
5877 NewImage, pSource, pDest, pAlpha: pByte;
5878 PngFormat: TglBitmapFormat;
5879 FormatDesc: TFormatDescriptor;
5882 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
5887 StreamPos := aStream.Position;
5888 aStream.Read(Header[0], SizeOf(Header));
5889 aStream.Position := StreamPos;
5891 {Test if the header matches}
5892 if Header = PngHeader then begin
5893 Png := TPNGObject.Create;
5895 Png.LoadFromStream(aStream);
5897 case Png.Header.ColorType of
5899 PngFormat := tfLuminance8;
5900 COLOR_GRAYSCALEALPHA:
5901 PngFormat := tfLuminance8Alpha8;
5903 PngFormat := tfBGR8;
5905 PngFormat := tfBGRA8;
5907 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5910 FormatDesc := TFormatDescriptor.Get(PngFormat);
5911 PixSize := Round(FormatDesc.PixelSize);
5912 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
5914 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5918 case Png.Header.ColorType of
5919 COLOR_RGB, COLOR_GRAYSCALE:
5921 for Row := 0 to Png.Height -1 do begin
5922 Move (Png.Scanline[Row]^, pDest^, LineSize);
5923 Inc(pDest, LineSize);
5926 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5928 PixSize := PixSize -1;
5930 for Row := 0 to Png.Height -1 do begin
5931 pSource := Png.Scanline[Row];
5932 pAlpha := pByte(Png.AlphaScanline[Row]);
5934 for Col := 0 to Png.Width -1 do begin
5935 Move (pSource^, pDest^, PixSize);
5936 Inc(pSource, PixSize);
5937 Inc(pDest, PixSize);
5946 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5949 SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); //be careful, Data could be freed by this method
5953 if Assigned(NewImage) then
5965 {$IFDEF GLB_SUPPORT_PNG_WRITE}
5966 {$IFDEF GLB_LIB_PNG}
5967 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5968 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5970 TStream(png_get_io_ptr(png)).Write(buffer^, size);
5974 {$IF DEFINED(GLB_LAZ_PNG)}
5975 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5976 procedure TglBitmap.SavePNG(const aStream: TStream);
5978 png: TPortableNetworkGraphic;
5979 intf: TLazIntfImage;
5981 png := TPortableNetworkGraphic.Create;
5982 intf := TLazIntfImage.Create(0, 0);
5984 if not AssignToLazIntfImage(intf) then
5985 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
5986 png.LoadFromIntfImage(intf);
5987 png.SaveToStream(aStream);
5994 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5995 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5996 procedure TglBitmap.SavePNG(const aStream: TStream);
5999 png_info: png_infop;
6000 png_rows: array of pByte;
6004 FormatDesc: TFormatDescriptor;
6006 if not (ftPNG in FormatGetSupportedFiles(Format)) then
6007 raise EglBitmapUnsupportedFormat.Create(Format);
6009 if not init_libPNG then
6010 raise Exception.Create('unable to initialize libPNG.');
6014 tfAlpha8, tfLuminance8:
6015 ColorType := PNG_COLOR_TYPE_GRAY;
6017 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
6019 ColorType := PNG_COLOR_TYPE_RGB;
6021 ColorType := PNG_COLOR_TYPE_RGBA;
6023 raise EglBitmapUnsupportedFormat.Create(Format);
6026 FormatDesc := TFormatDescriptor.Get(Format);
6027 LineSize := FormatDesc.GetSize(Width, 1);
6029 // creating array for scanline
6030 SetLength(png_rows, Height);
6032 for Row := 0 to Height - 1 do begin
6033 png_rows[Row] := Data;
6034 Inc(png_rows[Row], Row * LineSize)
6038 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
6040 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
6043 png_info := png_create_info_struct(png);
6044 if png_info = nil then begin
6045 png_destroy_write_struct(@png, nil);
6046 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
6049 // set read callback
6050 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
6053 png_set_compression_level(png, 6);
6055 if Format in [tfBGR8, tfBGRA8] then
6058 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
6059 png_write_info(png, png_info);
6060 png_write_image(png, @png_rows[0]);
6061 png_write_end(png, png_info);
6062 png_destroy_write_struct(@png, @png_info);
6064 SetLength(png_rows, 0);
6071 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
6072 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6073 procedure TglBitmap.SavePNG(const aStream: TStream);
6077 pSource, pDest: pByte;
6078 X, Y, PixSize: Integer;
6079 ColorType: Cardinal;
6085 if not (ftPNG in FormatGetSupportedFiles (Format)) then
6086 raise EglBitmapUnsupportedFormat.Create(Format);
6089 tfAlpha8, tfLuminance8: begin
6090 ColorType := COLOR_GRAYSCALE;
6094 tfLuminance8Alpha8: begin
6095 ColorType := COLOR_GRAYSCALEALPHA;
6099 tfBGR8, tfRGB8: begin
6100 ColorType := COLOR_RGB;
6104 tfBGRA8, tfRGBA8: begin
6105 ColorType := COLOR_RGBALPHA;
6110 raise EglBitmapUnsupportedFormat.Create(Format);
6113 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
6117 for Y := 0 to Height -1 do begin
6118 pDest := png.ScanLine[Y];
6119 for X := 0 to Width -1 do begin
6120 Move(pSource^, pDest^, PixSize);
6121 Inc(pDest, PixSize);
6122 Inc(pSource, PixSize);
6124 png.AlphaScanline[Y]^[X] := pSource^;
6129 // convert RGB line to BGR
6130 if Format in [tfRGB8, tfRGBA8] then begin
6131 pTemp := png.ScanLine[Y];
6132 for X := 0 to Width -1 do begin
6133 Temp := pByteArray(pTemp)^[0];
6134 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
6135 pByteArray(pTemp)^[2] := Temp;
6142 Png.CompressionLevel := 6;
6143 Png.SaveToStream(aStream);
6151 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6152 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6153 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6154 {$IFDEF GLB_LIB_JPEG}
6156 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
6157 glBitmap_libJPEG_source_mgr = record
6158 pub: jpeg_source_mgr;
6161 SrcBuffer: array [1..4096] of byte;
6164 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
6165 glBitmap_libJPEG_dest_mgr = record
6166 pub: jpeg_destination_mgr;
6168 DestStream: TStream;
6169 DestBuffer: array [1..4096] of byte;
6172 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
6178 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
6184 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
6189 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
6195 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
6201 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6202 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
6204 src: glBitmap_libJPEG_source_mgr_ptr;
6207 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6209 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
6210 if (bytes <= 0) then begin
6211 src^.SrcBuffer[1] := $FF;
6212 src^.SrcBuffer[2] := JPEG_EOI;
6216 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
6217 src^.pub.bytes_in_buffer := bytes;
6222 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6223 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
6225 src: glBitmap_libJPEG_source_mgr_ptr;
6227 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6229 if num_bytes > 0 then begin
6230 // wanted byte isn't in buffer so set stream position and read buffer
6231 if num_bytes > src^.pub.bytes_in_buffer then begin
6232 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
6233 src^.pub.fill_input_buffer(cinfo);
6235 // wanted byte is in buffer so only skip
6236 inc(src^.pub.next_input_byte, num_bytes);
6237 dec(src^.pub.bytes_in_buffer, num_bytes);
6242 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6243 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
6245 dest: glBitmap_libJPEG_dest_mgr_ptr;
6247 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6249 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
6250 // write complete buffer
6251 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
6254 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
6255 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
6261 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6262 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
6265 dest: glBitmap_libJPEG_dest_mgr_ptr;
6267 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6269 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6270 // check for endblock
6271 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6273 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6278 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6283 {$IFDEF GLB_SUPPORT_JPEG_READ}
6284 {$IF DEFINED(GLB_LAZ_JPEG)}
6285 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6286 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6289 JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
6292 intf: TLazIntfImage;
6294 magic: String[MAGIC_LEN];
6297 StreamPos := aStream.Position;
6299 SetLength(magic, MAGIC_LEN);
6300 aStream.Read(magic[1], MAGIC_LEN);
6301 aStream.Position := StreamPos;
6302 if (magic <> JPEG_MAGIC) then begin
6307 jpeg := TJPEGImage.Create;
6309 jpeg.LoadFromStream(aStream);
6310 intf := TLazIntfImage.Create(0, 0);
6312 intf.LoadFromBitmap(jpeg.BitmapHandle, jpeg.MaskHandle);
6313 AssignFromLazIntfImage(intf);
6316 aStream.Position := StreamPos;
6324 aStream.Position := StreamPos;
6332 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
6333 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6334 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6336 Surface: PSDL_Surface;
6341 RWops := glBitmapCreateRWops(aStream);
6343 if IMG_isJPG(RWops) > 0 then begin
6344 Surface := IMG_LoadJPG_RW(RWops);
6346 AssignFromSurface(Surface);
6349 SDL_FreeSurface(Surface);
6357 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6358 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6359 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6362 Temp: array[0..1]of Byte;
6364 jpeg: jpeg_decompress_struct;
6365 jpeg_err: jpeg_error_mgr;
6367 IntFormat: TglBitmapFormat;
6369 TempHeight, TempWidth: Integer;
6374 FormatDesc: TFormatDescriptor;
6378 if not init_libJPEG then
6379 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6382 // reading first two bytes to test file and set cursor back to begin
6383 StreamPos := aStream.Position;
6384 aStream.Read({%H-}Temp[0], 2);
6385 aStream.Position := StreamPos;
6387 // if Bitmap then read file.
6388 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6389 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6390 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6393 jpeg.err := jpeg_std_error(@jpeg_err);
6394 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6395 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6397 // decompression struct
6398 jpeg_create_decompress(@jpeg);
6400 // allocation space for streaming methods
6401 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6403 // seeting up custom functions
6404 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6405 pub.init_source := glBitmap_libJPEG_init_source;
6406 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6407 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6408 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6409 pub.term_source := glBitmap_libJPEG_term_source;
6411 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6412 pub.next_input_byte := nil; // until buffer loaded
6414 SrcStream := aStream;
6417 // set global decoding state
6418 jpeg.global_state := DSTATE_START;
6420 // read header of jpeg
6421 jpeg_read_header(@jpeg, false);
6423 // setting output parameter
6424 case jpeg.jpeg_color_space of
6427 jpeg.out_color_space := JCS_GRAYSCALE;
6428 IntFormat := tfLuminance8;
6431 jpeg.out_color_space := JCS_RGB;
6432 IntFormat := tfRGB8;
6436 jpeg_start_decompress(@jpeg);
6438 TempHeight := jpeg.output_height;
6439 TempWidth := jpeg.output_width;
6441 FormatDesc := TFormatDescriptor.Get(IntFormat);
6443 // creating new image
6444 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6448 for Row := 0 to TempHeight -1 do begin
6449 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6450 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6453 // finish decompression
6454 jpeg_finish_decompress(@jpeg);
6456 // destroy decompression
6457 jpeg_destroy_decompress(@jpeg);
6459 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
6463 if Assigned(pImage) then
6473 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6474 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6475 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6480 Temp: array[0..1]of Byte;
6484 // reading first two bytes to test file and set cursor back to begin
6485 StreamPos := aStream.Position;
6486 aStream.Read(Temp[0], 2);
6487 aStream.Position := StreamPos;
6489 // if Bitmap then read file.
6490 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6491 bmp := TBitmap.Create;
6493 jpg := TJPEGImage.Create;
6495 jpg.LoadFromStream(aStream);
6497 result := AssignFromBitmap(bmp);
6509 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6510 {$IF DEFINED(GLB_LAZ_JPEG)}
6511 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6512 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6515 intf: TLazIntfImage;
6517 jpeg := TJPEGImage.Create;
6518 intf := TLazIntfImage.Create(0, 0);
6520 if not AssignToLazIntfImage(intf) then
6521 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6522 jpeg.LoadFromIntfImage(intf);
6523 jpeg.SaveToStream(aStream);
6530 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6531 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6532 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6534 jpeg: jpeg_compress_struct;
6535 jpeg_err: jpeg_error_mgr;
6537 pTemp, pTemp2: pByte;
6539 procedure CopyRow(pDest, pSource: pByte);
6543 for X := 0 to Width - 1 do begin
6544 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6545 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6546 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6553 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6554 raise EglBitmapUnsupportedFormat.Create(Format);
6556 if not init_libJPEG then
6557 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6560 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6561 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6564 jpeg.err := jpeg_std_error(@jpeg_err);
6565 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6566 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6568 // compression struct
6569 jpeg_create_compress(@jpeg);
6571 // allocation space for streaming methods
6572 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6574 // seeting up custom functions
6575 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6576 pub.init_destination := glBitmap_libJPEG_init_destination;
6577 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6578 pub.term_destination := glBitmap_libJPEG_term_destination;
6580 pub.next_output_byte := @DestBuffer[1];
6581 pub.free_in_buffer := Length(DestBuffer);
6583 DestStream := aStream;
6586 // very important state
6587 jpeg.global_state := CSTATE_START;
6588 jpeg.image_width := Width;
6589 jpeg.image_height := Height;
6591 tfAlpha8, tfLuminance8: begin
6592 jpeg.input_components := 1;
6593 jpeg.in_color_space := JCS_GRAYSCALE;
6595 tfRGB8, tfBGR8: begin
6596 jpeg.input_components := 3;
6597 jpeg.in_color_space := JCS_RGB;
6601 jpeg_set_defaults(@jpeg);
6602 jpeg_set_quality(@jpeg, 95, true);
6603 jpeg_start_compress(@jpeg, true);
6606 if Format = tfBGR8 then
6607 GetMem(pTemp2, fRowSize)
6612 for Row := 0 to jpeg.image_height -1 do begin
6614 if Format = tfBGR8 then
6615 CopyRow(pTemp2, pTemp)
6620 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6621 inc(pTemp, fRowSize);
6625 if Format = tfBGR8 then
6628 jpeg_finish_compress(@jpeg);
6629 jpeg_destroy_compress(@jpeg);
6635 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6636 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6637 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6642 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6643 raise EglBitmapUnsupportedFormat.Create(Format);
6645 Bmp := TBitmap.Create;
6647 Jpg := TJPEGImage.Create;
6649 AssignToBitmap(Bmp);
6650 if (Format in [tfAlpha8, tfLuminance8]) then begin
6651 Jpg.Grayscale := true;
6652 Jpg.PixelFormat := jf8Bit;
6655 Jpg.SaveToStream(aStream);
6666 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6667 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6668 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6675 BMP_COMP_BITFIELDS = 3;
6678 TBMPHeader = packed record
6683 bfOffBits: Cardinal;
6686 TBMPInfo = packed record
6692 biCompression: Cardinal;
6693 biSizeImage: Cardinal;
6694 biXPelsPerMeter: Longint;
6695 biYPelsPerMeter: Longint;
6696 biClrUsed: Cardinal;
6697 biClrImportant: Cardinal;
6700 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6701 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6703 //////////////////////////////////////////////////////////////////////////////////////////////////
6704 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6707 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6708 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6711 case aInfo.biCompression of
6713 BMP_COMP_RLE8: begin
6714 raise EglBitmap.Create('RLE compression is not supported');
6716 BMP_COMP_BITFIELDS: begin
6717 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6718 aStream.Read(aMask.r, SizeOf(aMask.r));
6719 aStream.Read(aMask.g, SizeOf(aMask.g));
6720 aStream.Read(aMask.b, SizeOf(aMask.b));
6721 aStream.Read(aMask.a, SizeOf(aMask.a));
6723 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
6727 //get suitable format
6728 case aInfo.biBitCount of
6729 8: result := tfLuminance8;
6730 16: result := tfBGR5;
6731 24: result := tfBGR8;
6732 32: result := tfBGRA8;
6736 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6739 ColorTable: TbmpColorTable;
6742 if (aInfo.biBitCount >= 16) then
6744 aFormat := tfLuminance8;
6745 c := aInfo.biClrUsed;
6747 c := 1 shl aInfo.biBitCount;
6748 SetLength(ColorTable, c);
6749 for i := 0 to c-1 do begin
6750 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6751 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6755 result := TbmpColorTableFormat.Create;
6756 result.PixelSize := aInfo.biBitCount / 8;
6757 result.ColorTable := ColorTable;
6758 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6761 //////////////////////////////////////////////////////////////////////////////////////////////////
6762 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6763 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6765 TmpFormat: TglBitmapFormat;
6766 FormatDesc: TFormatDescriptor;
6769 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6770 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6771 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6772 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6773 aFormat := FormatDesc.Format;
6778 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6779 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6780 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6781 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6783 result := TbmpBitfieldFormat.Create;
6784 result.PixelSize := aInfo.biBitCount / 8;
6785 result.RedMask := aMask.r;
6786 result.GreenMask := aMask.g;
6787 result.BlueMask := aMask.b;
6788 result.AlphaMask := aMask.a;
6795 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6796 PaddingBuff: Cardinal;
6797 LineBuf, ImageData, TmpData: PByte;
6798 SourceMD, DestMD: Pointer;
6799 BmpFormat: TglBitmapFormat;
6802 Mask: TglBitmapColorRec;
6807 SpecialFormat: TFormatDescriptor;
6808 FormatDesc: TFormatDescriptor;
6810 //////////////////////////////////////////////////////////////////////////////////////////////////
6811 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6814 Pixel: TglBitmapPixelData;
6816 aStream.Read(aLineBuf^, rbLineSize);
6817 SpecialFormat.PreparePixel(Pixel);
6818 for i := 0 to Info.biWidth-1 do begin
6819 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6820 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6821 FormatDesc.Map(Pixel, aData, DestMD);
6827 BmpFormat := tfEmpty;
6828 SpecialFormat := nil;
6834 StartPos := aStream.Position;
6835 aStream.Read(Header{%H-}, SizeOf(Header));
6837 if Header.bfType = BMP_MAGIC then begin
6839 BmpFormat := ReadInfo(Info, Mask);
6840 SpecialFormat := ReadColorTable(BmpFormat, Info);
6841 if not Assigned(SpecialFormat) then
6842 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6843 aStream.Position := StartPos + Header.bfOffBits;
6845 if (BmpFormat <> tfEmpty) then begin
6846 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6847 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6848 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6849 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6852 DestMD := FormatDesc.CreateMappingData;
6853 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6854 GetMem(ImageData, ImageSize);
6855 if Assigned(SpecialFormat) then begin
6856 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6857 SourceMD := SpecialFormat.CreateMappingData;
6862 FillChar(ImageData^, ImageSize, $FF);
6863 TmpData := ImageData;
6864 if (Info.biHeight > 0) then
6865 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6866 for i := 0 to Abs(Info.biHeight)-1 do begin
6867 if Assigned(SpecialFormat) then
6868 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6870 aStream.Read(TmpData^, wbLineSize); //else only read data
6871 if (Info.biHeight > 0) then
6872 dec(TmpData, wbLineSize)
6874 inc(TmpData, wbLineSize);
6875 aStream.Read(PaddingBuff{%H-}, Padding);
6877 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method
6880 if Assigned(LineBuf) then
6882 if Assigned(SourceMD) then
6883 SpecialFormat.FreeMappingData(SourceMD);
6884 FormatDesc.FreeMappingData(DestMD);
6887 if Assigned(ImageData) then
6892 raise EglBitmap.Create('LoadBMP - No suitable format found');
6894 aStream.Position := StartPos;
6898 FreeAndNil(SpecialFormat);
6901 else aStream.Position := StartPos;
6904 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6905 procedure TglBitmap.SaveBMP(const aStream: TStream);
6909 Converter: TFormatDescriptor;
6910 FormatDesc: TFormatDescriptor;
6911 SourceFD, DestFD: Pointer;
6912 pData, srcData, dstData, ConvertBuffer: pByte;
6914 Pixel: TglBitmapPixelData;
6915 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6916 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6918 PaddingBuff: Cardinal;
6920 function GetLineWidth : Integer;
6922 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6926 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6927 raise EglBitmapUnsupportedFormat.Create(Format);
6930 FormatDesc := TFormatDescriptor.Get(Format);
6931 ImageSize := FormatDesc.GetSize(Dimension);
6933 FillChar(Header{%H-}, SizeOf(Header), 0);
6934 Header.bfType := BMP_MAGIC;
6935 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6936 Header.bfReserved1 := 0;
6937 Header.bfReserved2 := 0;
6938 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6940 FillChar(Info{%H-}, SizeOf(Info), 0);
6941 Info.biSize := SizeOf(Info);
6942 Info.biWidth := Width;
6943 Info.biHeight := Height;
6945 Info.biCompression := BMP_COMP_RGB;
6946 Info.biSizeImage := ImageSize;
6951 Info.biBitCount := 4;
6952 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6953 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6954 Converter := TbmpColorTableFormat.Create;
6955 with (Converter as TbmpColorTableFormat) do begin
6958 Range := glBitmapColorRec($F, $F, $F, $0);
6963 tfR3G3B2, tfLuminance8: begin
6964 Info.biBitCount := 8;
6965 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6966 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6967 Converter := TbmpColorTableFormat.Create;
6968 with (Converter as TbmpColorTableFormat) do begin
6971 if (Format = tfR3G3B2) then begin
6972 Range := glBitmapColorRec($7, $7, $3, $0);
6973 Shift := glBitmapShiftRec(0, 3, 6, 0);
6975 Range := glBitmapColorRec($FF, $FF, $FF, $0);
6980 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6981 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6982 Info.biBitCount := 16;
6983 Info.biCompression := BMP_COMP_BITFIELDS;
6986 tfBGR8, tfRGB8: begin
6987 Info.biBitCount := 24;
6988 if (Format = tfRGB8) then
6989 Converter := TfdBGR8.Create; //use BGR8 Format Descriptor to Swap RGB Values
6992 tfRGB10, tfRGB10A2, tfRGBA8,
6993 tfBGR10, tfBGR10A2, tfBGRA8: begin
6994 Info.biBitCount := 32;
6995 Info.biCompression := BMP_COMP_BITFIELDS;
6998 raise EglBitmapUnsupportedFormat.Create(Format);
7000 Info.biXPelsPerMeter := 2835;
7001 Info.biYPelsPerMeter := 2835;
7004 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7005 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
7006 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
7008 RedMask := FormatDesc.RedMask;
7009 GreenMask := FormatDesc.GreenMask;
7010 BlueMask := FormatDesc.BlueMask;
7011 AlphaMask := FormatDesc.AlphaMask;
7015 aStream.Write(Header, SizeOf(Header));
7016 aStream.Write(Info, SizeOf(Info));
7019 if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
7020 with (Converter as TbmpColorTableFormat) do
7021 aStream.Write(ColorTable[0].b,
7022 SizeOf(TbmpColorTableEnty) * Length(ColorTable));
7025 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7026 aStream.Write(RedMask, SizeOf(Cardinal));
7027 aStream.Write(GreenMask, SizeOf(Cardinal));
7028 aStream.Write(BlueMask, SizeOf(Cardinal));
7029 aStream.Write(AlphaMask, SizeOf(Cardinal));
7033 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
7034 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
7035 Padding := GetLineWidth - wbLineSize;
7039 inc(pData, (Height-1) * rbLineSize);
7041 // prepare row buffer. But only for RGB because RGBA supports color masks
7042 // so it's possible to change color within the image.
7043 if Assigned(Converter) then begin
7044 FormatDesc.PreparePixel(Pixel);
7045 GetMem(ConvertBuffer, wbLineSize);
7046 SourceFD := FormatDesc.CreateMappingData;
7047 DestFD := Converter.CreateMappingData;
7049 ConvertBuffer := nil;
7052 for LineIdx := 0 to Height - 1 do begin
7054 if Assigned(Converter) then begin
7056 dstData := ConvertBuffer;
7057 for PixelIdx := 0 to Info.biWidth-1 do begin
7058 FormatDesc.Unmap(srcData, Pixel, SourceFD);
7059 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
7060 Converter.Map(Pixel, dstData, DestFD);
7062 aStream.Write(ConvertBuffer^, wbLineSize);
7064 aStream.Write(pData^, rbLineSize);
7066 dec(pData, rbLineSize);
7067 if (Padding > 0) then
7068 aStream.Write(PaddingBuff, Padding);
7071 // destroy row buffer
7072 if Assigned(ConvertBuffer) then begin
7073 FormatDesc.FreeMappingData(SourceFD);
7074 Converter.FreeMappingData(DestFD);
7075 FreeMem(ConvertBuffer);
7079 if Assigned(Converter) then
7084 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7085 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7086 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7088 TTGAHeader = packed record
7092 //ColorMapSpec: Array[0..4] of Byte;
7093 ColorMapStart: Word;
7094 ColorMapLength: Word;
7095 ColorMapEntrySize: Byte;
7105 TGA_UNCOMPRESSED_RGB = 2;
7106 TGA_UNCOMPRESSED_GRAY = 3;
7107 TGA_COMPRESSED_RGB = 10;
7108 TGA_COMPRESSED_GRAY = 11;
7110 TGA_NONE_COLOR_TABLE = 0;
7112 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7113 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
7116 ImageData: System.PByte;
7117 StartPosition: Int64;
7118 PixelSize, LineSize: Integer;
7119 tgaFormat: TglBitmapFormat;
7120 FormatDesc: TFormatDescriptor;
7121 Counter: packed record
7123 low, high, dir: Integer;
7130 ////////////////////////////////////////////////////////////////////////////////////////
7131 procedure ReadUncompressed;
7134 buf, tmp1, tmp2: System.PByte;
7137 if (Counter.X.dir < 0) then
7138 GetMem(buf, LineSize);
7140 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
7142 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
7143 if (Counter.X.dir < 0) then begin //flip X
7144 aStream.Read(buf^, LineSize);
7146 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
7147 for i := 0 to Header.Width-1 do begin //for all pixels in line
7148 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
7153 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
7156 aStream.Read(tmp1^, LineSize);
7157 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
7160 if Assigned(buf) then
7165 ////////////////////////////////////////////////////////////////////////////////////////
7166 procedure ReadCompressed;
7168 /////////////////////////////////////////////////////////////////
7170 TmpData: System.PByte;
7171 LinePixelsRead: Integer;
7172 procedure CheckLine;
7174 if (LinePixelsRead >= Header.Width) then begin
7175 LinePixelsRead := 0;
7176 inc(Counter.Y.low, Counter.Y.dir); //next line index
7177 TmpData := ImageData;
7178 inc(TmpData, Counter.Y.low * LineSize); //set line
7179 if (Counter.X.dir < 0) then //if x flipped then
7180 inc(TmpData, LineSize - PixelSize); //set last pixel
7184 /////////////////////////////////////////////////////////////////
7187 CacheSize, CachePos: Integer;
7188 procedure CachedRead(out Buffer; Count: Integer);
7192 if (CachePos + Count > CacheSize) then begin
7193 //if buffer overflow save non read bytes
7195 if (CacheSize - CachePos > 0) then begin
7196 BytesRead := CacheSize - CachePos;
7197 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
7198 inc(CachePos, BytesRead);
7201 //load cache from file
7202 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
7203 aStream.Read(Cache^, CacheSize);
7206 //read rest of requested bytes
7207 if (Count - BytesRead > 0) then begin
7208 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
7209 inc(CachePos, Count - BytesRead);
7212 //if no buffer overflow just read the data
7213 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
7214 inc(CachePos, Count);
7218 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
7223 inc(aBuffer, Counter.X.dir);
7226 PWord(aBuffer)^ := PWord(aData)^;
7227 inc(aBuffer, 2 * Counter.X.dir);
7230 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
7231 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
7232 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
7233 inc(aBuffer, 3 * Counter.X.dir);
7236 PCardinal(aBuffer)^ := PCardinal(aData)^;
7237 inc(aBuffer, 4 * Counter.X.dir);
7243 TotalPixelsToRead, TotalPixelsRead: Integer;
7245 buf: array [0..3] of Byte; //1 pixel is max 32bit long
7246 PixelRepeat: Boolean;
7247 PixelsToRead, PixelCount: Integer;
7252 TotalPixelsToRead := Header.Width * Header.Height;
7253 TotalPixelsRead := 0;
7254 LinePixelsRead := 0;
7256 GetMem(Cache, CACHE_SIZE);
7258 TmpData := ImageData;
7259 inc(TmpData, Counter.Y.low * LineSize); //set line
7260 if (Counter.X.dir < 0) then //if x flipped then
7261 inc(TmpData, LineSize - PixelSize); //set last pixel
7265 CachedRead(Temp, 1);
7266 PixelRepeat := (Temp and $80) > 0;
7267 PixelsToRead := (Temp and $7F) + 1;
7268 inc(TotalPixelsRead, PixelsToRead);
7271 CachedRead(buf[0], PixelSize);
7272 while (PixelsToRead > 0) do begin
7274 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
7275 while (PixelCount > 0) do begin
7276 if not PixelRepeat then
7277 CachedRead(buf[0], PixelSize);
7278 PixelToBuffer(@buf[0], TmpData);
7279 inc(LinePixelsRead);
7284 until (TotalPixelsRead >= TotalPixelsToRead);
7290 function IsGrayFormat: Boolean;
7292 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
7298 // reading header to test file and set cursor back to begin
7299 StartPosition := aStream.Position;
7300 aStream.Read(Header{%H-}, SizeOf(Header));
7302 // no colormapped files
7303 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
7304 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
7307 if Header.ImageID <> 0 then // skip image ID
7308 aStream.Position := aStream.Position + Header.ImageID;
7310 tgaFormat := tfEmpty;
7312 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
7313 0: tgaFormat := tfLuminance8;
7314 8: tgaFormat := tfAlpha8;
7317 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
7318 0: tgaFormat := tfLuminance16;
7319 8: tgaFormat := tfLuminance8Alpha8;
7320 end else case (Header.ImageDesc and $F) of
7321 0: tgaFormat := tfBGR5;
7322 1: tgaFormat := tfBGR5A1;
7323 4: tgaFormat := tfBGRA4;
7326 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7327 0: tgaFormat := tfBGR8;
7330 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7331 2: tgaFormat := tfBGR10A2;
7332 8: tgaFormat := tfBGRA8;
7336 if (tgaFormat = tfEmpty) then
7337 raise EglBitmap.Create('LoadTga - unsupported format');
7339 FormatDesc := TFormatDescriptor.Get(tgaFormat);
7340 PixelSize := FormatDesc.GetSize(1, 1);
7341 LineSize := FormatDesc.GetSize(Header.Width, 1);
7343 GetMem(ImageData, LineSize * Header.Height);
7346 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7347 Counter.X.low := Header.Height-1;;
7348 Counter.X.high := 0;
7349 Counter.X.dir := -1;
7352 Counter.X.high := Header.Height-1;
7357 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7359 Counter.Y.high := Header.Height-1;
7362 Counter.Y.low := Header.Height-1;;
7363 Counter.Y.high := 0;
7364 Counter.Y.dir := -1;
7368 case Header.ImageType of
7369 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7371 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7375 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method
7378 if Assigned(ImageData) then
7383 aStream.Position := StartPosition;
7386 else aStream.Position := StartPosition;
7389 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7390 procedure TglBitmap.SaveTGA(const aStream: TStream);
7393 LineSize, Size, x, y: Integer;
7394 Pixel: TglBitmapPixelData;
7395 LineBuf, SourceData, DestData: PByte;
7396 SourceMD, DestMD: Pointer;
7397 FormatDesc: TFormatDescriptor;
7398 Converter: TFormatDescriptor;
7400 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7401 raise EglBitmapUnsupportedFormat.Create(Format);
7404 FillChar(Header{%H-}, SizeOf(Header), 0);
7407 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7408 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7409 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7411 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7414 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7416 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7417 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7419 else if (Format in [tfBGR8, tfRGB8]) then
7427 Header.ImageDesc := 1 and $F;
7428 tfRGB10A2, tfBGR10A2:
7429 Header.ImageDesc := 2 and $F;
7431 Header.ImageDesc := 4 and $F;
7432 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7433 Header.ImageDesc := 8 and $F;
7436 Header.Width := Width;
7437 Header.Height := Height;
7438 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7439 aStream.Write(Header, SizeOf(Header));
7441 // convert RGB(A) to BGR(A)
7443 FormatDesc := TFormatDescriptor.Get(Format);
7444 Size := FormatDesc.GetSize(Dimension);
7445 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7446 if (FormatDesc.RGBInverted = tfEmpty) then
7447 raise EglBitmap.Create('inverted RGB format is empty');
7448 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7449 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7450 (Converter.PixelSize <> FormatDesc.PixelSize) then
7451 raise EglBitmap.Create('invalid inverted RGB format');
7454 if Assigned(Converter) then begin
7455 LineSize := FormatDesc.GetSize(Width, 1);
7456 GetMem(LineBuf, LineSize);
7457 SourceMD := FormatDesc.CreateMappingData;
7458 DestMD := Converter.CreateMappingData;
7461 for y := 0 to Height-1 do begin
7462 DestData := LineBuf;
7463 for x := 0 to Width-1 do begin
7464 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7465 Converter.Map(Pixel, DestData, DestMD);
7467 aStream.Write(LineBuf^, LineSize);
7471 FormatDesc.FreeMappingData(SourceMD);
7472 FormatDesc.FreeMappingData(DestMD);
7475 aStream.Write(Data^, Size);
7478 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7479 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7480 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7482 DDS_MAGIC: Cardinal = $20534444;
7484 // DDS_header.dwFlags
7485 DDSD_CAPS = $00000001;
7486 DDSD_HEIGHT = $00000002;
7487 DDSD_WIDTH = $00000004;
7488 DDSD_PIXELFORMAT = $00001000;
7490 // DDS_header.sPixelFormat.dwFlags
7491 DDPF_ALPHAPIXELS = $00000001;
7492 DDPF_ALPHA = $00000002;
7493 DDPF_FOURCC = $00000004;
7494 DDPF_RGB = $00000040;
7495 DDPF_LUMINANCE = $00020000;
7497 // DDS_header.sCaps.dwCaps1
7498 DDSCAPS_TEXTURE = $00001000;
7500 // DDS_header.sCaps.dwCaps2
7501 DDSCAPS2_CUBEMAP = $00000200;
7503 D3DFMT_DXT1 = $31545844;
7504 D3DFMT_DXT3 = $33545844;
7505 D3DFMT_DXT5 = $35545844;
7508 TDDSPixelFormat = packed record
7512 dwRGBBitCount: Cardinal;
7513 dwRBitMask: Cardinal;
7514 dwGBitMask: Cardinal;
7515 dwBBitMask: Cardinal;
7516 dwABitMask: Cardinal;
7519 TDDSCaps = packed record
7523 dwReserved: Cardinal;
7526 TDDSHeader = packed record
7531 dwPitchOrLinearSize: Cardinal;
7533 dwMipMapCount: Cardinal;
7534 dwReserved: array[0..10] of Cardinal;
7535 PixelFormat: TDDSPixelFormat;
7537 dwReserved2: Cardinal;
7540 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7541 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7544 Converter: TbmpBitfieldFormat;
7546 function GetDDSFormat: TglBitmapFormat;
7548 fd: TFormatDescriptor;
7550 Range: TglBitmapColorRec;
7554 with Header.PixelFormat do begin
7556 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7557 case Header.PixelFormat.dwFourCC of
7558 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7559 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7560 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7562 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7564 //find matching format
7565 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7566 fd := TFormatDescriptor.Get(result);
7567 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7568 (8 * fd.PixelSize = dwRGBBitCount) then
7572 //find format with same Range
7573 Range.r := dwRBitMask;
7574 Range.g := dwGBitMask;
7575 Range.b := dwBBitMask;
7576 Range.a := dwABitMask;
7577 for i := 0 to 3 do begin
7578 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7579 Range.arr[i] := Range.arr[i] shr 1;
7581 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7582 fd := TFormatDescriptor.Get(result);
7585 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7593 //no format with same range found -> use default
7594 if (result = tfEmpty) then begin
7595 if (dwABitMask > 0) then
7601 Converter := TbmpBitfieldFormat.Create;
7602 Converter.RedMask := dwRBitMask;
7603 Converter.GreenMask := dwGBitMask;
7604 Converter.BlueMask := dwBBitMask;
7605 Converter.AlphaMask := dwABitMask;
7606 Converter.PixelSize := dwRGBBitCount / 8;
7613 x, y, LineSize, RowSize, Magic: Cardinal;
7614 NewImage, TmpData, RowData, SrcData: System.PByte;
7615 SourceMD, DestMD: Pointer;
7616 Pixel: TglBitmapPixelData;
7617 ddsFormat: TglBitmapFormat;
7618 FormatDesc: TFormatDescriptor;
7623 StreamPos := aStream.Position;
7626 aStream.Read(Magic{%H-}, sizeof(Magic));
7627 if (Magic <> DDS_MAGIC) then begin
7628 aStream.Position := StreamPos;
7633 aStream.Read(Header{%H-}, sizeof(Header));
7634 if (Header.dwSize <> SizeOf(Header)) or
7635 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7636 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7638 aStream.Position := StreamPos;
7642 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7643 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
7645 ddsFormat := GetDDSFormat;
7647 if (ddsFormat = tfEmpty) then
7648 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7650 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7651 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7652 GetMem(NewImage, Header.dwHeight * LineSize);
7654 TmpData := NewImage;
7657 if Assigned(Converter) then begin
7658 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7659 GetMem(RowData, RowSize);
7660 SourceMD := Converter.CreateMappingData;
7661 DestMD := FormatDesc.CreateMappingData;
7663 for y := 0 to Header.dwHeight-1 do begin
7664 TmpData := NewImage;
7665 inc(TmpData, y * LineSize);
7667 aStream.Read(SrcData^, RowSize);
7668 for x := 0 to Header.dwWidth-1 do begin
7669 Converter.Unmap(SrcData, Pixel, SourceMD);
7670 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7671 FormatDesc.Map(Pixel, TmpData, DestMD);
7675 Converter.FreeMappingData(SourceMD);
7676 FormatDesc.FreeMappingData(DestMD);
7682 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7683 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7684 for Y := 0 to Header.dwHeight-1 do begin
7685 aStream.Read(TmpData^, RowSize);
7686 Inc(TmpData, LineSize);
7691 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7692 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7693 for Y := 0 to Header.dwHeight-1 do begin
7694 aStream.Read(TmpData^, RowSize);
7695 Inc(TmpData, LineSize);
7698 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7700 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method
7703 if Assigned(NewImage) then
7708 FreeAndNil(Converter);
7712 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7713 procedure TglBitmap.SaveDDS(const aStream: TStream);
7716 FormatDesc: TFormatDescriptor;
7718 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7719 raise EglBitmapUnsupportedFormat.Create(Format);
7721 FormatDesc := TFormatDescriptor.Get(Format);
7724 FillChar(Header{%H-}, SizeOf(Header), 0);
7725 Header.dwSize := SizeOf(Header);
7726 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7728 Header.dwWidth := Max(1, Width);
7729 Header.dwHeight := Max(1, Height);
7732 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7735 Header.PixelFormat.dwSize := sizeof(Header);
7736 if (FormatDesc.IsCompressed) then begin
7737 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7739 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7740 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7741 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7743 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7744 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7745 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7746 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7747 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7748 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7749 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7750 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7751 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7753 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7754 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7755 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7756 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7757 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7758 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7761 if (FormatDesc.HasAlpha) then
7762 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7764 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7765 aStream.Write(Header, SizeOf(Header));
7766 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7769 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7770 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7771 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7772 procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7773 const aWidth: Integer; const aHeight: Integer);
7778 if (aHeight > 1) then begin
7779 Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1);
7780 GetMem(pTemp, Size);
7782 Move(aData^, pTemp^, Size);
7791 inherited SetDataPointer(pTemp, aFormat, aWidth);
7794 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7795 function TglBitmap1D.FlipHorz: Boolean;
7798 pTempDest, pDest, pSource: PByte;
7800 result := inherited FlipHorz;
7801 if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin
7803 GetMem(pDest, fRowSize);
7806 Inc(pTempDest, fRowSize);
7807 for Col := 0 to Width-1 do begin
7808 dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data
7809 Move(pSource^, pTempDest^, fPixelSize);
7810 Inc(pSource, fPixelSize);
7812 SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method
7815 if Assigned(pDest) then
7822 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7823 procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean);
7825 FormatDesc: TFormatDescriptor;
7828 FormatDesc := TFormatDescriptor.Get(Format);
7829 if FormatDesc.IsCompressed then begin
7830 if not Assigned(glCompressedTexImage1D) then
7831 raise EglBitmap.Create('compressed formats not supported by video adapter');
7832 glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
7833 end else if aBuildWithGlu then
7834 gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7836 glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7839 if (FreeDataAfterGenTexture) then
7843 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7844 procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean);
7846 BuildWithGlu, TexRec: Boolean;
7849 if Assigned(Data) then begin
7850 // Check Texture Size
7851 if (aTestTextureSize) then begin
7852 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7854 if (Width > TexSize) then
7855 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7857 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7858 (Target = GL_TEXTURE_RECTANGLE);
7859 if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7860 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7864 SetupParameters(BuildWithGlu);
7865 UploadData(BuildWithGlu);
7866 glAreTexturesResident(1, @fID, @fIsResident);
7870 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7871 procedure TglBitmap1D.AfterConstruction;
7874 Target := GL_TEXTURE_1D;
7877 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7878 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7879 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7880 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7882 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7883 result := fLines[aIndex]
7888 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7889 procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7890 const aWidth: Integer; const aHeight: Integer);
7892 Idx, LineWidth: Integer;
7894 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7896 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7898 if Assigned(Data) then begin
7899 SetLength(fLines, GetHeight);
7900 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7902 for Idx := 0 to GetHeight-1 do begin
7903 fLines[Idx] := Data;
7904 Inc(fLines[Idx], Idx * LineWidth);
7907 else SetLength(fLines, 0);
7909 SetLength(fLines, 0);
7913 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7914 procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
7916 FormatDesc: TFormatDescriptor;
7918 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7920 FormatDesc := TFormatDescriptor.Get(Format);
7921 if FormatDesc.IsCompressed then begin
7922 if not Assigned(glCompressedTexImage2D) then
7923 raise EglBitmap.Create('compressed formats not supported by video adapter');
7924 glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7925 end else if aBuildWithGlu then begin
7926 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7927 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7929 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7930 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7934 if (FreeDataAfterGenTexture) then
7938 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7939 procedure TglBitmap2D.AfterConstruction;
7942 Target := GL_TEXTURE_2D;
7945 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7946 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7949 Size, w, h: Integer;
7950 FormatDesc: TFormatDescriptor;
7952 FormatDesc := TFormatDescriptor.Get(aFormat);
7953 if FormatDesc.IsCompressed then
7954 raise EglBitmapUnsupportedFormat.Create(aFormat);
7956 w := aRight - aLeft;
7957 h := aBottom - aTop;
7958 Size := FormatDesc.GetSize(w, h);
7961 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7962 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7963 SetDataPointer(Temp, aFormat, w, h); //be careful, Data could be freed by this method
7966 if Assigned(Temp) then
7972 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7973 procedure TglBitmap2D.GetDataFromTexture;
7976 TempWidth, TempHeight: Integer;
7977 TempIntFormat: Cardinal;
7978 IntFormat, f: TglBitmapFormat;
7979 FormatDesc: TFormatDescriptor;
7984 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7985 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7986 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7988 IntFormat := tfEmpty;
7989 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
7990 FormatDesc := TFormatDescriptor.Get(f);
7991 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
7992 IntFormat := FormatDesc.Format;
7997 // Getting data from OpenGL
7998 FormatDesc := TFormatDescriptor.Get(IntFormat);
7999 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
8001 if FormatDesc.IsCompressed then begin
8002 if not Assigned(glGetCompressedTexImage) then
8003 raise EglBitmap.Create('compressed formats not supported by video adapter');
8004 glGetCompressedTexImage(Target, 0, Temp)
8006 glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8007 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
8009 if Assigned(Temp) then
8015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8016 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
8018 BuildWithGlu, PotTex, TexRec: Boolean;
8021 if Assigned(Data) then begin
8022 // Check Texture Size
8023 if (aTestTextureSize) then begin
8024 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8026 if ((Height > TexSize) or (Width > TexSize)) then
8027 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8029 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
8030 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
8031 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8032 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8036 SetupParameters(BuildWithGlu);
8037 UploadData(Target, BuildWithGlu);
8038 glAreTexturesResident(1, @fID, @fIsResident);
8042 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8043 function TglBitmap2D.FlipHorz: Boolean;
8046 TempDestData, DestData, SourceData: PByte;
8049 result := inherited FlipHorz;
8050 if Assigned(Data) then begin
8052 ImgSize := Height * fRowSize;
8053 GetMem(DestData, ImgSize);
8055 TempDestData := DestData;
8056 Dec(TempDestData, fRowSize + fPixelSize);
8057 for Row := 0 to Height -1 do begin
8058 Inc(TempDestData, fRowSize * 2);
8059 for Col := 0 to Width -1 do begin
8060 Move(SourceData^, TempDestData^, fPixelSize);
8061 Inc(SourceData, fPixelSize);
8062 Dec(TempDestData, fPixelSize);
8065 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8068 if Assigned(DestData) then
8075 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8076 function TglBitmap2D.FlipVert: Boolean;
8079 TempDestData, DestData, SourceData: PByte;
8081 result := inherited FlipVert;
8082 if Assigned(Data) then begin
8084 GetMem(DestData, Height * fRowSize);
8086 TempDestData := DestData;
8087 Inc(TempDestData, Width * (Height -1) * fPixelSize);
8088 for Row := 0 to Height -1 do begin
8089 Move(SourceData^, TempDestData^, fRowSize);
8090 Dec(TempDestData, fRowSize);
8091 Inc(SourceData, fRowSize);
8093 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8096 if Assigned(DestData) then
8103 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8104 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8105 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8107 TMatrixItem = record
8112 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
8113 TglBitmapToNormalMapRec = Record
8115 Heights: array of Single;
8116 MatrixU : array of TMatrixItem;
8117 MatrixV : array of TMatrixItem;
8121 ONE_OVER_255 = 1 / 255;
8123 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8124 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
8128 with FuncRec do begin
8130 Source.Data.r * LUMINANCE_WEIGHT_R +
8131 Source.Data.g * LUMINANCE_WEIGHT_G +
8132 Source.Data.b * LUMINANCE_WEIGHT_B;
8133 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
8137 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8138 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
8141 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
8144 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8145 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
8147 TVec = Array[0..2] of Single;
8154 function GetHeight(X, Y: Integer): Single;
8156 with FuncRec do begin
8157 X := Max(0, Min(Size.X -1, X));
8158 Y := Max(0, Min(Size.Y -1, Y));
8159 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
8164 with FuncRec do begin
8165 with PglBitmapToNormalMapRec(Args)^ do begin
8167 for Idx := Low(MatrixU) to High(MatrixU) do
8168 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
8171 for Idx := Low(MatrixU) to High(MatrixU) do
8172 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
8174 Vec[0] := -du * Scale;
8175 Vec[1] := -dv * Scale;
8180 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8181 if Len <> 0 then begin
8182 Vec[0] := Vec[0] * Len;
8183 Vec[1] := Vec[1] * Len;
8184 Vec[2] := Vec[2] * Len;
8188 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
8189 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
8190 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
8194 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8195 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
8197 Rec: TglBitmapToNormalMapRec;
8199 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
8201 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
8202 Matrix[Index].X := X;
8203 Matrix[Index].Y := Y;
8204 Matrix[Index].W := W;
8209 if TFormatDescriptor.Get(Format).IsCompressed then
8210 raise EglBitmapUnsupportedFormat.Create(Format);
8212 if aScale > 100 then
8214 else if aScale < -100 then
8217 Rec.Scale := aScale;
8219 SetLength(Rec.Heights, Width * Height);
8223 SetLength(Rec.MatrixU, 2);
8224 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
8225 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
8227 SetLength(Rec.MatrixV, 2);
8228 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
8229 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
8233 SetLength(Rec.MatrixU, 6);
8234 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
8235 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
8236 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
8237 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
8238 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
8239 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
8241 SetLength(Rec.MatrixV, 6);
8242 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
8243 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
8244 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
8245 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
8246 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
8247 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
8251 SetLength(Rec.MatrixU, 6);
8252 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
8253 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
8254 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
8255 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
8256 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
8257 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
8259 SetLength(Rec.MatrixV, 6);
8260 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
8261 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
8262 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
8263 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
8264 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
8265 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
8269 SetLength(Rec.MatrixU, 20);
8270 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
8271 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
8272 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
8273 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
8274 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
8275 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
8276 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
8277 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
8278 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
8279 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
8280 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
8281 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
8282 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
8283 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
8284 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
8285 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
8286 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
8287 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
8288 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
8289 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
8291 SetLength(Rec.MatrixV, 20);
8292 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
8293 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
8294 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
8295 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
8296 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
8297 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
8298 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
8299 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
8300 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
8301 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
8302 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
8303 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
8304 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
8305 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
8306 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
8307 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
8308 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
8309 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
8310 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
8311 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
8316 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
8317 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
8319 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
8320 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
8322 SetLength(Rec.Heights, 0);
8326 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8327 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8328 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8329 procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean);
8331 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8334 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8335 procedure TglBitmapCubeMap.AfterConstruction;
8339 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8340 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8343 Target := GL_TEXTURE_CUBE_MAP;
8344 fGenMode := GL_REFLECTION_MAP;
8347 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8348 procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean);
8350 BuildWithGlu: Boolean;
8353 if (aTestTextureSize) then begin
8354 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8356 if (Height > TexSize) or (Width > TexSize) then
8357 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8359 if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8360 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8365 SetupParameters(BuildWithGlu);
8366 UploadData(aCubeTarget, BuildWithGlu);
8369 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8370 procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean);
8372 inherited Bind (aEnableTextureUnit);
8373 if aEnableTexCoordsGen then begin
8374 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8375 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8376 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8377 glEnable(GL_TEXTURE_GEN_S);
8378 glEnable(GL_TEXTURE_GEN_T);
8379 glEnable(GL_TEXTURE_GEN_R);
8383 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8384 procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean);
8386 inherited Unbind(aDisableTextureUnit);
8387 if aDisableTexCoordsGen then begin
8388 glDisable(GL_TEXTURE_GEN_S);
8389 glDisable(GL_TEXTURE_GEN_T);
8390 glDisable(GL_TEXTURE_GEN_R);
8394 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8395 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8396 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8398 TVec = Array[0..2] of Single;
8399 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8401 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8402 TglBitmapNormalMapRec = record
8404 Func: TglBitmapNormalMapGetVectorFunc;
8407 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8408 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8410 aVec[0] := aHalfSize;
8411 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8412 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8416 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8418 aVec[0] := - aHalfSize;
8419 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8420 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8423 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8424 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8426 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8427 aVec[1] := aHalfSize;
8428 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8431 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8432 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8434 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8435 aVec[1] := - aHalfSize;
8436 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8439 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8440 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8442 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8443 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8444 aVec[2] := aHalfSize;
8447 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8448 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8450 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8451 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8452 aVec[2] := - aHalfSize;
8455 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8456 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8462 with FuncRec do begin
8463 with PglBitmapNormalMapRec(Args)^ do begin
8464 Func(Vec, Position, HalfSize);
8467 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8468 if Len <> 0 then begin
8469 Vec[0] := Vec[0] * Len;
8470 Vec[1] := Vec[1] * Len;
8471 Vec[2] := Vec[2] * Len;
8474 // Scale Vector and AddVectro
8475 Vec[0] := Vec[0] * 0.5 + 0.5;
8476 Vec[1] := Vec[1] * 0.5 + 0.5;
8477 Vec[2] := Vec[2] * 0.5 + 0.5;
8482 Dest.Data.arr[i] := Round(Vec[i] * 255);
8486 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8487 procedure TglBitmapNormalMap.AfterConstruction;
8490 fGenMode := GL_NORMAL_MAP;
8493 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8494 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean);
8496 Rec: TglBitmapNormalMapRec;
8497 SizeRec: TglBitmapPixelPosition;
8499 Rec.HalfSize := aSize div 2;
8500 FreeDataAfterGenTexture := false;
8502 SizeRec.Fields := [ffX, ffY];
8507 Rec.Func := glBitmapNormalMapPosX;
8508 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8509 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize);
8512 Rec.Func := glBitmapNormalMapNegX;
8513 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8514 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize);
8517 Rec.Func := glBitmapNormalMapPosY;
8518 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8519 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize);
8522 Rec.Func := glBitmapNormalMapNegY;
8523 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8524 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize);
8527 Rec.Func := glBitmapNormalMapPosZ;
8528 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8529 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize);
8532 Rec.Func := glBitmapNormalMapNegZ;
8533 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8534 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize);
8539 glBitmapSetDefaultFormat (tfEmpty);
8540 glBitmapSetDefaultMipmap (mmMipmap);
8541 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8542 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8543 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8545 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8546 glBitmapSetDefaultDeleteTextureOnFree (true);
8548 TFormatDescriptor.Init;
8550 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8551 OpenGLInitialized := false;
8552 InitOpenGLCS := TCriticalSection.Create;
8556 TFormatDescriptor.Finalize;
8558 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8559 FreeAndNil(InitOpenGLCS);