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.RedMask or FormatDesc.GreenMask or FormatDesc.BlueMask or FormatDesc.AlphaMask);
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;
5982 png := TPortableNetworkGraphic.Create;
5983 intf := TLazIntfImage.Create(0, 0);
5985 if not AssignToLazIntfImage(intf) then
5986 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
5987 intf.GetRawImage(raw);
5988 png.LoadFromRawImage(raw, false);
5989 png.SaveToStream(aStream);
5996 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5997 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5998 procedure TglBitmap.SavePNG(const aStream: TStream);
6001 png_info: png_infop;
6002 png_rows: array of pByte;
6006 FormatDesc: TFormatDescriptor;
6008 if not (ftPNG in FormatGetSupportedFiles(Format)) then
6009 raise EglBitmapUnsupportedFormat.Create(Format);
6011 if not init_libPNG then
6012 raise Exception.Create('unable to initialize libPNG.');
6016 tfAlpha8, tfLuminance8:
6017 ColorType := PNG_COLOR_TYPE_GRAY;
6019 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
6021 ColorType := PNG_COLOR_TYPE_RGB;
6023 ColorType := PNG_COLOR_TYPE_RGBA;
6025 raise EglBitmapUnsupportedFormat.Create(Format);
6028 FormatDesc := TFormatDescriptor.Get(Format);
6029 LineSize := FormatDesc.GetSize(Width, 1);
6031 // creating array for scanline
6032 SetLength(png_rows, Height);
6034 for Row := 0 to Height - 1 do begin
6035 png_rows[Row] := Data;
6036 Inc(png_rows[Row], Row * LineSize)
6040 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
6042 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
6045 png_info := png_create_info_struct(png);
6046 if png_info = nil then begin
6047 png_destroy_write_struct(@png, nil);
6048 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
6051 // set read callback
6052 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
6055 png_set_compression_level(png, 6);
6057 if Format in [tfBGR8, tfBGRA8] then
6060 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
6061 png_write_info(png, png_info);
6062 png_write_image(png, @png_rows[0]);
6063 png_write_end(png, png_info);
6064 png_destroy_write_struct(@png, @png_info);
6066 SetLength(png_rows, 0);
6073 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
6074 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6075 procedure TglBitmap.SavePNG(const aStream: TStream);
6079 pSource, pDest: pByte;
6080 X, Y, PixSize: Integer;
6081 ColorType: Cardinal;
6087 if not (ftPNG in FormatGetSupportedFiles (Format)) then
6088 raise EglBitmapUnsupportedFormat.Create(Format);
6091 tfAlpha8, tfLuminance8: begin
6092 ColorType := COLOR_GRAYSCALE;
6096 tfLuminance8Alpha8: begin
6097 ColorType := COLOR_GRAYSCALEALPHA;
6101 tfBGR8, tfRGB8: begin
6102 ColorType := COLOR_RGB;
6106 tfBGRA8, tfRGBA8: begin
6107 ColorType := COLOR_RGBALPHA;
6112 raise EglBitmapUnsupportedFormat.Create(Format);
6115 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
6119 for Y := 0 to Height -1 do begin
6120 pDest := png.ScanLine[Y];
6121 for X := 0 to Width -1 do begin
6122 Move(pSource^, pDest^, PixSize);
6123 Inc(pDest, PixSize);
6124 Inc(pSource, PixSize);
6126 png.AlphaScanline[Y]^[X] := pSource^;
6131 // convert RGB line to BGR
6132 if Format in [tfRGB8, tfRGBA8] then begin
6133 pTemp := png.ScanLine[Y];
6134 for X := 0 to Width -1 do begin
6135 Temp := pByteArray(pTemp)^[0];
6136 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
6137 pByteArray(pTemp)^[2] := Temp;
6144 Png.CompressionLevel := 6;
6145 Png.SaveToStream(aStream);
6153 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6154 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6156 {$IFDEF GLB_LIB_JPEG}
6158 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
6159 glBitmap_libJPEG_source_mgr = record
6160 pub: jpeg_source_mgr;
6163 SrcBuffer: array [1..4096] of byte;
6166 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
6167 glBitmap_libJPEG_dest_mgr = record
6168 pub: jpeg_destination_mgr;
6170 DestStream: TStream;
6171 DestBuffer: array [1..4096] of byte;
6174 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
6180 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
6186 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
6191 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
6197 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
6203 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6204 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
6206 src: glBitmap_libJPEG_source_mgr_ptr;
6209 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6211 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
6212 if (bytes <= 0) then begin
6213 src^.SrcBuffer[1] := $FF;
6214 src^.SrcBuffer[2] := JPEG_EOI;
6218 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
6219 src^.pub.bytes_in_buffer := bytes;
6224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6225 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
6227 src: glBitmap_libJPEG_source_mgr_ptr;
6229 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6231 if num_bytes > 0 then begin
6232 // wanted byte isn't in buffer so set stream position and read buffer
6233 if num_bytes > src^.pub.bytes_in_buffer then begin
6234 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
6235 src^.pub.fill_input_buffer(cinfo);
6237 // wanted byte is in buffer so only skip
6238 inc(src^.pub.next_input_byte, num_bytes);
6239 dec(src^.pub.bytes_in_buffer, num_bytes);
6244 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6245 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
6247 dest: glBitmap_libJPEG_dest_mgr_ptr;
6249 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6251 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
6252 // write complete buffer
6253 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
6256 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
6257 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
6263 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6264 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
6267 dest: glBitmap_libJPEG_dest_mgr_ptr;
6269 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6271 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6272 // check for endblock
6273 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6275 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6280 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6285 {$IFDEF GLB_SUPPORT_JPEG_READ}
6286 {$IF DEFINED(GLB_LAZ_JPEG)}
6287 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6288 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6291 JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
6294 intf: TLazIntfImage;
6296 magic: String[MAGIC_LEN];
6299 StreamPos := aStream.Position;
6301 SetLength(magic, MAGIC_LEN);
6302 aStream.Read(magic[1], MAGIC_LEN);
6303 aStream.Position := StreamPos;
6304 if (magic <> JPEG_MAGIC) then begin
6309 jpeg := TJPEGImage.Create;
6311 jpeg.LoadFromStream(aStream);
6312 intf := TLazIntfImage.Create(0, 0);
6314 intf.LoadFromBitmap(jpeg.BitmapHandle, jpeg.MaskHandle);
6315 AssignFromLazIntfImage(intf);
6318 aStream.Position := StreamPos;
6326 aStream.Position := StreamPos;
6334 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
6335 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6336 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6338 Surface: PSDL_Surface;
6343 RWops := glBitmapCreateRWops(aStream);
6345 if IMG_isJPG(RWops) > 0 then begin
6346 Surface := IMG_LoadJPG_RW(RWops);
6348 AssignFromSurface(Surface);
6351 SDL_FreeSurface(Surface);
6359 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6360 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6361 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6364 Temp: array[0..1]of Byte;
6366 jpeg: jpeg_decompress_struct;
6367 jpeg_err: jpeg_error_mgr;
6369 IntFormat: TglBitmapFormat;
6371 TempHeight, TempWidth: Integer;
6376 FormatDesc: TFormatDescriptor;
6380 if not init_libJPEG then
6381 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6384 // reading first two bytes to test file and set cursor back to begin
6385 StreamPos := aStream.Position;
6386 aStream.Read({%H-}Temp[0], 2);
6387 aStream.Position := StreamPos;
6389 // if Bitmap then read file.
6390 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6391 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6392 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6395 jpeg.err := jpeg_std_error(@jpeg_err);
6396 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6397 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6399 // decompression struct
6400 jpeg_create_decompress(@jpeg);
6402 // allocation space for streaming methods
6403 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6405 // seeting up custom functions
6406 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6407 pub.init_source := glBitmap_libJPEG_init_source;
6408 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6409 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6410 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6411 pub.term_source := glBitmap_libJPEG_term_source;
6413 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6414 pub.next_input_byte := nil; // until buffer loaded
6416 SrcStream := aStream;
6419 // set global decoding state
6420 jpeg.global_state := DSTATE_START;
6422 // read header of jpeg
6423 jpeg_read_header(@jpeg, false);
6425 // setting output parameter
6426 case jpeg.jpeg_color_space of
6429 jpeg.out_color_space := JCS_GRAYSCALE;
6430 IntFormat := tfLuminance8;
6433 jpeg.out_color_space := JCS_RGB;
6434 IntFormat := tfRGB8;
6438 jpeg_start_decompress(@jpeg);
6440 TempHeight := jpeg.output_height;
6441 TempWidth := jpeg.output_width;
6443 FormatDesc := TFormatDescriptor.Get(IntFormat);
6445 // creating new image
6446 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6450 for Row := 0 to TempHeight -1 do begin
6451 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6452 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6455 // finish decompression
6456 jpeg_finish_decompress(@jpeg);
6458 // destroy decompression
6459 jpeg_destroy_decompress(@jpeg);
6461 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
6465 if Assigned(pImage) then
6475 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6476 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6477 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6482 Temp: array[0..1]of Byte;
6486 // reading first two bytes to test file and set cursor back to begin
6487 StreamPos := aStream.Position;
6488 aStream.Read(Temp[0], 2);
6489 aStream.Position := StreamPos;
6491 // if Bitmap then read file.
6492 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6493 bmp := TBitmap.Create;
6495 jpg := TJPEGImage.Create;
6497 jpg.LoadFromStream(aStream);
6499 result := AssignFromBitmap(bmp);
6511 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6512 {$IF DEFINED(GLB_LAZ_JPEG)}
6513 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6514 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6517 intf: TLazIntfImage;
6520 jpeg := TJPEGImage.Create;
6521 intf := TLazIntfImage.Create(0, 0);
6523 if not AssignToLazIntfImage(intf) then
6524 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6525 intf.GetRawImage(raw);
6526 jpeg.LoadFromRawImage(raw, false);
6527 jpeg.SaveToStream(aStream);
6534 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6535 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6536 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6538 jpeg: jpeg_compress_struct;
6539 jpeg_err: jpeg_error_mgr;
6541 pTemp, pTemp2: pByte;
6543 procedure CopyRow(pDest, pSource: pByte);
6547 for X := 0 to Width - 1 do begin
6548 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6549 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6550 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6557 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6558 raise EglBitmapUnsupportedFormat.Create(Format);
6560 if not init_libJPEG then
6561 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6564 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6565 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6568 jpeg.err := jpeg_std_error(@jpeg_err);
6569 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6570 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6572 // compression struct
6573 jpeg_create_compress(@jpeg);
6575 // allocation space for streaming methods
6576 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6578 // seeting up custom functions
6579 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6580 pub.init_destination := glBitmap_libJPEG_init_destination;
6581 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6582 pub.term_destination := glBitmap_libJPEG_term_destination;
6584 pub.next_output_byte := @DestBuffer[1];
6585 pub.free_in_buffer := Length(DestBuffer);
6587 DestStream := aStream;
6590 // very important state
6591 jpeg.global_state := CSTATE_START;
6592 jpeg.image_width := Width;
6593 jpeg.image_height := Height;
6595 tfAlpha8, tfLuminance8: begin
6596 jpeg.input_components := 1;
6597 jpeg.in_color_space := JCS_GRAYSCALE;
6599 tfRGB8, tfBGR8: begin
6600 jpeg.input_components := 3;
6601 jpeg.in_color_space := JCS_RGB;
6605 jpeg_set_defaults(@jpeg);
6606 jpeg_set_quality(@jpeg, 95, true);
6607 jpeg_start_compress(@jpeg, true);
6610 if Format = tfBGR8 then
6611 GetMem(pTemp2, fRowSize)
6616 for Row := 0 to jpeg.image_height -1 do begin
6618 if Format = tfBGR8 then
6619 CopyRow(pTemp2, pTemp)
6624 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6625 inc(pTemp, fRowSize);
6629 if Format = tfBGR8 then
6632 jpeg_finish_compress(@jpeg);
6633 jpeg_destroy_compress(@jpeg);
6639 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6640 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6641 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6646 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6647 raise EglBitmapUnsupportedFormat.Create(Format);
6649 Bmp := TBitmap.Create;
6651 Jpg := TJPEGImage.Create;
6653 AssignToBitmap(Bmp);
6654 if (Format in [tfAlpha8, tfLuminance8]) then begin
6655 Jpg.Grayscale := true;
6656 Jpg.PixelFormat := jf8Bit;
6659 Jpg.SaveToStream(aStream);
6670 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6671 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6672 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6679 BMP_COMP_BITFIELDS = 3;
6682 TBMPHeader = packed record
6687 bfOffBits: Cardinal;
6690 TBMPInfo = packed record
6696 biCompression: Cardinal;
6697 biSizeImage: Cardinal;
6698 biXPelsPerMeter: Longint;
6699 biYPelsPerMeter: Longint;
6700 biClrUsed: Cardinal;
6701 biClrImportant: Cardinal;
6704 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6705 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6707 //////////////////////////////////////////////////////////////////////////////////////////////////
6708 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6711 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6712 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6715 case aInfo.biCompression of
6717 BMP_COMP_RLE8: begin
6718 raise EglBitmap.Create('RLE compression is not supported');
6720 BMP_COMP_BITFIELDS: begin
6721 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6722 aStream.Read(aMask.r, SizeOf(aMask.r));
6723 aStream.Read(aMask.g, SizeOf(aMask.g));
6724 aStream.Read(aMask.b, SizeOf(aMask.b));
6725 aStream.Read(aMask.a, SizeOf(aMask.a));
6727 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
6731 //get suitable format
6732 case aInfo.biBitCount of
6733 8: result := tfLuminance8;
6734 16: result := tfBGR5;
6735 24: result := tfBGR8;
6736 32: result := tfBGRA8;
6740 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6743 ColorTable: TbmpColorTable;
6746 if (aInfo.biBitCount >= 16) then
6748 aFormat := tfLuminance8;
6749 c := aInfo.biClrUsed;
6751 c := 1 shl aInfo.biBitCount;
6752 SetLength(ColorTable, c);
6753 for i := 0 to c-1 do begin
6754 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6755 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6759 result := TbmpColorTableFormat.Create;
6760 result.PixelSize := aInfo.biBitCount / 8;
6761 result.ColorTable := ColorTable;
6762 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6765 //////////////////////////////////////////////////////////////////////////////////////////////////
6766 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6767 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6769 TmpFormat: TglBitmapFormat;
6770 FormatDesc: TFormatDescriptor;
6773 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6774 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6775 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6776 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6777 aFormat := FormatDesc.Format;
6782 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6783 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6784 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6785 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6787 result := TbmpBitfieldFormat.Create;
6788 result.PixelSize := aInfo.biBitCount / 8;
6789 result.RedMask := aMask.r;
6790 result.GreenMask := aMask.g;
6791 result.BlueMask := aMask.b;
6792 result.AlphaMask := aMask.a;
6799 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6800 PaddingBuff: Cardinal;
6801 LineBuf, ImageData, TmpData: PByte;
6802 SourceMD, DestMD: Pointer;
6803 BmpFormat: TglBitmapFormat;
6806 Mask: TglBitmapColorRec;
6811 SpecialFormat: TFormatDescriptor;
6812 FormatDesc: TFormatDescriptor;
6814 //////////////////////////////////////////////////////////////////////////////////////////////////
6815 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6818 Pixel: TglBitmapPixelData;
6820 aStream.Read(aLineBuf^, rbLineSize);
6821 SpecialFormat.PreparePixel(Pixel);
6822 for i := 0 to Info.biWidth-1 do begin
6823 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6824 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6825 FormatDesc.Map(Pixel, aData, DestMD);
6831 BmpFormat := tfEmpty;
6832 SpecialFormat := nil;
6838 StartPos := aStream.Position;
6839 aStream.Read(Header{%H-}, SizeOf(Header));
6841 if Header.bfType = BMP_MAGIC then begin
6843 BmpFormat := ReadInfo(Info, Mask);
6844 SpecialFormat := ReadColorTable(BmpFormat, Info);
6845 if not Assigned(SpecialFormat) then
6846 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6847 aStream.Position := StartPos + Header.bfOffBits;
6849 if (BmpFormat <> tfEmpty) then begin
6850 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6851 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6852 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6853 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6856 DestMD := FormatDesc.CreateMappingData;
6857 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6858 GetMem(ImageData, ImageSize);
6859 if Assigned(SpecialFormat) then begin
6860 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6861 SourceMD := SpecialFormat.CreateMappingData;
6866 FillChar(ImageData^, ImageSize, $FF);
6867 TmpData := ImageData;
6868 if (Info.biHeight > 0) then
6869 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6870 for i := 0 to Abs(Info.biHeight)-1 do begin
6871 if Assigned(SpecialFormat) then
6872 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6874 aStream.Read(TmpData^, wbLineSize); //else only read data
6875 if (Info.biHeight > 0) then
6876 dec(TmpData, wbLineSize)
6878 inc(TmpData, wbLineSize);
6879 aStream.Read(PaddingBuff{%H-}, Padding);
6881 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method
6884 if Assigned(LineBuf) then
6886 if Assigned(SourceMD) then
6887 SpecialFormat.FreeMappingData(SourceMD);
6888 FormatDesc.FreeMappingData(DestMD);
6891 if Assigned(ImageData) then
6896 raise EglBitmap.Create('LoadBMP - No suitable format found');
6898 aStream.Position := StartPos;
6902 FreeAndNil(SpecialFormat);
6905 else aStream.Position := StartPos;
6908 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6909 procedure TglBitmap.SaveBMP(const aStream: TStream);
6913 Converter: TFormatDescriptor;
6914 FormatDesc: TFormatDescriptor;
6915 SourceFD, DestFD: Pointer;
6916 pData, srcData, dstData, ConvertBuffer: pByte;
6918 Pixel: TglBitmapPixelData;
6919 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6920 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6922 PaddingBuff: Cardinal;
6924 function GetLineWidth : Integer;
6926 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6930 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6931 raise EglBitmapUnsupportedFormat.Create(Format);
6934 FormatDesc := TFormatDescriptor.Get(Format);
6935 ImageSize := FormatDesc.GetSize(Dimension);
6937 FillChar(Header{%H-}, SizeOf(Header), 0);
6938 Header.bfType := BMP_MAGIC;
6939 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6940 Header.bfReserved1 := 0;
6941 Header.bfReserved2 := 0;
6942 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6944 FillChar(Info{%H-}, SizeOf(Info), 0);
6945 Info.biSize := SizeOf(Info);
6946 Info.biWidth := Width;
6947 Info.biHeight := Height;
6949 Info.biCompression := BMP_COMP_RGB;
6950 Info.biSizeImage := ImageSize;
6955 Info.biBitCount := 4;
6956 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6957 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6958 Converter := TbmpColorTableFormat.Create;
6959 with (Converter as TbmpColorTableFormat) do begin
6962 Range := glBitmapColorRec($F, $F, $F, $0);
6967 tfR3G3B2, tfLuminance8: begin
6968 Info.biBitCount := 8;
6969 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6970 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6971 Converter := TbmpColorTableFormat.Create;
6972 with (Converter as TbmpColorTableFormat) do begin
6975 if (Format = tfR3G3B2) then begin
6976 Range := glBitmapColorRec($7, $7, $3, $0);
6977 Shift := glBitmapShiftRec(0, 3, 6, 0);
6979 Range := glBitmapColorRec($FF, $FF, $FF, $0);
6984 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6985 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6986 Info.biBitCount := 16;
6987 Info.biCompression := BMP_COMP_BITFIELDS;
6990 tfBGR8, tfRGB8: begin
6991 Info.biBitCount := 24;
6992 if (Format = tfRGB8) then
6993 Converter := TfdBGR8.Create; //use BGR8 Format Descriptor to Swap RGB Values
6996 tfRGB10, tfRGB10A2, tfRGBA8,
6997 tfBGR10, tfBGR10A2, tfBGRA8: begin
6998 Info.biBitCount := 32;
6999 Info.biCompression := BMP_COMP_BITFIELDS;
7002 raise EglBitmapUnsupportedFormat.Create(Format);
7004 Info.biXPelsPerMeter := 2835;
7005 Info.biYPelsPerMeter := 2835;
7008 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7009 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
7010 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
7012 RedMask := FormatDesc.RedMask;
7013 GreenMask := FormatDesc.GreenMask;
7014 BlueMask := FormatDesc.BlueMask;
7015 AlphaMask := FormatDesc.AlphaMask;
7019 aStream.Write(Header, SizeOf(Header));
7020 aStream.Write(Info, SizeOf(Info));
7023 if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
7024 with (Converter as TbmpColorTableFormat) do
7025 aStream.Write(ColorTable[0].b,
7026 SizeOf(TbmpColorTableEnty) * Length(ColorTable));
7029 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7030 aStream.Write(RedMask, SizeOf(Cardinal));
7031 aStream.Write(GreenMask, SizeOf(Cardinal));
7032 aStream.Write(BlueMask, SizeOf(Cardinal));
7033 aStream.Write(AlphaMask, SizeOf(Cardinal));
7037 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
7038 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
7039 Padding := GetLineWidth - wbLineSize;
7043 inc(pData, (Height-1) * rbLineSize);
7045 // prepare row buffer. But only for RGB because RGBA supports color masks
7046 // so it's possible to change color within the image.
7047 if Assigned(Converter) then begin
7048 FormatDesc.PreparePixel(Pixel);
7049 GetMem(ConvertBuffer, wbLineSize);
7050 SourceFD := FormatDesc.CreateMappingData;
7051 DestFD := Converter.CreateMappingData;
7053 ConvertBuffer := nil;
7056 for LineIdx := 0 to Height - 1 do begin
7058 if Assigned(Converter) then begin
7060 dstData := ConvertBuffer;
7061 for PixelIdx := 0 to Info.biWidth-1 do begin
7062 FormatDesc.Unmap(srcData, Pixel, SourceFD);
7063 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
7064 Converter.Map(Pixel, dstData, DestFD);
7066 aStream.Write(ConvertBuffer^, wbLineSize);
7068 aStream.Write(pData^, rbLineSize);
7070 dec(pData, rbLineSize);
7071 if (Padding > 0) then
7072 aStream.Write(PaddingBuff, Padding);
7075 // destroy row buffer
7076 if Assigned(ConvertBuffer) then begin
7077 FormatDesc.FreeMappingData(SourceFD);
7078 Converter.FreeMappingData(DestFD);
7079 FreeMem(ConvertBuffer);
7083 if Assigned(Converter) then
7088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7089 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7090 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7092 TTGAHeader = packed record
7096 //ColorMapSpec: Array[0..4] of Byte;
7097 ColorMapStart: Word;
7098 ColorMapLength: Word;
7099 ColorMapEntrySize: Byte;
7109 TGA_UNCOMPRESSED_RGB = 2;
7110 TGA_UNCOMPRESSED_GRAY = 3;
7111 TGA_COMPRESSED_RGB = 10;
7112 TGA_COMPRESSED_GRAY = 11;
7114 TGA_NONE_COLOR_TABLE = 0;
7116 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7117 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
7120 ImageData: System.PByte;
7121 StartPosition: Int64;
7122 PixelSize, LineSize: Integer;
7123 tgaFormat: TglBitmapFormat;
7124 FormatDesc: TFormatDescriptor;
7125 Counter: packed record
7127 low, high, dir: Integer;
7134 ////////////////////////////////////////////////////////////////////////////////////////
7135 procedure ReadUncompressed;
7138 buf, tmp1, tmp2: System.PByte;
7141 if (Counter.X.dir < 0) then
7142 GetMem(buf, LineSize);
7144 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
7146 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
7147 if (Counter.X.dir < 0) then begin //flip X
7148 aStream.Read(buf^, LineSize);
7150 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
7151 for i := 0 to Header.Width-1 do begin //for all pixels in line
7152 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
7157 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
7160 aStream.Read(tmp1^, LineSize);
7161 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
7164 if Assigned(buf) then
7169 ////////////////////////////////////////////////////////////////////////////////////////
7170 procedure ReadCompressed;
7172 /////////////////////////////////////////////////////////////////
7174 TmpData: System.PByte;
7175 LinePixelsRead: Integer;
7176 procedure CheckLine;
7178 if (LinePixelsRead >= Header.Width) then begin
7179 LinePixelsRead := 0;
7180 inc(Counter.Y.low, Counter.Y.dir); //next line index
7181 TmpData := ImageData;
7182 inc(TmpData, Counter.Y.low * LineSize); //set line
7183 if (Counter.X.dir < 0) then //if x flipped then
7184 inc(TmpData, LineSize - PixelSize); //set last pixel
7188 /////////////////////////////////////////////////////////////////
7191 CacheSize, CachePos: Integer;
7192 procedure CachedRead(out Buffer; Count: Integer);
7196 if (CachePos + Count > CacheSize) then begin
7197 //if buffer overflow save non read bytes
7199 if (CacheSize - CachePos > 0) then begin
7200 BytesRead := CacheSize - CachePos;
7201 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
7202 inc(CachePos, BytesRead);
7205 //load cache from file
7206 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
7207 aStream.Read(Cache^, CacheSize);
7210 //read rest of requested bytes
7211 if (Count - BytesRead > 0) then begin
7212 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
7213 inc(CachePos, Count - BytesRead);
7216 //if no buffer overflow just read the data
7217 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
7218 inc(CachePos, Count);
7222 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
7227 inc(aBuffer, Counter.X.dir);
7230 PWord(aBuffer)^ := PWord(aData)^;
7231 inc(aBuffer, 2 * Counter.X.dir);
7234 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
7235 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
7236 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
7237 inc(aBuffer, 3 * Counter.X.dir);
7240 PCardinal(aBuffer)^ := PCardinal(aData)^;
7241 inc(aBuffer, 4 * Counter.X.dir);
7247 TotalPixelsToRead, TotalPixelsRead: Integer;
7249 buf: array [0..3] of Byte; //1 pixel is max 32bit long
7250 PixelRepeat: Boolean;
7251 PixelsToRead, PixelCount: Integer;
7256 TotalPixelsToRead := Header.Width * Header.Height;
7257 TotalPixelsRead := 0;
7258 LinePixelsRead := 0;
7260 GetMem(Cache, CACHE_SIZE);
7262 TmpData := ImageData;
7263 inc(TmpData, Counter.Y.low * LineSize); //set line
7264 if (Counter.X.dir < 0) then //if x flipped then
7265 inc(TmpData, LineSize - PixelSize); //set last pixel
7269 CachedRead(Temp, 1);
7270 PixelRepeat := (Temp and $80) > 0;
7271 PixelsToRead := (Temp and $7F) + 1;
7272 inc(TotalPixelsRead, PixelsToRead);
7275 CachedRead(buf[0], PixelSize);
7276 while (PixelsToRead > 0) do begin
7278 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
7279 while (PixelCount > 0) do begin
7280 if not PixelRepeat then
7281 CachedRead(buf[0], PixelSize);
7282 PixelToBuffer(@buf[0], TmpData);
7283 inc(LinePixelsRead);
7288 until (TotalPixelsRead >= TotalPixelsToRead);
7294 function IsGrayFormat: Boolean;
7296 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
7302 // reading header to test file and set cursor back to begin
7303 StartPosition := aStream.Position;
7304 aStream.Read(Header{%H-}, SizeOf(Header));
7306 // no colormapped files
7307 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
7308 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
7311 if Header.ImageID <> 0 then // skip image ID
7312 aStream.Position := aStream.Position + Header.ImageID;
7314 tgaFormat := tfEmpty;
7316 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
7317 0: tgaFormat := tfLuminance8;
7318 8: tgaFormat := tfAlpha8;
7321 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
7322 0: tgaFormat := tfLuminance16;
7323 8: tgaFormat := tfLuminance8Alpha8;
7324 end else case (Header.ImageDesc and $F) of
7325 0: tgaFormat := tfBGR5;
7326 1: tgaFormat := tfBGR5A1;
7327 4: tgaFormat := tfBGRA4;
7330 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7331 0: tgaFormat := tfBGR8;
7334 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7335 2: tgaFormat := tfBGR10A2;
7336 8: tgaFormat := tfBGRA8;
7340 if (tgaFormat = tfEmpty) then
7341 raise EglBitmap.Create('LoadTga - unsupported format');
7343 FormatDesc := TFormatDescriptor.Get(tgaFormat);
7344 PixelSize := FormatDesc.GetSize(1, 1);
7345 LineSize := FormatDesc.GetSize(Header.Width, 1);
7347 GetMem(ImageData, LineSize * Header.Height);
7350 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7351 Counter.X.low := Header.Height-1;;
7352 Counter.X.high := 0;
7353 Counter.X.dir := -1;
7356 Counter.X.high := Header.Height-1;
7361 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7363 Counter.Y.high := Header.Height-1;
7366 Counter.Y.low := Header.Height-1;;
7367 Counter.Y.high := 0;
7368 Counter.Y.dir := -1;
7372 case Header.ImageType of
7373 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7375 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7379 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method
7382 if Assigned(ImageData) then
7387 aStream.Position := StartPosition;
7390 else aStream.Position := StartPosition;
7393 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7394 procedure TglBitmap.SaveTGA(const aStream: TStream);
7397 LineSize, Size, x, y: Integer;
7398 Pixel: TglBitmapPixelData;
7399 LineBuf, SourceData, DestData: PByte;
7400 SourceMD, DestMD: Pointer;
7401 FormatDesc: TFormatDescriptor;
7402 Converter: TFormatDescriptor;
7404 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7405 raise EglBitmapUnsupportedFormat.Create(Format);
7408 FillChar(Header{%H-}, SizeOf(Header), 0);
7411 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7412 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7413 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7415 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7418 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7420 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7421 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7423 else if (Format in [tfBGR8, tfRGB8]) then
7431 Header.ImageDesc := 1 and $F;
7432 tfRGB10A2, tfBGR10A2:
7433 Header.ImageDesc := 2 and $F;
7435 Header.ImageDesc := 4 and $F;
7436 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7437 Header.ImageDesc := 8 and $F;
7440 Header.Width := Width;
7441 Header.Height := Height;
7442 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7443 aStream.Write(Header, SizeOf(Header));
7445 // convert RGB(A) to BGR(A)
7447 FormatDesc := TFormatDescriptor.Get(Format);
7448 Size := FormatDesc.GetSize(Dimension);
7449 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7450 if (FormatDesc.RGBInverted = tfEmpty) then
7451 raise EglBitmap.Create('inverted RGB format is empty');
7452 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7453 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7454 (Converter.PixelSize <> FormatDesc.PixelSize) then
7455 raise EglBitmap.Create('invalid inverted RGB format');
7458 if Assigned(Converter) then begin
7459 LineSize := FormatDesc.GetSize(Width, 1);
7460 GetMem(LineBuf, LineSize);
7461 SourceMD := FormatDesc.CreateMappingData;
7462 DestMD := Converter.CreateMappingData;
7465 for y := 0 to Height-1 do begin
7466 DestData := LineBuf;
7467 for x := 0 to Width-1 do begin
7468 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7469 Converter.Map(Pixel, DestData, DestMD);
7471 aStream.Write(LineBuf^, LineSize);
7475 FormatDesc.FreeMappingData(SourceMD);
7476 FormatDesc.FreeMappingData(DestMD);
7479 aStream.Write(Data^, Size);
7482 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7483 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7486 DDS_MAGIC: Cardinal = $20534444;
7488 // DDS_header.dwFlags
7489 DDSD_CAPS = $00000001;
7490 DDSD_HEIGHT = $00000002;
7491 DDSD_WIDTH = $00000004;
7492 DDSD_PIXELFORMAT = $00001000;
7494 // DDS_header.sPixelFormat.dwFlags
7495 DDPF_ALPHAPIXELS = $00000001;
7496 DDPF_ALPHA = $00000002;
7497 DDPF_FOURCC = $00000004;
7498 DDPF_RGB = $00000040;
7499 DDPF_LUMINANCE = $00020000;
7501 // DDS_header.sCaps.dwCaps1
7502 DDSCAPS_TEXTURE = $00001000;
7504 // DDS_header.sCaps.dwCaps2
7505 DDSCAPS2_CUBEMAP = $00000200;
7507 D3DFMT_DXT1 = $31545844;
7508 D3DFMT_DXT3 = $33545844;
7509 D3DFMT_DXT5 = $35545844;
7512 TDDSPixelFormat = packed record
7516 dwRGBBitCount: Cardinal;
7517 dwRBitMask: Cardinal;
7518 dwGBitMask: Cardinal;
7519 dwBBitMask: Cardinal;
7520 dwABitMask: Cardinal;
7523 TDDSCaps = packed record
7527 dwReserved: Cardinal;
7530 TDDSHeader = packed record
7535 dwPitchOrLinearSize: Cardinal;
7537 dwMipMapCount: Cardinal;
7538 dwReserved: array[0..10] of Cardinal;
7539 PixelFormat: TDDSPixelFormat;
7541 dwReserved2: Cardinal;
7544 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7545 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7548 Converter: TbmpBitfieldFormat;
7550 function GetDDSFormat: TglBitmapFormat;
7552 fd: TFormatDescriptor;
7554 Range: TglBitmapColorRec;
7558 with Header.PixelFormat do begin
7560 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7561 case Header.PixelFormat.dwFourCC of
7562 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7563 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7564 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7566 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7568 //find matching format
7569 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7570 fd := TFormatDescriptor.Get(result);
7571 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7572 (8 * fd.PixelSize = dwRGBBitCount) then
7576 //find format with same Range
7577 Range.r := dwRBitMask;
7578 Range.g := dwGBitMask;
7579 Range.b := dwBBitMask;
7580 Range.a := dwABitMask;
7581 for i := 0 to 3 do begin
7582 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7583 Range.arr[i] := Range.arr[i] shr 1;
7585 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7586 fd := TFormatDescriptor.Get(result);
7589 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7597 //no format with same range found -> use default
7598 if (result = tfEmpty) then begin
7599 if (dwABitMask > 0) then
7605 Converter := TbmpBitfieldFormat.Create;
7606 Converter.RedMask := dwRBitMask;
7607 Converter.GreenMask := dwGBitMask;
7608 Converter.BlueMask := dwBBitMask;
7609 Converter.AlphaMask := dwABitMask;
7610 Converter.PixelSize := dwRGBBitCount / 8;
7617 x, y, LineSize, RowSize, Magic: Cardinal;
7618 NewImage, TmpData, RowData, SrcData: System.PByte;
7619 SourceMD, DestMD: Pointer;
7620 Pixel: TglBitmapPixelData;
7621 ddsFormat: TglBitmapFormat;
7622 FormatDesc: TFormatDescriptor;
7627 StreamPos := aStream.Position;
7630 aStream.Read(Magic{%H-}, sizeof(Magic));
7631 if (Magic <> DDS_MAGIC) then begin
7632 aStream.Position := StreamPos;
7637 aStream.Read(Header{%H-}, sizeof(Header));
7638 if (Header.dwSize <> SizeOf(Header)) or
7639 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7640 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7642 aStream.Position := StreamPos;
7646 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7647 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
7649 ddsFormat := GetDDSFormat;
7651 if (ddsFormat = tfEmpty) then
7652 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7654 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7655 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7656 GetMem(NewImage, Header.dwHeight * LineSize);
7658 TmpData := NewImage;
7661 if Assigned(Converter) then begin
7662 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7663 GetMem(RowData, RowSize);
7664 SourceMD := Converter.CreateMappingData;
7665 DestMD := FormatDesc.CreateMappingData;
7667 for y := 0 to Header.dwHeight-1 do begin
7668 TmpData := NewImage;
7669 inc(TmpData, y * LineSize);
7671 aStream.Read(SrcData^, RowSize);
7672 for x := 0 to Header.dwWidth-1 do begin
7673 Converter.Unmap(SrcData, Pixel, SourceMD);
7674 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7675 FormatDesc.Map(Pixel, TmpData, DestMD);
7679 Converter.FreeMappingData(SourceMD);
7680 FormatDesc.FreeMappingData(DestMD);
7686 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7687 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7688 for Y := 0 to Header.dwHeight-1 do begin
7689 aStream.Read(TmpData^, RowSize);
7690 Inc(TmpData, LineSize);
7695 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7696 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7697 for Y := 0 to Header.dwHeight-1 do begin
7698 aStream.Read(TmpData^, RowSize);
7699 Inc(TmpData, LineSize);
7702 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7704 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method
7707 if Assigned(NewImage) then
7712 FreeAndNil(Converter);
7716 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7717 procedure TglBitmap.SaveDDS(const aStream: TStream);
7720 FormatDesc: TFormatDescriptor;
7722 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7723 raise EglBitmapUnsupportedFormat.Create(Format);
7725 FormatDesc := TFormatDescriptor.Get(Format);
7728 FillChar(Header{%H-}, SizeOf(Header), 0);
7729 Header.dwSize := SizeOf(Header);
7730 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7732 Header.dwWidth := Max(1, Width);
7733 Header.dwHeight := Max(1, Height);
7736 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7739 Header.PixelFormat.dwSize := sizeof(Header);
7740 if (FormatDesc.IsCompressed) then begin
7741 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7743 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7744 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7745 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7747 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7748 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7749 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7750 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7751 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7752 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7753 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7754 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7755 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7757 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7758 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7759 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7760 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7761 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7762 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7765 if (FormatDesc.HasAlpha) then
7766 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7768 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7769 aStream.Write(Header, SizeOf(Header));
7770 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7773 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7774 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7775 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7776 procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7777 const aWidth: Integer; const aHeight: Integer);
7782 if (aHeight > 1) then begin
7783 Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1);
7784 GetMem(pTemp, Size);
7786 Move(aData^, pTemp^, Size);
7795 inherited SetDataPointer(pTemp, aFormat, aWidth);
7798 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7799 function TglBitmap1D.FlipHorz: Boolean;
7802 pTempDest, pDest, pSource: PByte;
7804 result := inherited FlipHorz;
7805 if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin
7807 GetMem(pDest, fRowSize);
7810 Inc(pTempDest, fRowSize);
7811 for Col := 0 to Width-1 do begin
7812 dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data
7813 Move(pSource^, pTempDest^, fPixelSize);
7814 Inc(pSource, fPixelSize);
7816 SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method
7819 if Assigned(pDest) then
7826 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7827 procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean);
7829 FormatDesc: TFormatDescriptor;
7832 FormatDesc := TFormatDescriptor.Get(Format);
7833 if FormatDesc.IsCompressed then begin
7834 if not Assigned(glCompressedTexImage1D) then
7835 raise EglBitmap.Create('compressed formats not supported by video adapter');
7836 glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
7837 end else if aBuildWithGlu then
7838 gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7840 glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7843 if (FreeDataAfterGenTexture) then
7847 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7848 procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean);
7850 BuildWithGlu, TexRec: Boolean;
7853 if Assigned(Data) then begin
7854 // Check Texture Size
7855 if (aTestTextureSize) then begin
7856 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7858 if (Width > TexSize) then
7859 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7861 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7862 (Target = GL_TEXTURE_RECTANGLE);
7863 if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7864 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7868 SetupParameters(BuildWithGlu);
7869 UploadData(BuildWithGlu);
7870 glAreTexturesResident(1, @fID, @fIsResident);
7874 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7875 procedure TglBitmap1D.AfterConstruction;
7878 Target := GL_TEXTURE_1D;
7881 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7882 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7883 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7884 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7886 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7887 result := fLines[aIndex]
7892 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7893 procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7894 const aWidth: Integer; const aHeight: Integer);
7896 Idx, LineWidth: Integer;
7898 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7900 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7902 if Assigned(Data) then begin
7903 SetLength(fLines, GetHeight);
7904 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7906 for Idx := 0 to GetHeight-1 do begin
7907 fLines[Idx] := Data;
7908 Inc(fLines[Idx], Idx * LineWidth);
7911 else SetLength(fLines, 0);
7913 SetLength(fLines, 0);
7917 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7918 procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
7920 FormatDesc: TFormatDescriptor;
7922 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7924 FormatDesc := TFormatDescriptor.Get(Format);
7925 if FormatDesc.IsCompressed then begin
7926 if not Assigned(glCompressedTexImage2D) then
7927 raise EglBitmap.Create('compressed formats not supported by video adapter');
7928 glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7929 end else if aBuildWithGlu then begin
7930 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7931 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7933 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7934 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7938 if (FreeDataAfterGenTexture) then
7942 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7943 procedure TglBitmap2D.AfterConstruction;
7946 Target := GL_TEXTURE_2D;
7949 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7950 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7953 Size, w, h: Integer;
7954 FormatDesc: TFormatDescriptor;
7956 FormatDesc := TFormatDescriptor.Get(aFormat);
7957 if FormatDesc.IsCompressed then
7958 raise EglBitmapUnsupportedFormat.Create(aFormat);
7960 w := aRight - aLeft;
7961 h := aBottom - aTop;
7962 Size := FormatDesc.GetSize(w, h);
7965 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7966 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7967 SetDataPointer(Temp, aFormat, w, h); //be careful, Data could be freed by this method
7970 if Assigned(Temp) then
7976 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7977 procedure TglBitmap2D.GetDataFromTexture;
7980 TempWidth, TempHeight: Integer;
7981 TempIntFormat: Cardinal;
7982 IntFormat, f: TglBitmapFormat;
7983 FormatDesc: TFormatDescriptor;
7988 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7989 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7990 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7992 IntFormat := tfEmpty;
7993 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
7994 FormatDesc := TFormatDescriptor.Get(f);
7995 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
7996 IntFormat := FormatDesc.Format;
8001 // Getting data from OpenGL
8002 FormatDesc := TFormatDescriptor.Get(IntFormat);
8003 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
8005 if FormatDesc.IsCompressed then begin
8006 if not Assigned(glGetCompressedTexImage) then
8007 raise EglBitmap.Create('compressed formats not supported by video adapter');
8008 glGetCompressedTexImage(Target, 0, Temp)
8010 glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8011 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
8013 if Assigned(Temp) then
8019 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8020 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
8022 BuildWithGlu, PotTex, TexRec: Boolean;
8025 if Assigned(Data) then begin
8026 // Check Texture Size
8027 if (aTestTextureSize) then begin
8028 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8030 if ((Height > TexSize) or (Width > TexSize)) then
8031 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8033 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
8034 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
8035 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8036 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8040 SetupParameters(BuildWithGlu);
8041 UploadData(Target, BuildWithGlu);
8042 glAreTexturesResident(1, @fID, @fIsResident);
8046 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8047 function TglBitmap2D.FlipHorz: Boolean;
8050 TempDestData, DestData, SourceData: PByte;
8053 result := inherited FlipHorz;
8054 if Assigned(Data) then begin
8056 ImgSize := Height * fRowSize;
8057 GetMem(DestData, ImgSize);
8059 TempDestData := DestData;
8060 Dec(TempDestData, fRowSize + fPixelSize);
8061 for Row := 0 to Height -1 do begin
8062 Inc(TempDestData, fRowSize * 2);
8063 for Col := 0 to Width -1 do begin
8064 Move(SourceData^, TempDestData^, fPixelSize);
8065 Inc(SourceData, fPixelSize);
8066 Dec(TempDestData, fPixelSize);
8069 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8072 if Assigned(DestData) then
8079 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8080 function TglBitmap2D.FlipVert: Boolean;
8083 TempDestData, DestData, SourceData: PByte;
8085 result := inherited FlipVert;
8086 if Assigned(Data) then begin
8088 GetMem(DestData, Height * fRowSize);
8090 TempDestData := DestData;
8091 Inc(TempDestData, Width * (Height -1) * fPixelSize);
8092 for Row := 0 to Height -1 do begin
8093 Move(SourceData^, TempDestData^, fRowSize);
8094 Dec(TempDestData, fRowSize);
8095 Inc(SourceData, fRowSize);
8097 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8100 if Assigned(DestData) then
8107 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8108 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8109 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8111 TMatrixItem = record
8116 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
8117 TglBitmapToNormalMapRec = Record
8119 Heights: array of Single;
8120 MatrixU : array of TMatrixItem;
8121 MatrixV : array of TMatrixItem;
8125 ONE_OVER_255 = 1 / 255;
8127 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8128 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
8132 with FuncRec do begin
8134 Source.Data.r * LUMINANCE_WEIGHT_R +
8135 Source.Data.g * LUMINANCE_WEIGHT_G +
8136 Source.Data.b * LUMINANCE_WEIGHT_B;
8137 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
8141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8142 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
8145 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
8148 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8149 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
8151 TVec = Array[0..2] of Single;
8158 function GetHeight(X, Y: Integer): Single;
8160 with FuncRec do begin
8161 X := Max(0, Min(Size.X -1, X));
8162 Y := Max(0, Min(Size.Y -1, Y));
8163 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
8168 with FuncRec do begin
8169 with PglBitmapToNormalMapRec(Args)^ do begin
8171 for Idx := Low(MatrixU) to High(MatrixU) do
8172 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
8175 for Idx := Low(MatrixU) to High(MatrixU) do
8176 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
8178 Vec[0] := -du * Scale;
8179 Vec[1] := -dv * Scale;
8184 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8185 if Len <> 0 then begin
8186 Vec[0] := Vec[0] * Len;
8187 Vec[1] := Vec[1] * Len;
8188 Vec[2] := Vec[2] * Len;
8192 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
8193 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
8194 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
8198 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8199 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
8201 Rec: TglBitmapToNormalMapRec;
8203 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
8205 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
8206 Matrix[Index].X := X;
8207 Matrix[Index].Y := Y;
8208 Matrix[Index].W := W;
8213 if TFormatDescriptor.Get(Format).IsCompressed then
8214 raise EglBitmapUnsupportedFormat.Create(Format);
8216 if aScale > 100 then
8218 else if aScale < -100 then
8221 Rec.Scale := aScale;
8223 SetLength(Rec.Heights, Width * Height);
8227 SetLength(Rec.MatrixU, 2);
8228 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
8229 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
8231 SetLength(Rec.MatrixV, 2);
8232 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
8233 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
8237 SetLength(Rec.MatrixU, 6);
8238 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
8239 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
8240 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
8241 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
8242 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
8243 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
8245 SetLength(Rec.MatrixV, 6);
8246 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
8247 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
8248 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
8249 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
8250 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
8251 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
8255 SetLength(Rec.MatrixU, 6);
8256 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
8257 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
8258 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
8259 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
8260 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
8261 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
8263 SetLength(Rec.MatrixV, 6);
8264 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
8265 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
8266 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
8267 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
8268 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
8269 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
8273 SetLength(Rec.MatrixU, 20);
8274 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
8275 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
8276 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
8277 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
8278 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
8279 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
8280 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
8281 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
8282 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
8283 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
8284 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
8285 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
8286 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
8287 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
8288 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
8289 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
8290 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
8291 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
8292 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
8293 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
8295 SetLength(Rec.MatrixV, 20);
8296 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
8297 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
8298 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
8299 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
8300 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
8301 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
8302 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
8303 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
8304 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
8305 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
8306 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
8307 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
8308 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
8309 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
8310 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
8311 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
8312 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
8313 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
8314 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
8315 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
8320 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
8321 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
8323 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
8324 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
8326 SetLength(Rec.Heights, 0);
8330 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8331 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8332 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8333 procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean);
8335 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8338 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8339 procedure TglBitmapCubeMap.AfterConstruction;
8343 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8344 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8347 Target := GL_TEXTURE_CUBE_MAP;
8348 fGenMode := GL_REFLECTION_MAP;
8351 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8352 procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean);
8354 BuildWithGlu: Boolean;
8357 if (aTestTextureSize) then begin
8358 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8360 if (Height > TexSize) or (Width > TexSize) then
8361 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8363 if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8364 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8369 SetupParameters(BuildWithGlu);
8370 UploadData(aCubeTarget, BuildWithGlu);
8373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8374 procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean);
8376 inherited Bind (aEnableTextureUnit);
8377 if aEnableTexCoordsGen then begin
8378 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8379 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8380 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8381 glEnable(GL_TEXTURE_GEN_S);
8382 glEnable(GL_TEXTURE_GEN_T);
8383 glEnable(GL_TEXTURE_GEN_R);
8387 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8388 procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean);
8390 inherited Unbind(aDisableTextureUnit);
8391 if aDisableTexCoordsGen then begin
8392 glDisable(GL_TEXTURE_GEN_S);
8393 glDisable(GL_TEXTURE_GEN_T);
8394 glDisable(GL_TEXTURE_GEN_R);
8398 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8399 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8400 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8402 TVec = Array[0..2] of Single;
8403 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8405 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8406 TglBitmapNormalMapRec = record
8408 Func: TglBitmapNormalMapGetVectorFunc;
8411 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8412 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8414 aVec[0] := aHalfSize;
8415 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8416 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8419 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8420 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8422 aVec[0] := - aHalfSize;
8423 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8424 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8428 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8430 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8431 aVec[1] := aHalfSize;
8432 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8435 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8436 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8438 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8439 aVec[1] := - aHalfSize;
8440 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8443 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8444 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8446 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8447 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8448 aVec[2] := aHalfSize;
8451 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8452 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8454 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8455 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8456 aVec[2] := - aHalfSize;
8459 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8460 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8466 with FuncRec do begin
8467 with PglBitmapNormalMapRec(Args)^ do begin
8468 Func(Vec, Position, HalfSize);
8471 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8472 if Len <> 0 then begin
8473 Vec[0] := Vec[0] * Len;
8474 Vec[1] := Vec[1] * Len;
8475 Vec[2] := Vec[2] * Len;
8478 // Scale Vector and AddVectro
8479 Vec[0] := Vec[0] * 0.5 + 0.5;
8480 Vec[1] := Vec[1] * 0.5 + 0.5;
8481 Vec[2] := Vec[2] * 0.5 + 0.5;
8486 Dest.Data.arr[i] := Round(Vec[i] * 255);
8490 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8491 procedure TglBitmapNormalMap.AfterConstruction;
8494 fGenMode := GL_NORMAL_MAP;
8497 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8498 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean);
8500 Rec: TglBitmapNormalMapRec;
8501 SizeRec: TglBitmapPixelPosition;
8503 Rec.HalfSize := aSize div 2;
8504 FreeDataAfterGenTexture := false;
8506 SizeRec.Fields := [ffX, ffY];
8511 Rec.Func := glBitmapNormalMapPosX;
8512 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8513 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize);
8516 Rec.Func := glBitmapNormalMapNegX;
8517 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8518 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize);
8521 Rec.Func := glBitmapNormalMapPosY;
8522 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8523 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize);
8526 Rec.Func := glBitmapNormalMapNegY;
8527 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8528 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize);
8531 Rec.Func := glBitmapNormalMapPosZ;
8532 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8533 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize);
8536 Rec.Func := glBitmapNormalMapNegZ;
8537 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8538 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize);
8543 glBitmapSetDefaultFormat (tfEmpty);
8544 glBitmapSetDefaultMipmap (mmMipmap);
8545 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8546 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8547 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8549 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8550 glBitmapSetDefaultDeleteTextureOnFree (true);
8552 TFormatDescriptor.Init;
8554 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8555 OpenGLInitialized := false;
8556 InitOpenGLCS := TCriticalSection.Create;
8560 TFormatDescriptor.Finalize;
8562 {$IFDEF GLB_NATIVE_OGL}
8563 if Assigned(GL_LibHandle) then
8564 glbFreeLibrary(GL_LibHandle);
8566 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8567 if Assigned(GLU_LibHandle) then
8568 glbFreeLibrary(GLU_LibHandle);
8569 FreeAndNil(InitOpenGLCS);