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) OR
447 DEFINED(GLB_DELPHI))} windows, {$IFEND}
449 {$IFDEF GLB_SDL} SDL, {$ENDIF}
450 {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, Graphics, {$ENDIF}
451 {$IFDEF GLB_DELPHI} Dialogs, Graphics, Types, {$ENDIF}
453 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
454 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
455 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
456 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
457 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
461 {$IFDEF GLB_NATIVE_OGL}
470 GL_EXTENSIONS = $1F03;
472 GL_TEXTURE_1D = $0DE0;
473 GL_TEXTURE_2D = $0DE1;
474 GL_TEXTURE_RECTANGLE = $84F5;
476 GL_NORMAL_MAP = $8511;
477 GL_TEXTURE_CUBE_MAP = $8513;
478 GL_REFLECTION_MAP = $8512;
479 GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515;
480 GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516;
481 GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517;
482 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518;
483 GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519;
484 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A;
486 GL_TEXTURE_WIDTH = $1000;
487 GL_TEXTURE_HEIGHT = $1001;
488 GL_TEXTURE_INTERNAL_FORMAT = $1003;
489 GL_TEXTURE_SWIZZLE_RGBA = $8E46;
496 GL_TEXTURE_GEN_S = $0C60;
497 GL_TEXTURE_GEN_T = $0C61;
498 GL_TEXTURE_GEN_R = $0C62;
499 GL_TEXTURE_GEN_Q = $0C63;
511 GL_LUMINANCE = $1909;
512 GL_LUMINANCE4 = $803F;
513 GL_LUMINANCE8 = $8040;
514 GL_LUMINANCE12 = $8041;
515 GL_LUMINANCE16 = $8042;
517 GL_LUMINANCE_ALPHA = $190A;
518 GL_LUMINANCE4_ALPHA4 = $8043;
519 GL_LUMINANCE6_ALPHA2 = $8044;
520 GL_LUMINANCE8_ALPHA8 = $8045;
521 GL_LUMINANCE12_ALPHA4 = $8046;
522 GL_LUMINANCE12_ALPHA12 = $8047;
523 GL_LUMINANCE16_ALPHA16 = $8048;
546 GL_DEPTH_COMPONENT = $1902;
547 GL_DEPTH_COMPONENT16 = $81A5;
548 GL_DEPTH_COMPONENT24 = $81A6;
549 GL_DEPTH_COMPONENT32 = $81A7;
551 GL_COMPRESSED_RGB = $84ED;
552 GL_COMPRESSED_RGBA = $84EE;
553 GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
554 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
555 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
556 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
558 GL_UNSIGNED_BYTE = $1401;
559 GL_UNSIGNED_BYTE_3_3_2 = $8032;
560 GL_UNSIGNED_BYTE_2_3_3_REV = $8362;
562 GL_UNSIGNED_SHORT = $1403;
563 GL_UNSIGNED_SHORT_5_6_5 = $8363;
564 GL_UNSIGNED_SHORT_4_4_4_4 = $8033;
565 GL_UNSIGNED_SHORT_5_5_5_1 = $8034;
566 GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
567 GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
568 GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
570 GL_UNSIGNED_INT = $1405;
571 GL_UNSIGNED_INT_8_8_8_8 = $8035;
572 GL_UNSIGNED_INT_10_10_10_2 = $8036;
573 GL_UNSIGNED_INT_8_8_8_8_REV = $8367;
574 GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
577 GL_TEXTURE_MAG_FILTER = $2800;
578 GL_TEXTURE_MIN_FILTER = $2801;
580 GL_NEAREST_MIPMAP_NEAREST = $2700;
581 GL_NEAREST_MIPMAP_LINEAR = $2702;
583 GL_LINEAR_MIPMAP_NEAREST = $2701;
584 GL_LINEAR_MIPMAP_LINEAR = $2703;
587 GL_TEXTURE_WRAP_S = $2802;
588 GL_TEXTURE_WRAP_T = $2803;
589 GL_TEXTURE_WRAP_R = $8072;
592 GL_CLAMP_TO_EDGE = $812F;
593 GL_CLAMP_TO_BORDER = $812D;
594 GL_MIRRORED_REPEAT = $8370;
597 GL_GENERATE_MIPMAP = $8191;
598 GL_TEXTURE_BORDER_COLOR = $1004;
599 GL_MAX_TEXTURE_SIZE = $0D33;
600 GL_PACK_ALIGNMENT = $0D05;
601 GL_UNPACK_ALIGNMENT = $0CF5;
603 GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
604 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
605 GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C;
606 GL_TEXTURE_GEN_MODE = $2500;
608 {$IF DEFINED(GLB_WIN)}
609 libglu = 'glu32.dll';
610 libopengl = 'opengl32.dll';
611 {$ELSEIF DEFINED(GLB_LINUX)}
612 libglu = 'libGLU.so.1';
613 libopengl = 'libGL.so.1';
617 GLboolean = BYTEBOOL;
625 PGLboolean = ^GLboolean;
630 TglCompressedTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
631 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}
632 TglGetCompressedTexImage = procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
634 {$IF DEFINED(GLB_WIN)}
635 TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall;
636 {$ELSEIF DEFINED(GLB_LINUX)}
637 TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl;
638 TglXGetProcAddressARB = function(const name: PAnsiChar): pointer; cdecl;
641 {$IF DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
642 TglEnable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
643 TglDisable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
645 TglGetString = function(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
646 TglGetIntegerv = procedure(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
648 TglTexParameteri = procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
649 TglTexParameteriv = procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
650 TglTexParameterfv = procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
651 TglGetTexParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
652 TglGetTexParameterfv = procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
653 TglGetTexLevelParameteriv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
654 TglGetTexLevelParameterfv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
656 TglTexGeni = procedure(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
657 TglGenTextures = procedure(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
658 TglBindTexture = procedure(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
659 TglDeleteTextures = procedure(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
661 TglAreTexturesResident = function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
662 TglReadPixels = procedure(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
663 TglPixelStorei = procedure(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
665 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}
666 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}
667 TglGetTexImage = procedure(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
669 TgluBuild1DMipmaps = function(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
670 TgluBuild2DMipmaps = function(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
672 {$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)}
673 procedure glEnable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
674 procedure glDisable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
676 function glGetString(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
677 procedure glGetIntegerv(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
679 procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
680 procedure glTexParameteriv(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
681 procedure glTexParameterfv(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
682 procedure glGetTexParameteriv(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
683 procedure glGetTexParameterfv(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
684 procedure glGetTexLevelParameteriv(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
685 procedure glGetTexLevelParameterfv(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
687 procedure glTexGeni(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
688 procedure glGenTextures(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
689 procedure glBindTexture(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
690 procedure glDeleteTextures(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
692 function glAreTexturesResident(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
693 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;
694 procedure glPixelStorei(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
696 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;
697 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;
698 procedure glGetTexImage(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
700 function gluBuild1DMipmaps(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
701 function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
711 GL_SGIS_generate_mipmap,
713 GL_ARB_texture_border_clamp,
714 GL_ARB_texture_mirrored_repeat,
715 GL_ARB_texture_rectangle,
716 GL_ARB_texture_non_power_of_two,
717 GL_ARB_texture_swizzle,
718 GL_ARB_texture_cube_map,
720 GL_IBM_texture_mirrored_repeat,
722 GL_NV_texture_rectangle,
724 GL_EXT_texture_edge_clamp,
725 GL_EXT_texture_rectangle,
726 GL_EXT_texture_swizzle,
727 GL_EXT_texture_cube_map,
728 GL_EXT_texture_filter_anisotropic: Boolean;
730 glCompressedTexImage1D: TglCompressedTexImage1D;
731 glCompressedTexImage2D: TglCompressedTexImage2D;
732 glGetCompressedTexImage: TglGetCompressedTexImage;
734 {$IF DEFINED(GLB_WIN)}
735 wglGetProcAddress: TwglGetProcAddress;
736 {$ELSEIF DEFINED(GLB_LINUX)}
737 glXGetProcAddress: TglXGetProcAddress;
738 glXGetProcAddressARB: TglXGetProcAddress;
741 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
743 glDisable: TglDisable;
745 glGetString: TglGetString;
746 glGetIntegerv: TglGetIntegerv;
748 glTexParameteri: TglTexParameteri;
749 glTexParameteriv: TglTexParameteriv;
750 glTexParameterfv: TglTexParameterfv;
751 glGetTexParameteriv: TglGetTexParameteriv;
752 glGetTexParameterfv: TglGetTexParameterfv;
753 glGetTexLevelParameteriv: TglGetTexLevelParameteriv;
754 glGetTexLevelParameterfv: TglGetTexLevelParameterfv;
756 glTexGeni: TglTexGeni;
757 glGenTextures: TglGenTextures;
758 glBindTexture: TglBindTexture;
759 glDeleteTextures: TglDeleteTextures;
761 glAreTexturesResident: TglAreTexturesResident;
762 glReadPixels: TglReadPixels;
763 glPixelStorei: TglPixelStorei;
765 glTexImage1D: TglTexImage1D;
766 glTexImage2D: TglTexImage2D;
767 glGetTexImage: TglGetTexImage;
769 gluBuild1DMipmaps: TgluBuild1DMipmaps;
770 gluBuild2DMipmaps: TgluBuild2DMipmaps;
775 ////////////////////////////////////////////////////////////////////////////////////////////////////
777 tfEmpty = 0, //must be smallest value!
793 tfLuminance12Alpha12,
794 tfLuminance16Alpha16,
838 TglBitmapFileType = (
839 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
840 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
844 TglBitmapFileTypes = set of TglBitmapFileType;
851 TglBitmapNormalMapFunc = (
857 ////////////////////////////////////////////////////////////////////////////////////////////////////
858 EglBitmap = class(Exception);
859 EglBitmapNotSupported = class(Exception);
860 EglBitmapSizeToLarge = class(EglBitmap);
861 EglBitmapNonPowerOfTwo = class(EglBitmap);
862 EglBitmapUnsupportedFormat = class(EglBitmap)
863 constructor Create(const aFormat: TglBitmapFormat); overload;
864 constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload;
867 ////////////////////////////////////////////////////////////////////////////////////////////////////
868 TglBitmapColorRec = packed record
870 0: (r, g, b, a: Cardinal);
871 1: (arr: array[0..3] of Cardinal);
874 TglBitmapPixelData = packed record
875 Data, Range: TglBitmapColorRec;
876 Format: TglBitmapFormat;
878 PglBitmapPixelData = ^TglBitmapPixelData;
880 ////////////////////////////////////////////////////////////////////////////////////////////////////
881 TglBitmapPixelPositionFields = set of (ffX, ffY);
882 TglBitmapPixelPosition = record
883 Fields : TglBitmapPixelPositionFields;
888 TglBitmapFormatDescriptor = class(TObject)
890 function GetIsCompressed: Boolean; virtual; abstract;
891 function GetHasAlpha: Boolean; virtual; abstract;
893 function GetglDataFormat: GLenum; virtual; abstract;
894 function GetglFormat: GLenum; virtual; abstract;
895 function GetglInternalFormat: GLenum; virtual; abstract;
897 property IsCompressed: Boolean read GetIsCompressed;
898 property HasAlpha: Boolean read GetHasAlpha;
900 property glFormat: GLenum read GetglFormat;
901 property glInternalFormat: GLenum read GetglInternalFormat;
902 property glDataFormat: GLenum read GetglDataFormat;
905 ////////////////////////////////////////////////////////////////////////////////////////////////////
907 TglBitmapFunctionRec = record
909 Size: TglBitmapPixelPosition;
910 Position: TglBitmapPixelPosition;
911 Source: TglBitmapPixelData;
912 Dest: TglBitmapPixelData;
915 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
917 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
920 function GetFormatDesc: TglBitmapFormatDescriptor;
924 fAnisotropic: Integer;
925 fDeleteTextureOnFree: Boolean;
926 fFreeDataAfterGenTexture: Boolean;
928 fIsResident: Boolean;
929 fBorderColor: array[0..3] of Single;
931 fDimension: TglBitmapPixelPosition;
932 fMipMap: TglBitmapMipMap;
933 fFormat: TglBitmapFormat;
949 fSwizzle: array[0..3] of GLenum;
954 fCustomNameW: WideString;
955 fCustomData: Pointer;
958 function GetWidth: Integer; virtual;
959 function GetHeight: Integer; virtual;
961 function GetFileWidth: Integer; virtual;
962 function GetFileHeight: Integer; virtual;
965 procedure SetCustomData(const aValue: Pointer);
966 procedure SetCustomName(const aValue: String);
967 procedure SetCustomNameW(const aValue: WideString);
968 procedure SetDeleteTextureOnFree(const aValue: Boolean);
969 procedure SetFormat(const aValue: TglBitmapFormat);
970 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
971 procedure SetID(const aValue: Cardinal);
972 procedure SetMipMap(const aValue: TglBitmapMipMap);
973 procedure SetTarget(const aValue: Cardinal);
974 procedure SetAnisotropic(const aValue: Integer);
977 procedure SetupParameters(out aBuildWithGlu: Boolean);
978 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
979 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; //be careful, aData could be freed by this method
980 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
982 function FlipHorz: Boolean; virtual;
983 function FlipVert: Boolean; virtual;
985 property Width: Integer read GetWidth;
986 property Height: Integer read GetHeight;
988 property FileWidth: Integer read GetFileWidth;
989 property FileHeight: Integer read GetFileHeight;
992 property ID: Cardinal read fID write SetID;
993 property Target: Cardinal read fTarget write SetTarget;
994 property Format: TglBitmapFormat read fFormat write SetFormat;
995 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
996 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
998 property FormatDesc: TglBitmapFormatDescriptor read GetFormatDesc;
1000 property Filename: String read fFilename;
1001 property CustomName: String read fCustomName write SetCustomName;
1002 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
1003 property CustomData: Pointer read fCustomData write SetCustomData;
1005 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
1006 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
1008 property Dimension: TglBitmapPixelPosition read fDimension;
1009 property Data: PByte read fData;
1010 property IsResident: Boolean read fIsResident;
1012 procedure AfterConstruction; override;
1013 procedure BeforeDestruction; override;
1015 procedure PrepareResType(var aResource: String; var aResType: PChar);
1018 procedure LoadFromFile(const aFilename: String);
1019 procedure LoadFromStream(const aStream: TStream); virtual;
1020 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
1021 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil);
1022 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil);
1023 procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
1026 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
1027 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
1030 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
1031 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
1032 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
1036 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
1037 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
1038 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
1039 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
1040 const aArgs: Pointer = nil): Boolean;
1044 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
1045 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
1046 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
1047 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
1048 const aArgs: Pointer = nil): Boolean;
1051 {$IFDEF GLB_LAZARUS}
1052 function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1053 function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
1054 function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1055 function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil;
1056 const aArgs: Pointer = nil): Boolean;
1059 function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil;
1060 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1061 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
1062 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1064 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
1065 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1066 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1067 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1069 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
1070 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
1071 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
1073 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
1074 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
1075 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
1077 function RemoveAlpha: Boolean; virtual;
1080 function Clone: TglBitmap;
1081 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
1082 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
1083 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
1087 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
1088 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
1089 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
1092 procedure SetFilter(const aMin, aMag: GLenum);
1094 const S: GLenum = GL_CLAMP_TO_EDGE;
1095 const T: GLenum = GL_CLAMP_TO_EDGE;
1096 const R: GLenum = GL_CLAMP_TO_EDGE);
1097 procedure SetSwizzle(const r, g, b, a: GLenum);
1099 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
1100 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
1103 constructor Create; overload;
1104 constructor Create(const aFileName: String); overload;
1105 constructor Create(const aStream: TStream); overload;
1106 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload;
1107 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
1108 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
1109 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
1111 {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1112 {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF}
1114 {$IFDEF GLB_SUPPORT_JPEG_READ} function LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1115 {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF}
1117 function LoadBMP(const aStream: TStream): Boolean; virtual;
1118 procedure SaveBMP(const aStream: TStream); virtual;
1120 function LoadTGA(const aStream: TStream): Boolean; virtual;
1121 procedure SaveTGA(const aStream: TStream); virtual;
1123 function LoadDDS(const aStream: TStream): Boolean; virtual;
1124 procedure SaveDDS(const aStream: TStream); virtual;
1127 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1128 TglBitmap1D = class(TglBitmap)
1130 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1131 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1132 procedure UploadData(const aBuildWithGlu: Boolean);
1135 procedure AfterConstruction; override;
1136 function FlipHorz: Boolean; override;
1137 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1140 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1141 TglBitmap2D = class(TglBitmap)
1143 fLines: array of PByte;
1144 function GetScanline(const aIndex: Integer): Pointer;
1145 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1146 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1147 procedure UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
1151 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
1153 procedure AfterConstruction; override;
1155 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
1156 procedure GetDataFromTexture;
1157 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1159 function FlipHorz: Boolean; override;
1160 function FlipVert: Boolean; override;
1162 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
1163 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1166 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1167 TglBitmapCubeMap = class(TglBitmap2D)
1170 procedure GenTexture(const aTestTextureSize: Boolean = true); reintroduce;
1172 procedure AfterConstruction; override;
1173 procedure GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean = true);
1174 procedure Bind(const aEnableTexCoordsGen: Boolean = true; const aEnableTextureUnit: Boolean = true); reintroduce; virtual;
1175 procedure Unbind(const aDisableTexCoordsGen: Boolean = true; const aDisableTextureUnit: Boolean = true); reintroduce; virtual;
1178 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1179 TglBitmapNormalMap = class(TglBitmapCubeMap)
1181 procedure AfterConstruction; override;
1182 procedure GenerateNormalMap(const aSize: Integer = 32; const aTestTextureSize: Boolean = true);
1186 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1188 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1189 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1190 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1191 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1192 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1193 procedure glBitmapSetDefaultWrap(
1194 const S: Cardinal = GL_CLAMP_TO_EDGE;
1195 const T: Cardinal = GL_CLAMP_TO_EDGE;
1196 const R: Cardinal = GL_CLAMP_TO_EDGE);
1198 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1199 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1200 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1201 function glBitmapGetDefaultFormat: TglBitmapFormat;
1202 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1203 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1205 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1206 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1207 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1210 glBitmapDefaultDeleteTextureOnFree: Boolean;
1211 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1212 glBitmapDefaultFormat: TglBitmapFormat;
1213 glBitmapDefaultMipmap: TglBitmapMipMap;
1214 glBitmapDefaultFilterMin: Cardinal;
1215 glBitmapDefaultFilterMag: Cardinal;
1216 glBitmapDefaultWrapS: Cardinal;
1217 glBitmapDefaultWrapT: Cardinal;
1218 glBitmapDefaultWrapR: Cardinal;
1219 glDefaultSwizzle: array[0..3] of GLenum;
1222 function CreateGrayPalette: HPALETTE;
1228 Math, syncobjs, typinfo
1229 {$IFDEF GLB_DELPHI}, Types{$ENDIF};
1233 QWord = System.UInt64;
1240 ////////////////////////////////////////////////////////////////////////////////////////////////////
1241 TShiftRec = packed record
1243 0: (r, g, b, a: Byte);
1244 1: (arr: array[0..3] of Byte);
1247 TFormatDescriptor = class(TglBitmapFormatDescriptor)
1249 function GetRedMask: QWord;
1250 function GetGreenMask: QWord;
1251 function GetBlueMask: QWord;
1252 function GetAlphaMask: QWord;
1254 fFormat: TglBitmapFormat;
1255 fWithAlpha: TglBitmapFormat;
1256 fWithoutAlpha: TglBitmapFormat;
1257 fRGBInverted: TglBitmapFormat;
1258 fUncompressed: TglBitmapFormat;
1260 fIsCompressed: Boolean;
1262 fRange: TglBitmapColorRec;
1266 fglInternalFormat: GLenum;
1267 fglDataFormat: GLenum;
1269 function GetIsCompressed: Boolean; override;
1270 function GetHasAlpha: Boolean; override;
1272 function GetglFormat: GLenum; override;
1273 function GetglInternalFormat: GLenum; override;
1274 function GetglDataFormat: GLenum; override;
1276 function GetComponents: Integer; virtual;
1278 property Format: TglBitmapFormat read fFormat;
1279 property WithAlpha: TglBitmapFormat read fWithAlpha;
1280 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1281 property RGBInverted: TglBitmapFormat read fRGBInverted;
1282 property Components: Integer read GetComponents;
1283 property PixelSize: Single read fPixelSize;
1285 property Range: TglBitmapColorRec read fRange;
1286 property Shift: TShiftRec read fShift;
1288 property RedMask: QWord read GetRedMask;
1289 property GreenMask: QWord read GetGreenMask;
1290 property BlueMask: QWord read GetBlueMask;
1291 property AlphaMask: QWord read GetAlphaMask;
1293 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1294 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1296 function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual;
1297 function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
1299 function CreateMappingData: Pointer; virtual;
1300 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1302 function IsEmpty: Boolean; virtual;
1303 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual;
1305 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1307 constructor Create; virtual;
1309 class procedure Init;
1310 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1311 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1312 class procedure Clear;
1313 class procedure Finalize;
1315 TFormatDescriptorClass = class of TFormatDescriptor;
1317 TfdEmpty = class(TFormatDescriptor);
1319 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1320 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1321 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1322 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1323 constructor Create; override;
1326 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1327 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1328 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1329 constructor Create; override;
1332 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1333 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1334 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1335 constructor Create; override;
1338 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1339 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1340 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1341 constructor Create; override;
1344 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1345 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1346 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1347 constructor Create; override;
1350 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1351 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1352 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1353 constructor Create; override;
1356 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1357 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1358 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1359 constructor Create; override;
1362 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1363 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1364 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1365 constructor Create; override;
1368 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1369 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1370 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1371 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1372 constructor Create; override;
1375 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1376 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1377 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1378 constructor Create; override;
1381 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1382 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1383 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1384 constructor Create; override;
1387 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1388 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1389 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1390 constructor Create; override;
1393 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1394 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1395 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1396 constructor Create; override;
1399 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1400 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1401 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1402 constructor Create; override;
1405 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1406 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1407 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1408 constructor Create; override;
1411 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1412 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1413 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1414 constructor Create; override;
1417 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1418 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1419 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1420 constructor Create; override;
1423 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1424 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1425 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1426 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1427 constructor Create; override;
1430 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1431 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1432 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1433 constructor Create; override;
1436 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1437 TfdAlpha4 = class(TfdAlpha_UB1)
1438 constructor Create; override;
1441 TfdAlpha8 = class(TfdAlpha_UB1)
1442 constructor Create; override;
1445 TfdAlpha12 = class(TfdAlpha_US1)
1446 constructor Create; override;
1449 TfdAlpha16 = class(TfdAlpha_US1)
1450 constructor Create; override;
1453 TfdLuminance4 = class(TfdLuminance_UB1)
1454 constructor Create; override;
1457 TfdLuminance8 = class(TfdLuminance_UB1)
1458 constructor Create; override;
1461 TfdLuminance12 = class(TfdLuminance_US1)
1462 constructor Create; override;
1465 TfdLuminance16 = class(TfdLuminance_US1)
1466 constructor Create; override;
1469 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1470 constructor Create; override;
1473 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1474 constructor Create; override;
1477 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1478 constructor Create; override;
1481 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1482 constructor Create; override;
1485 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1486 constructor Create; override;
1489 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1490 constructor Create; override;
1493 TfdR3G3B2 = class(TfdUniversal_UB1)
1494 constructor Create; override;
1497 TfdRGB4 = class(TfdUniversal_US1)
1498 constructor Create; override;
1501 TfdR5G6B5 = class(TfdUniversal_US1)
1502 constructor Create; override;
1505 TfdRGB5 = class(TfdUniversal_US1)
1506 constructor Create; override;
1509 TfdRGB8 = class(TfdRGB_UB3)
1510 constructor Create; override;
1513 TfdRGB10 = class(TfdUniversal_UI1)
1514 constructor Create; override;
1517 TfdRGB12 = class(TfdRGB_US3)
1518 constructor Create; override;
1521 TfdRGB16 = class(TfdRGB_US3)
1522 constructor Create; override;
1525 TfdRGBA2 = class(TfdRGBA_UB4)
1526 constructor Create; override;
1529 TfdRGBA4 = class(TfdUniversal_US1)
1530 constructor Create; override;
1533 TfdRGB5A1 = class(TfdUniversal_US1)
1534 constructor Create; override;
1537 TfdRGBA8 = class(TfdRGBA_UB4)
1538 constructor Create; override;
1541 TfdRGB10A2 = class(TfdUniversal_UI1)
1542 constructor Create; override;
1545 TfdRGBA12 = class(TfdRGBA_US4)
1546 constructor Create; override;
1549 TfdRGBA16 = class(TfdRGBA_US4)
1550 constructor Create; override;
1553 TfdBGR4 = class(TfdUniversal_US1)
1554 constructor Create; override;
1557 TfdB5G6R5 = class(TfdUniversal_US1)
1558 constructor Create; override;
1561 TfdBGR5 = class(TfdUniversal_US1)
1562 constructor Create; override;
1565 TfdBGR8 = class(TfdBGR_UB3)
1566 constructor Create; override;
1569 TfdBGR10 = class(TfdUniversal_UI1)
1570 constructor Create; override;
1573 TfdBGR12 = class(TfdBGR_US3)
1574 constructor Create; override;
1577 TfdBGR16 = class(TfdBGR_US3)
1578 constructor Create; override;
1581 TfdBGRA2 = class(TfdBGRA_UB4)
1582 constructor Create; override;
1585 TfdBGRA4 = class(TfdUniversal_US1)
1586 constructor Create; override;
1589 TfdBGR5A1 = class(TfdUniversal_US1)
1590 constructor Create; override;
1593 TfdBGRA8 = class(TfdBGRA_UB4)
1594 constructor Create; override;
1597 TfdBGR10A2 = class(TfdUniversal_UI1)
1598 constructor Create; override;
1601 TfdBGRA12 = class(TfdBGRA_US4)
1602 constructor Create; override;
1605 TfdBGRA16 = class(TfdBGRA_US4)
1606 constructor Create; override;
1609 TfdDepth16 = class(TfdDepth_US1)
1610 constructor Create; override;
1613 TfdDepth24 = class(TfdDepth_UI1)
1614 constructor Create; override;
1617 TfdDepth32 = class(TfdDepth_UI1)
1618 constructor Create; override;
1621 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1622 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1623 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1624 constructor Create; override;
1627 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1628 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1629 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1630 constructor Create; override;
1633 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1634 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1635 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1636 constructor Create; override;
1639 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1640 TbmpBitfieldFormat = class(TFormatDescriptor)
1642 procedure SetRedMask (const aValue: QWord);
1643 procedure SetGreenMask(const aValue: QWord);
1644 procedure SetBlueMask (const aValue: QWord);
1645 procedure SetAlphaMask(const aValue: QWord);
1647 procedure Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte);
1649 property RedMask: QWord read GetRedMask write SetRedMask;
1650 property GreenMask: QWord read GetGreenMask write SetGreenMask;
1651 property BlueMask: QWord read GetBlueMask write SetBlueMask;
1652 property AlphaMask: QWord read GetAlphaMask write SetAlphaMask;
1654 property PixelSize: Single read fPixelSize write fPixelSize;
1656 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1657 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1660 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1661 TbmpColorTableEnty = packed record
1664 TbmpColorTable = array of TbmpColorTableEnty;
1665 TbmpColorTableFormat = class(TFormatDescriptor)
1667 fColorTable: TbmpColorTable;
1669 property PixelSize: Single read fPixelSize write fPixelSize;
1670 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1671 property Range: TglBitmapColorRec read fRange write fRange;
1672 property Shift: TShiftRec read fShift write fShift;
1673 property Format: TglBitmapFormat read fFormat write fFormat;
1675 procedure CreateColorTable;
1677 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1678 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1679 destructor Destroy; override;
1683 LUMINANCE_WEIGHT_R = 0.30;
1684 LUMINANCE_WEIGHT_G = 0.59;
1685 LUMINANCE_WEIGHT_B = 0.11;
1687 ALPHA_WEIGHT_R = 0.30;
1688 ALPHA_WEIGHT_G = 0.59;
1689 ALPHA_WEIGHT_B = 0.11;
1691 DEPTH_WEIGHT_R = 0.333333333;
1692 DEPTH_WEIGHT_G = 0.333333333;
1693 DEPTH_WEIGHT_B = 0.333333333;
1695 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1697 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1710 TfdLuminance4Alpha4,
1711 TfdLuminance6Alpha2,
1712 TfdLuminance8Alpha8,
1713 TfdLuminance12Alpha4,
1714 TfdLuminance12Alpha12,
1715 TfdLuminance16Alpha16,
1760 FormatDescriptorCS: TCriticalSection;
1761 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1763 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1764 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1766 inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1769 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1770 constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat);
1772 inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1775 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1776 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1778 result.Fields := [];
1781 result.Fields := result.Fields + [ffX];
1783 result.Fields := result.Fields + [ffY];
1785 result.X := Max(0, X);
1786 result.Y := Max(0, Y);
1789 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1790 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1798 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1799 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1804 for i := 0 to high(r1.arr) do
1805 if (r1.arr[i] <> r2.arr[i]) then
1810 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1811 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1819 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1820 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1829 tfR3G3B2, tfLuminance8,
1832 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1833 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1839 tfRGB10, tfRGB10A2, tfRGBA8,
1840 tfBGR10, tfBGR10A2, tfBGRA8]) then
1841 result := result + [ftBMP];
1845 tfLuminance8, tfAlpha8,
1848 tfLuminance16, tfLuminance8Alpha8,
1849 tfRGB5, tfRGB5A1, tfRGBA4,
1850 tfBGR5, tfBGR5A1, tfBGRA4,
1856 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1857 result := result + [ftTGA];
1861 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1862 tfR3G3B2, tfRGBA2, tfBGRA2,
1865 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1866 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1867 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1873 tfLuminance16Alpha16,
1878 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1879 result := result + [ftDDS];
1881 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1883 tfAlpha8, tfLuminance8, tfLuminance8Alpha8,
1885 tfBGR8, tfBGRA8] then
1886 result := result + [ftPNG];
1889 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1890 if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then
1891 result := result + [ftJPEG];
1895 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1896 function IsPowerOfTwo(aNumber: Integer): Boolean;
1898 while (aNumber and 1) = 0 do
1899 aNumber := aNumber shr 1;
1900 result := aNumber = 1;
1903 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1904 function GetTopMostBit(aBitSet: QWord): Integer;
1907 while aBitSet > 0 do begin
1909 aBitSet := aBitSet shr 1;
1913 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1914 function CountSetBits(aBitSet: QWord): Integer;
1917 while aBitSet > 0 do begin
1918 if (aBitSet and 1) = 1 then
1920 aBitSet := aBitSet shr 1;
1924 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1925 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1928 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1929 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1930 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1933 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1934 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1937 DEPTH_WEIGHT_R * aPixel.Data.r +
1938 DEPTH_WEIGHT_G * aPixel.Data.g +
1939 DEPTH_WEIGHT_B * aPixel.Data.b);
1942 {$IFDEF GLB_NATIVE_OGL}
1943 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1944 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1945 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1947 GL_LibHandle: Pointer = nil;
1949 function glbGetProcAddress(aProcName: PAnsiChar; aLibHandle: Pointer = nil; const aRaiseOnErr: Boolean = true): Pointer;
1951 if not Assigned(aLibHandle) then
1952 aLibHandle := GL_LibHandle;
1954 {$IF DEFINED(GLB_WIN)}
1955 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1956 if Assigned(result) then
1959 if Assigned(wglGetProcAddress) then
1960 result := wglGetProcAddress(aProcName);
1961 {$ELSEIF DEFINED(GLB_LINUX)}
1962 if Assigned(glXGetProcAddress) then begin
1963 result := glXGetProcAddress(aProcName);
1964 if Assigned(result) then
1968 if Assigned(glXGetProcAddressARB) then begin
1969 result := glXGetProcAddressARB(aProcName);
1970 if Assigned(result) then
1974 result := dlsym(aLibHandle, aProcName);
1976 if not Assigned(result) and aRaiseOnErr then
1977 raise EglBitmap.Create('unable to load procedure form library: ' + aProcName);
1980 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1982 GLU_LibHandle: Pointer = nil;
1983 OpenGLInitialized: Boolean;
1984 InitOpenGLCS: TCriticalSection;
1986 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1987 procedure glbInitOpenGL;
1989 ////////////////////////////////////////////////////////////////////////////////
1990 function glbLoadLibrary(const aName: PChar): Pointer;
1992 {$IF DEFINED(GLB_WIN)}
1993 result := {%H-}Pointer(LoadLibrary(aName));
1994 {$ELSEIF DEFINED(GLB_LINUX)}
1995 result := dlopen(Name, RTLD_LAZY);
2001 ////////////////////////////////////////////////////////////////////////////////
2002 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
2005 if not Assigned(aLibHandle) then
2008 {$IF DEFINED(GLB_WIN)}
2009 Result := FreeLibrary({%H-}HINST(aLibHandle));
2010 {$ELSEIF DEFINED(GLB_LINUX)}
2011 Result := dlclose(aLibHandle) = 0;
2016 if Assigned(GL_LibHandle) then
2017 glbFreeLibrary(GL_LibHandle);
2019 if Assigned(GLU_LibHandle) then
2020 glbFreeLibrary(GLU_LibHandle);
2022 GL_LibHandle := glbLoadLibrary(libopengl);
2023 if not Assigned(GL_LibHandle) then
2024 raise EglBitmap.Create('unable to load library: ' + libopengl);
2026 GLU_LibHandle := glbLoadLibrary(libglu);
2027 if not Assigned(GLU_LibHandle) then
2028 raise EglBitmap.Create('unable to load library: ' + libglu);
2030 {$IF DEFINED(GLB_WIN)}
2031 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
2032 {$ELSEIF DEFINED(GLB_LINUX)}
2033 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
2034 glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
2037 glEnable := glbGetProcAddress('glEnable');
2038 glDisable := glbGetProcAddress('glDisable');
2039 glGetString := glbGetProcAddress('glGetString');
2040 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
2041 glTexParameteri := glbGetProcAddress('glTexParameteri');
2042 glTexParameteriv := glbGetProcAddress('glTexParameteriv');
2043 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
2044 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
2045 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
2046 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
2047 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
2048 glTexGeni := glbGetProcAddress('glTexGeni');
2049 glGenTextures := glbGetProcAddress('glGenTextures');
2050 glBindTexture := glbGetProcAddress('glBindTexture');
2051 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
2052 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
2053 glReadPixels := glbGetProcAddress('glReadPixels');
2054 glPixelStorei := glbGetProcAddress('glPixelStorei');
2055 glTexImage1D := glbGetProcAddress('glTexImage1D');
2056 glTexImage2D := glbGetProcAddress('glTexImage2D');
2057 glGetTexImage := glbGetProcAddress('glGetTexImage');
2059 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
2060 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
2064 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2065 procedure glbReadOpenGLExtensions;
2068 MajorVersion, MinorVersion: Integer;
2070 ///////////////////////////////////////////////////////////////////////////////////////////
2071 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
2078 Separator := Pos(AnsiString('.'), aBuffer);
2079 if (Separator > 1) and (Separator < Length(aBuffer)) and
2080 (aBuffer[Separator - 1] in ['0'..'9']) and
2081 (aBuffer[Separator + 1] in ['0'..'9']) then begin
2084 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
2087 Delete(aBuffer, 1, Separator);
2088 Separator := Pos(AnsiString('.'), aBuffer) + 1;
2090 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
2093 Delete(aBuffer, Separator, 255);
2094 Separator := Pos(AnsiString('.'), aBuffer);
2096 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
2097 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2101 ///////////////////////////////////////////////////////////////////////////////////////////
2102 function CheckExtension(const Extension: AnsiString): Boolean;
2106 ExtPos := Pos(Extension, Buffer);
2107 result := ExtPos > 0;
2109 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2112 ///////////////////////////////////////////////////////////////////////////////////////////
2113 function CheckVersion(const aMajor, aMinor: Integer): Boolean;
2115 result := (MajorVersion > aMajor) or ((MajorVersion = aMajor) and (MinorVersion >= aMinor));
2119 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2122 if not OpenGLInitialized then begin
2124 OpenGLInitialized := true;
2132 Buffer := glGetString(GL_VERSION);
2133 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2135 GL_VERSION_1_2 := CheckVersion(1, 2);
2136 GL_VERSION_1_3 := CheckVersion(1, 3);
2137 GL_VERSION_1_4 := CheckVersion(1, 4);
2138 GL_VERSION_2_0 := CheckVersion(2, 0);
2139 GL_VERSION_3_3 := CheckVersion(3, 3);
2142 Buffer := glGetString(GL_EXTENSIONS);
2143 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2144 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2145 GL_ARB_texture_swizzle := CheckExtension('GL_ARB_texture_swizzle');
2146 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
2147 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2148 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2149 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2150 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2151 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2152 GL_EXT_texture_swizzle := CheckExtension('GL_EXT_texture_swizzle');
2153 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
2154 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2155 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2156 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2158 if GL_VERSION_1_3 then begin
2159 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2160 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2161 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2163 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB', nil, false);
2164 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB', nil, false);
2165 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB', nil, false);
2170 {$IFDEF GLB_SDL_IMAGE}
2171 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2172 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2173 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2174 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2176 result := TStream(context^.unknown.data1).Seek(offset, whence);
2179 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2181 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2184 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2186 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2189 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2194 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2196 result := SDL_AllocRW;
2198 if result = nil then
2199 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2201 result^.seek := glBitmapRWseek;
2202 result^.read := glBitmapRWread;
2203 result^.write := glBitmapRWwrite;
2204 result^.close := glBitmapRWclose;
2205 result^.unknown.data1 := Stream;
2209 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2210 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2212 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2216 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2218 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2221 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2222 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2224 glBitmapDefaultMipmap := aValue;
2227 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2228 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2230 glBitmapDefaultFormat := aFormat;
2233 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2234 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2236 glBitmapDefaultFilterMin := aMin;
2237 glBitmapDefaultFilterMag := aMag;
2240 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2241 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2243 glBitmapDefaultWrapS := S;
2244 glBitmapDefaultWrapT := T;
2245 glBitmapDefaultWrapR := R;
2248 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2249 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
2251 glDefaultSwizzle[0] := r;
2252 glDefaultSwizzle[1] := g;
2253 glDefaultSwizzle[2] := b;
2254 glDefaultSwizzle[3] := a;
2257 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2258 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2260 result := glBitmapDefaultDeleteTextureOnFree;
2263 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2264 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2266 result := glBitmapDefaultFreeDataAfterGenTextures;
2269 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2270 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2272 result := glBitmapDefaultMipmap;
2275 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2276 function glBitmapGetDefaultFormat: TglBitmapFormat;
2278 result := glBitmapDefaultFormat;
2281 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2282 procedure glBitmapGetDefaultFilter(var aMin, aMag: GLenum);
2284 aMin := glBitmapDefaultFilterMin;
2285 aMag := glBitmapDefaultFilterMag;
2288 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2289 procedure glBitmapGetDefaultTextureWrap(var S, T, R: GLenum);
2291 S := glBitmapDefaultWrapS;
2292 T := glBitmapDefaultWrapT;
2293 R := glBitmapDefaultWrapR;
2296 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2297 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
2299 r := glDefaultSwizzle[0];
2300 g := glDefaultSwizzle[1];
2301 b := glDefaultSwizzle[2];
2302 a := glDefaultSwizzle[3];
2305 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2306 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2307 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2308 function TFormatDescriptor.GetRedMask: QWord;
2310 result := fRange.r shl fShift.r;
2313 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2314 function TFormatDescriptor.GetGreenMask: QWord;
2316 result := fRange.g shl fShift.g;
2319 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2320 function TFormatDescriptor.GetBlueMask: QWord;
2322 result := fRange.b shl fShift.b;
2325 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2326 function TFormatDescriptor.GetAlphaMask: QWord;
2328 result := fRange.a shl fShift.a;
2331 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2332 function TFormatDescriptor.GetIsCompressed: Boolean;
2334 result := fIsCompressed;
2337 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2338 function TFormatDescriptor.GetHasAlpha: Boolean;
2340 result := (fRange.a > 0);
2343 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2344 function TFormatDescriptor.GetglFormat: GLenum;
2346 result := fglFormat;
2349 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2350 function TFormatDescriptor.GetglInternalFormat: GLenum;
2352 result := fglInternalFormat;
2355 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2356 function TFormatDescriptor.GetglDataFormat: GLenum;
2358 result := fglDataFormat;
2361 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2362 function TFormatDescriptor.GetComponents: Integer;
2368 if (fRange.arr[i] > 0) then
2372 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2373 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2377 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2378 w := Max(1, aSize.X);
2379 h := Max(1, aSize.Y);
2380 result := GetSize(w, h);
2385 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2386 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2389 if (aWidth <= 0) or (aHeight <= 0) then
2391 result := Ceil(aWidth * aHeight * fPixelSize);
2394 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2395 function TFormatDescriptor.CreateMappingData: Pointer;
2400 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2401 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2406 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2407 function TFormatDescriptor.IsEmpty: Boolean;
2409 result := (fFormat = tfEmpty);
2412 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2413 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2416 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2417 raise EglBitmap.Create('FormatCheckFormat - All Masks are 0');
2418 if (aRedMask <> RedMask) then
2420 if (aGreenMask <> GreenMask) then
2422 if (aBlueMask <> BlueMask) then
2424 if (aAlphaMask <> AlphaMask) then
2429 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2430 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2432 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2433 aPixel.Data := fRange;
2434 aPixel.Range := fRange;
2435 aPixel.Format := fFormat;
2438 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2439 constructor TFormatDescriptor.Create;
2444 fWithAlpha := tfEmpty;
2445 fWithoutAlpha := tfEmpty;
2446 fRGBInverted := tfEmpty;
2447 fUncompressed := tfEmpty;
2449 fIsCompressed := false;
2452 fglInternalFormat := 0;
2455 FillChar(fRange, 0, SizeOf(fRange));
2456 FillChar(fShift, 0, SizeOf(fShift));
2459 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2460 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2461 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2462 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2464 aData^ := aPixel.Data.a;
2468 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2473 aPixel.Data.a := aData^;
2477 constructor TfdAlpha_UB1.Create;
2482 fglFormat := GL_ALPHA;
2483 fglDataFormat := GL_UNSIGNED_BYTE;
2486 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2487 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2488 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2489 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2491 aData^ := LuminanceWeight(aPixel);
2495 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2497 aPixel.Data.r := aData^;
2498 aPixel.Data.g := aData^;
2499 aPixel.Data.b := aData^;
2504 constructor TfdLuminance_UB1.Create;
2511 fglFormat := GL_LUMINANCE;
2512 fglDataFormat := GL_UNSIGNED_BYTE;
2515 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2516 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2517 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2518 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2524 if (fRange.arr[i] > 0) then
2525 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2529 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2534 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2538 constructor TfdUniversal_UB1.Create;
2544 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2545 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2546 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2547 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2549 inherited Map(aPixel, aData, aMapData);
2550 aData^ := aPixel.Data.a;
2554 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2556 inherited Unmap(aData, aPixel, aMapData);
2557 aPixel.Data.a := aData^;
2561 constructor TfdLuminanceAlpha_UB2.Create;
2567 fglFormat := GL_LUMINANCE_ALPHA;
2568 fglDataFormat := GL_UNSIGNED_BYTE;
2571 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2572 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2573 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2574 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2576 aData^ := aPixel.Data.r;
2578 aData^ := aPixel.Data.g;
2580 aData^ := aPixel.Data.b;
2584 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2586 aPixel.Data.r := aData^;
2588 aPixel.Data.g := aData^;
2590 aPixel.Data.b := aData^;
2595 constructor TfdRGB_UB3.Create;
2605 fglFormat := GL_RGB;
2606 fglDataFormat := GL_UNSIGNED_BYTE;
2609 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2610 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2611 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2612 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2614 aData^ := aPixel.Data.b;
2616 aData^ := aPixel.Data.g;
2618 aData^ := aPixel.Data.r;
2622 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2624 aPixel.Data.b := aData^;
2626 aPixel.Data.g := aData^;
2628 aPixel.Data.r := aData^;
2633 constructor TfdBGR_UB3.Create;
2642 fglFormat := GL_BGR;
2643 fglDataFormat := GL_UNSIGNED_BYTE;
2646 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2647 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2648 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2649 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2651 inherited Map(aPixel, aData, aMapData);
2652 aData^ := aPixel.Data.a;
2656 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2658 inherited Unmap(aData, aPixel, aMapData);
2659 aPixel.Data.a := aData^;
2663 constructor TfdRGBA_UB4.Create;
2669 fglFormat := GL_RGBA;
2670 fglDataFormat := GL_UNSIGNED_BYTE;
2673 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2674 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2675 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2676 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2678 inherited Map(aPixel, aData, aMapData);
2679 aData^ := aPixel.Data.a;
2683 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2685 inherited Unmap(aData, aPixel, aMapData);
2686 aPixel.Data.a := aData^;
2690 constructor TfdBGRA_UB4.Create;
2696 fglFormat := GL_BGRA;
2697 fglDataFormat := GL_UNSIGNED_BYTE;
2700 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2701 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2702 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2703 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2705 PWord(aData)^ := aPixel.Data.a;
2709 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2714 aPixel.Data.a := PWord(aData)^;
2718 constructor TfdAlpha_US1.Create;
2723 fglFormat := GL_ALPHA;
2724 fglDataFormat := GL_UNSIGNED_SHORT;
2727 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2728 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2729 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2730 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2732 PWord(aData)^ := LuminanceWeight(aPixel);
2736 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2738 aPixel.Data.r := PWord(aData)^;
2739 aPixel.Data.g := PWord(aData)^;
2740 aPixel.Data.b := PWord(aData)^;
2745 constructor TfdLuminance_US1.Create;
2752 fglFormat := GL_LUMINANCE;
2753 fglDataFormat := GL_UNSIGNED_SHORT;
2756 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2757 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2758 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2759 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2765 if (fRange.arr[i] > 0) then
2766 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2770 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2775 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2779 constructor TfdUniversal_US1.Create;
2785 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2786 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2787 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2788 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2790 PWord(aData)^ := DepthWeight(aPixel);
2794 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2796 aPixel.Data.r := PWord(aData)^;
2797 aPixel.Data.g := PWord(aData)^;
2798 aPixel.Data.b := PWord(aData)^;
2803 constructor TfdDepth_US1.Create;
2810 fglFormat := GL_DEPTH_COMPONENT;
2811 fglDataFormat := GL_UNSIGNED_SHORT;
2814 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2815 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2816 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2817 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2819 inherited Map(aPixel, aData, aMapData);
2820 PWord(aData)^ := aPixel.Data.a;
2824 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2826 inherited Unmap(aData, aPixel, aMapData);
2827 aPixel.Data.a := PWord(aData)^;
2831 constructor TfdLuminanceAlpha_US2.Create;
2837 fglFormat := GL_LUMINANCE_ALPHA;
2838 fglDataFormat := GL_UNSIGNED_SHORT;
2841 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2842 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2843 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2844 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2846 PWord(aData)^ := aPixel.Data.r;
2848 PWord(aData)^ := aPixel.Data.g;
2850 PWord(aData)^ := aPixel.Data.b;
2854 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2856 aPixel.Data.r := PWord(aData)^;
2858 aPixel.Data.g := PWord(aData)^;
2860 aPixel.Data.b := PWord(aData)^;
2865 constructor TfdRGB_US3.Create;
2875 fglFormat := GL_RGB;
2876 fglDataFormat := GL_UNSIGNED_SHORT;
2879 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2880 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2881 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2882 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2884 PWord(aData)^ := aPixel.Data.b;
2886 PWord(aData)^ := aPixel.Data.g;
2888 PWord(aData)^ := aPixel.Data.r;
2892 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2894 aPixel.Data.b := PWord(aData)^;
2896 aPixel.Data.g := PWord(aData)^;
2898 aPixel.Data.r := PWord(aData)^;
2903 constructor TfdBGR_US3.Create;
2913 fglFormat := GL_BGR;
2914 fglDataFormat := GL_UNSIGNED_SHORT;
2917 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2918 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2919 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2920 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2922 inherited Map(aPixel, aData, aMapData);
2923 PWord(aData)^ := aPixel.Data.a;
2927 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2929 inherited Unmap(aData, aPixel, aMapData);
2930 aPixel.Data.a := PWord(aData)^;
2934 constructor TfdRGBA_US4.Create;
2940 fglFormat := GL_RGBA;
2941 fglDataFormat := GL_UNSIGNED_SHORT;
2944 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2945 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2946 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2947 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2949 inherited Map(aPixel, aData, aMapData);
2950 PWord(aData)^ := aPixel.Data.a;
2954 procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2956 inherited Unmap(aData, aPixel, aMapData);
2957 aPixel.Data.a := PWord(aData)^;
2961 constructor TfdBGRA_US4.Create;
2967 fglFormat := GL_BGRA;
2968 fglDataFormat := GL_UNSIGNED_SHORT;
2971 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2972 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2973 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2974 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2978 PCardinal(aData)^ := 0;
2980 if (fRange.arr[i] > 0) then
2981 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2985 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2990 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2994 constructor TfdUniversal_UI1.Create;
3000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3001 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3002 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3003 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3005 PCardinal(aData)^ := DepthWeight(aPixel);
3009 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3011 aPixel.Data.r := PCardinal(aData)^;
3012 aPixel.Data.g := PCardinal(aData)^;
3013 aPixel.Data.b := PCardinal(aData)^;
3018 constructor TfdDepth_UI1.Create;
3022 fRange.r := $FFFFFFFF;
3023 fRange.g := $FFFFFFFF;
3024 fRange.b := $FFFFFFFF;
3025 fglFormat := GL_DEPTH_COMPONENT;
3026 fglDataFormat := GL_UNSIGNED_INT;
3029 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3030 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3031 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3032 constructor TfdAlpha4.Create;
3035 fFormat := tfAlpha4;
3036 fWithAlpha := tfAlpha4;
3037 fglInternalFormat := GL_ALPHA4;
3040 constructor TfdAlpha8.Create;
3043 fFormat := tfAlpha8;
3044 fWithAlpha := tfAlpha8;
3045 fglInternalFormat := GL_ALPHA8;
3048 constructor TfdAlpha12.Create;
3051 fFormat := tfAlpha12;
3052 fWithAlpha := tfAlpha12;
3053 fglInternalFormat := GL_ALPHA12;
3056 constructor TfdAlpha16.Create;
3059 fFormat := tfAlpha16;
3060 fWithAlpha := tfAlpha16;
3061 fglInternalFormat := GL_ALPHA16;
3064 constructor TfdLuminance4.Create;
3067 fFormat := tfLuminance4;
3068 fWithAlpha := tfLuminance4Alpha4;
3069 fWithoutAlpha := tfLuminance4;
3070 fglInternalFormat := GL_LUMINANCE4;
3073 constructor TfdLuminance8.Create;
3076 fFormat := tfLuminance8;
3077 fWithAlpha := tfLuminance8Alpha8;
3078 fWithoutAlpha := tfLuminance8;
3079 fglInternalFormat := GL_LUMINANCE8;
3082 constructor TfdLuminance12.Create;
3085 fFormat := tfLuminance12;
3086 fWithAlpha := tfLuminance12Alpha12;
3087 fWithoutAlpha := tfLuminance12;
3088 fglInternalFormat := GL_LUMINANCE12;
3091 constructor TfdLuminance16.Create;
3094 fFormat := tfLuminance16;
3095 fWithAlpha := tfLuminance16Alpha16;
3096 fWithoutAlpha := tfLuminance16;
3097 fglInternalFormat := GL_LUMINANCE16;
3100 constructor TfdLuminance4Alpha4.Create;
3103 fFormat := tfLuminance4Alpha4;
3104 fWithAlpha := tfLuminance4Alpha4;
3105 fWithoutAlpha := tfLuminance4;
3106 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3109 constructor TfdLuminance6Alpha2.Create;
3112 fFormat := tfLuminance6Alpha2;
3113 fWithAlpha := tfLuminance6Alpha2;
3114 fWithoutAlpha := tfLuminance8;
3115 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3118 constructor TfdLuminance8Alpha8.Create;
3121 fFormat := tfLuminance8Alpha8;
3122 fWithAlpha := tfLuminance8Alpha8;
3123 fWithoutAlpha := tfLuminance8;
3124 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3127 constructor TfdLuminance12Alpha4.Create;
3130 fFormat := tfLuminance12Alpha4;
3131 fWithAlpha := tfLuminance12Alpha4;
3132 fWithoutAlpha := tfLuminance12;
3133 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3136 constructor TfdLuminance12Alpha12.Create;
3139 fFormat := tfLuminance12Alpha12;
3140 fWithAlpha := tfLuminance12Alpha12;
3141 fWithoutAlpha := tfLuminance12;
3142 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3145 constructor TfdLuminance16Alpha16.Create;
3148 fFormat := tfLuminance16Alpha16;
3149 fWithAlpha := tfLuminance16Alpha16;
3150 fWithoutAlpha := tfLuminance16;
3151 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3154 constructor TfdR3G3B2.Create;
3157 fFormat := tfR3G3B2;
3158 fWithAlpha := tfRGBA2;
3159 fWithoutAlpha := tfR3G3B2;
3166 fglFormat := GL_RGB;
3167 fglInternalFormat := GL_R3_G3_B2;
3168 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3171 constructor TfdRGB4.Create;
3175 fWithAlpha := tfRGBA4;
3176 fWithoutAlpha := tfRGB4;
3177 fRGBInverted := tfBGR4;
3184 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3185 fglInternalFormat := GL_RGB4;
3186 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3189 constructor TfdR5G6B5.Create;
3192 fFormat := tfR5G6B5;
3193 fWithAlpha := tfRGBA4;
3194 fWithoutAlpha := tfR5G6B5;
3195 fRGBInverted := tfB5G6R5;
3202 fglFormat := GL_RGB;
3203 fglInternalFormat := GL_RGB565;
3204 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3207 constructor TfdRGB5.Create;
3211 fWithAlpha := tfRGB5A1;
3212 fWithoutAlpha := tfRGB5;
3213 fRGBInverted := tfBGR5;
3220 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3221 fglInternalFormat := GL_RGB5;
3222 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3225 constructor TfdRGB8.Create;
3229 fWithAlpha := tfRGBA8;
3230 fWithoutAlpha := tfRGB8;
3231 fRGBInverted := tfBGR8;
3232 fglInternalFormat := GL_RGB8;
3235 constructor TfdRGB10.Create;
3239 fWithAlpha := tfRGB10A2;
3240 fWithoutAlpha := tfRGB10;
3241 fRGBInverted := tfBGR10;
3248 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3249 fglInternalFormat := GL_RGB10;
3250 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3253 constructor TfdRGB12.Create;
3257 fWithAlpha := tfRGBA12;
3258 fWithoutAlpha := tfRGB12;
3259 fRGBInverted := tfBGR12;
3260 fglInternalFormat := GL_RGB12;
3263 constructor TfdRGB16.Create;
3267 fWithAlpha := tfRGBA16;
3268 fWithoutAlpha := tfRGB16;
3269 fRGBInverted := tfBGR16;
3270 fglInternalFormat := GL_RGB16;
3273 constructor TfdRGBA2.Create;
3277 fWithAlpha := tfRGBA2;
3278 fWithoutAlpha := tfR3G3B2;
3279 fRGBInverted := tfBGRA2;
3280 fglInternalFormat := GL_RGBA2;
3283 constructor TfdRGBA4.Create;
3287 fWithAlpha := tfRGBA4;
3288 fWithoutAlpha := tfRGB4;
3289 fRGBInverted := tfBGRA4;
3298 fglFormat := GL_RGBA;
3299 fglInternalFormat := GL_RGBA4;
3300 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3303 constructor TfdRGB5A1.Create;
3306 fFormat := tfRGB5A1;
3307 fWithAlpha := tfRGB5A1;
3308 fWithoutAlpha := tfRGB5;
3309 fRGBInverted := tfBGR5A1;
3318 fglFormat := GL_RGBA;
3319 fglInternalFormat := GL_RGB5_A1;
3320 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3323 constructor TfdRGBA8.Create;
3327 fWithAlpha := tfRGBA8;
3328 fWithoutAlpha := tfRGB8;
3329 fRGBInverted := tfBGRA8;
3330 fglInternalFormat := GL_RGBA8;
3333 constructor TfdRGB10A2.Create;
3336 fFormat := tfRGB10A2;
3337 fWithAlpha := tfRGB10A2;
3338 fWithoutAlpha := tfRGB10;
3339 fRGBInverted := tfBGR10A2;
3348 fglFormat := GL_RGBA;
3349 fglInternalFormat := GL_RGB10_A2;
3350 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3353 constructor TfdRGBA12.Create;
3356 fFormat := tfRGBA12;
3357 fWithAlpha := tfRGBA12;
3358 fWithoutAlpha := tfRGB12;
3359 fRGBInverted := tfBGRA12;
3360 fglInternalFormat := GL_RGBA12;
3363 constructor TfdRGBA16.Create;
3366 fFormat := tfRGBA16;
3367 fWithAlpha := tfRGBA16;
3368 fWithoutAlpha := tfRGB16;
3369 fRGBInverted := tfBGRA16;
3370 fglInternalFormat := GL_RGBA16;
3373 constructor TfdBGR4.Create;
3378 fWithAlpha := tfBGRA4;
3379 fWithoutAlpha := tfBGR4;
3380 fRGBInverted := tfRGB4;
3389 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3390 fglInternalFormat := GL_RGB4;
3391 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3394 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3395 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3396 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3397 constructor TfdB5G6R5.Create;
3400 fFormat := tfB5G6R5;
3401 fWithAlpha := tfBGRA4;
3402 fWithoutAlpha := tfB5G6R5;
3403 fRGBInverted := tfR5G6B5;
3410 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3411 fglInternalFormat := GL_RGB8;
3412 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3415 constructor TfdBGR5.Create;
3420 fWithAlpha := tfBGR5A1;
3421 fWithoutAlpha := tfBGR5;
3422 fRGBInverted := tfRGB5;
3431 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3432 fglInternalFormat := GL_RGB5;
3433 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3436 constructor TfdBGR8.Create;
3440 fWithAlpha := tfBGRA8;
3441 fWithoutAlpha := tfBGR8;
3442 fRGBInverted := tfRGB8;
3443 fglInternalFormat := GL_RGB8;
3446 constructor TfdBGR10.Create;
3450 fWithAlpha := tfBGR10A2;
3451 fWithoutAlpha := tfBGR10;
3452 fRGBInverted := tfRGB10;
3461 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3462 fglInternalFormat := GL_RGB10;
3463 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3466 constructor TfdBGR12.Create;
3470 fWithAlpha := tfBGRA12;
3471 fWithoutAlpha := tfBGR12;
3472 fRGBInverted := tfRGB12;
3473 fglInternalFormat := GL_RGB12;
3476 constructor TfdBGR16.Create;
3480 fWithAlpha := tfBGRA16;
3481 fWithoutAlpha := tfBGR16;
3482 fRGBInverted := tfRGB16;
3483 fglInternalFormat := GL_RGB16;
3486 constructor TfdBGRA2.Create;
3490 fWithAlpha := tfBGRA4;
3491 fWithoutAlpha := tfBGR4;
3492 fRGBInverted := tfRGBA2;
3493 fglInternalFormat := GL_RGBA2;
3496 constructor TfdBGRA4.Create;
3500 fWithAlpha := tfBGRA4;
3501 fWithoutAlpha := tfBGR4;
3502 fRGBInverted := tfRGBA4;
3511 fglFormat := GL_BGRA;
3512 fglInternalFormat := GL_RGBA4;
3513 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3516 constructor TfdBGR5A1.Create;
3519 fFormat := tfBGR5A1;
3520 fWithAlpha := tfBGR5A1;
3521 fWithoutAlpha := tfBGR5;
3522 fRGBInverted := tfRGB5A1;
3531 fglFormat := GL_BGRA;
3532 fglInternalFormat := GL_RGB5_A1;
3533 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3536 constructor TfdBGRA8.Create;
3540 fWithAlpha := tfBGRA8;
3541 fWithoutAlpha := tfBGR8;
3542 fRGBInverted := tfRGBA8;
3543 fglInternalFormat := GL_RGBA8;
3546 constructor TfdBGR10A2.Create;
3549 fFormat := tfBGR10A2;
3550 fWithAlpha := tfBGR10A2;
3551 fWithoutAlpha := tfBGR10;
3552 fRGBInverted := tfRGB10A2;
3561 fglFormat := GL_BGRA;
3562 fglInternalFormat := GL_RGB10_A2;
3563 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3566 constructor TfdBGRA12.Create;
3569 fFormat := tfBGRA12;
3570 fWithAlpha := tfBGRA12;
3571 fWithoutAlpha := tfBGR12;
3572 fRGBInverted := tfRGBA12;
3573 fglInternalFormat := GL_RGBA12;
3576 constructor TfdBGRA16.Create;
3579 fFormat := tfBGRA16;
3580 fWithAlpha := tfBGRA16;
3581 fWithoutAlpha := tfBGR16;
3582 fRGBInverted := tfRGBA16;
3583 fglInternalFormat := GL_RGBA16;
3586 constructor TfdDepth16.Create;
3589 fFormat := tfDepth16;
3590 fWithAlpha := tfEmpty;
3591 fWithoutAlpha := tfDepth16;
3592 fglInternalFormat := GL_DEPTH_COMPONENT16;
3595 constructor TfdDepth24.Create;
3598 fFormat := tfDepth24;
3599 fWithAlpha := tfEmpty;
3600 fWithoutAlpha := tfDepth24;
3601 fglInternalFormat := GL_DEPTH_COMPONENT24;
3604 constructor TfdDepth32.Create;
3607 fFormat := tfDepth32;
3608 fWithAlpha := tfEmpty;
3609 fWithoutAlpha := tfDepth32;
3610 fglInternalFormat := GL_DEPTH_COMPONENT32;
3613 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3614 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3616 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3618 raise EglBitmap.Create('mapping for compressed formats is not supported');
3621 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3623 raise EglBitmap.Create('mapping for compressed formats is not supported');
3626 constructor TfdS3tcDtx1RGBA.Create;
3629 fFormat := tfS3tcDtx1RGBA;
3630 fWithAlpha := tfS3tcDtx1RGBA;
3631 fUncompressed := tfRGB5A1;
3633 fIsCompressed := true;
3634 fglFormat := GL_COMPRESSED_RGBA;
3635 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3636 fglDataFormat := GL_UNSIGNED_BYTE;
3639 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3640 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3641 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3642 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3644 raise EglBitmap.Create('mapping for compressed formats is not supported');
3647 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3649 raise EglBitmap.Create('mapping for compressed formats is not supported');
3652 constructor TfdS3tcDtx3RGBA.Create;
3655 fFormat := tfS3tcDtx3RGBA;
3656 fWithAlpha := tfS3tcDtx3RGBA;
3657 fUncompressed := tfRGBA8;
3659 fIsCompressed := true;
3660 fglFormat := GL_COMPRESSED_RGBA;
3661 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3662 fglDataFormat := GL_UNSIGNED_BYTE;
3665 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3666 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3667 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3668 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3670 raise EglBitmap.Create('mapping for compressed formats is not supported');
3673 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3675 raise EglBitmap.Create('mapping for compressed formats is not supported');
3678 constructor TfdS3tcDtx5RGBA.Create;
3681 fFormat := tfS3tcDtx3RGBA;
3682 fWithAlpha := tfS3tcDtx3RGBA;
3683 fUncompressed := tfRGBA8;
3685 fIsCompressed := true;
3686 fglFormat := GL_COMPRESSED_RGBA;
3687 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3688 fglDataFormat := GL_UNSIGNED_BYTE;
3691 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3692 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3693 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3694 class procedure TFormatDescriptor.Init;
3696 if not Assigned(FormatDescriptorCS) then
3697 FormatDescriptorCS := TCriticalSection.Create;
3700 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3701 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3703 FormatDescriptorCS.Enter;
3705 result := FormatDescriptors[aFormat];
3706 if not Assigned(result) then begin
3707 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3708 FormatDescriptors[aFormat] := result;
3711 FormatDescriptorCS.Leave;
3715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3716 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3718 result := Get(Get(aFormat).WithAlpha);
3721 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3722 class procedure TFormatDescriptor.Clear;
3726 FormatDescriptorCS.Enter;
3728 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3729 FreeAndNil(FormatDescriptors[f]);
3731 FormatDescriptorCS.Leave;
3735 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3736 class procedure TFormatDescriptor.Finalize;
3739 FreeAndNil(FormatDescriptorCS);
3742 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3743 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3744 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3745 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3747 Update(aValue, fRange.r, fShift.r);
3750 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3751 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3753 Update(aValue, fRange.g, fShift.g);
3756 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3757 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3759 Update(aValue, fRange.b, fShift.b);
3762 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3763 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3765 Update(aValue, fRange.a, fShift.a);
3768 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3769 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3776 while (aMask > 0) and ((aMask and 1) = 0) do begin
3778 aMask := aMask shr 1;
3781 while (aMask > 0) do begin
3782 aRange := aRange shl 1;
3783 aMask := aMask shr 1;
3787 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3790 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3791 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3797 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3798 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3799 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3800 ((aPixel.Data.a and fRange.a) shl fShift.a);
3801 s := Round(fPixelSize);
3804 2: PWord(aData)^ := data;
3805 4: PCardinal(aData)^ := data;
3806 8: PQWord(aData)^ := data;
3808 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3813 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3814 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3819 s := Round(fPixelSize);
3822 2: data := PWord(aData)^;
3823 4: data := PCardinal(aData)^;
3824 8: data := PQWord(aData)^;
3826 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3829 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3833 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3834 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3835 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3836 procedure TbmpColorTableFormat.CreateColorTable;
3840 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3841 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3843 if (Format = tfLuminance4) then
3844 SetLength(fColorTable, 16)
3846 SetLength(fColorTable, 256);
3850 for i := 0 to High(fColorTable) do begin
3851 fColorTable[i].r := 16 * i;
3852 fColorTable[i].g := 16 * i;
3853 fColorTable[i].b := 16 * i;
3854 fColorTable[i].a := 0;
3859 for i := 0 to High(fColorTable) do begin
3860 fColorTable[i].r := i;
3861 fColorTable[i].g := i;
3862 fColorTable[i].b := i;
3863 fColorTable[i].a := 0;
3868 for i := 0 to High(fColorTable) do begin
3869 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3870 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3871 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3872 fColorTable[i].a := 0;
3878 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3879 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3883 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3884 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3888 if (aMapData = nil) then
3890 d := LuminanceWeight(aPixel) and Range.r;
3891 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3892 inc(PByte(aMapData), 4);
3893 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3900 aData^ := LuminanceWeight(aPixel) and Range.r;
3906 ((aPixel.Data.r and Range.r) shl Shift.r) or
3907 ((aPixel.Data.g and Range.g) shl Shift.g) or
3908 ((aPixel.Data.b and Range.b) shl Shift.b));
3914 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3915 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3922 s := Trunc(fPixelSize);
3923 f := fPixelSize - s;
3924 bits := Round(8 * f);
3926 0: idx := (aData^ shr (8 - bits - {%H-}PtrInt(aMapData))) and ((1 shl bits) - 1);
3928 2: idx := PWord(aData)^;
3929 4: idx := PCardinal(aData)^;
3930 8: idx := PQWord(aData)^;
3932 raise EglBitmap.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3934 if (idx >= Length(fColorTable)) then
3935 raise EglBitmap.CreateFmt('invalid color index: %d', [idx]);
3936 with fColorTable[idx] do begin
3942 inc(PByte(aMapData), bits);
3943 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3945 dec(PByte(aMapData), 8);
3950 destructor TbmpColorTableFormat.Destroy;
3952 SetLength(fColorTable, 0);
3956 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3957 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3958 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3959 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
3963 for i := 0 to 3 do begin
3964 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
3965 if (aSourceFD.Range.arr[i] > 0) then
3966 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
3968 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
3973 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3974 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
3976 with aFuncRec do begin
3977 if (Source.Range.r > 0) then
3978 Dest.Data.r := Source.Data.r;
3979 if (Source.Range.g > 0) then
3980 Dest.Data.g := Source.Data.g;
3981 if (Source.Range.b > 0) then
3982 Dest.Data.b := Source.Data.b;
3983 if (Source.Range.a > 0) then
3984 Dest.Data.a := Source.Data.a;
3988 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3989 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3993 with aFuncRec do begin
3995 if (Source.Range.arr[i] > 0) then
3996 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4001 TShiftData = packed record
4003 0: (r, g, b, a: SmallInt);
4004 1: (arr: array[0..3] of SmallInt);
4006 PShiftData = ^TShiftData;
4008 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4009 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4015 if (Source.Range.arr[i] > 0) then
4016 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4019 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4020 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4022 with aFuncRec do begin
4023 Dest.Data := Source.Data;
4024 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4025 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4026 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4027 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4029 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4030 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4035 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4036 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4040 with aFuncRec do begin
4042 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4046 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4047 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4051 with FuncRec do begin
4052 if (FuncRec.Args = nil) then begin //source has no alpha
4054 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4055 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4056 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4057 Dest.Data.a := Round(Dest.Range.a * Temp);
4059 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4063 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4064 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4066 PglBitmapPixelData = ^TglBitmapPixelData;
4068 with FuncRec do begin
4069 Dest.Data.r := Source.Data.r;
4070 Dest.Data.g := Source.Data.g;
4071 Dest.Data.b := Source.Data.b;
4073 with PglBitmapPixelData(Args)^ do
4074 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4075 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4076 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4079 Dest.Data.a := Dest.Range.a;
4083 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4084 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4086 with FuncRec do begin
4087 Dest.Data.r := Source.Data.r;
4088 Dest.Data.g := Source.Data.g;
4089 Dest.Data.b := Source.Data.b;
4090 Dest.Data.a := PCardinal(Args)^;
4094 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4095 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4098 TRGBPix = array [0..2] of byte;
4102 while aWidth > 0 do begin
4103 Temp := PRGBPix(aData)^[0];
4104 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4105 PRGBPix(aData)^[2] := Temp;
4115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4116 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4117 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4118 function TglBitmap.GetFormatDesc: TglBitmapFormatDescriptor;
4120 result := TFormatDescriptor.Get(Format);
4123 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4124 function TglBitmap.GetWidth: Integer;
4126 if (ffX in fDimension.Fields) then
4127 result := fDimension.X
4132 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4133 function TglBitmap.GetHeight: Integer;
4135 if (ffY in fDimension.Fields) then
4136 result := fDimension.Y
4141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4142 function TglBitmap.GetFileWidth: Integer;
4144 result := Max(1, Width);
4147 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4148 function TglBitmap.GetFileHeight: Integer;
4150 result := Max(1, Height);
4153 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4154 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4156 if fCustomData = aValue then
4158 fCustomData := aValue;
4161 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4162 procedure TglBitmap.SetCustomName(const aValue: String);
4164 if fCustomName = aValue then
4166 fCustomName := aValue;
4169 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4170 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4172 if fCustomNameW = aValue then
4174 fCustomNameW := aValue;
4177 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4178 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4180 if fDeleteTextureOnFree = aValue then
4182 fDeleteTextureOnFree := aValue;
4185 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4186 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4188 if fFormat = aValue then
4190 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4191 raise EglBitmapUnsupportedFormat.Create(Format);
4192 SetDataPointer(fData, aValue, Width, Height); //be careful, Data could be freed by this method
4195 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4196 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4198 if fFreeDataAfterGenTexture = aValue then
4200 fFreeDataAfterGenTexture := aValue;
4203 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4204 procedure TglBitmap.SetID(const aValue: Cardinal);
4206 if fID = aValue then
4211 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4212 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4214 if fMipMap = aValue then
4219 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4220 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4222 if fTarget = aValue then
4227 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4228 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4230 MaxAnisotropic: Integer;
4232 fAnisotropic := aValue;
4233 if (ID > 0) then begin
4234 if GL_EXT_texture_filter_anisotropic then begin
4235 if fAnisotropic > 0 then begin
4237 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4238 if aValue > MaxAnisotropic then
4239 fAnisotropic := MaxAnisotropic;
4240 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4248 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4249 procedure TglBitmap.CreateID;
4252 glDeleteTextures(1, @fID);
4253 glGenTextures(1, @fID);
4257 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4258 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4260 // Set Up Parameters
4261 SetWrap(fWrapS, fWrapT, fWrapR);
4262 SetFilter(fFilterMin, fFilterMag);
4263 SetAnisotropic(fAnisotropic);
4264 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4266 if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
4267 SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4269 // Mip Maps Generation Mode
4270 aBuildWithGlu := false;
4271 if (MipMap = mmMipmap) then begin
4272 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4273 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4275 aBuildWithGlu := true;
4276 end else if (MipMap = mmMipmapGlu) then
4277 aBuildWithGlu := true;
4280 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4281 procedure TglBitmap.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
4282 const aWidth: Integer; const aHeight: Integer);
4286 if (Data <> aData) then begin
4287 if (Assigned(Data)) then
4292 if not Assigned(fData) then begin
4296 FillChar(fDimension, SizeOf(fDimension), 0);
4297 if aWidth <> -1 then begin
4298 fDimension.Fields := fDimension.Fields + [ffX];
4299 fDimension.X := aWidth;
4302 if aHeight <> -1 then begin
4303 fDimension.Fields := fDimension.Fields + [ffY];
4304 fDimension.Y := aHeight;
4307 s := TFormatDescriptor.Get(aFormat).PixelSize;
4309 fPixelSize := Ceil(s);
4310 fRowSize := Ceil(s * aWidth);
4314 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4315 function TglBitmap.FlipHorz: Boolean;
4320 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4321 function TglBitmap.FlipVert: Boolean;
4326 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4327 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4328 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4329 procedure TglBitmap.AfterConstruction;
4331 inherited AfterConstruction;
4335 fIsResident := false;
4337 fFormat := glBitmapGetDefaultFormat;
4338 fMipMap := glBitmapDefaultMipmap;
4339 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4340 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4342 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4343 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4344 glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4347 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4348 procedure TglBitmap.BeforeDestruction;
4353 SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
4354 if (fID > 0) and fDeleteTextureOnFree then
4355 glDeleteTextures(1, @fID);
4356 inherited BeforeDestruction;
4359 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4360 procedure TglBitmap.PrepareResType(var aResource: String; var aResType: PChar);
4364 if not Assigned(aResType) then begin
4365 TempPos := Pos('.', aResource);
4366 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4367 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4371 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4372 procedure TglBitmap.LoadFromFile(const aFilename: String);
4376 if not FileExists(aFilename) then
4377 raise EglBitmap.Create('file does not exist: ' + aFilename);
4378 fFilename := aFilename;
4379 fs := TFileStream.Create(fFilename, fmOpenRead);
4388 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4389 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4391 {$IFDEF GLB_SUPPORT_PNG_READ}
4392 if not LoadPNG(aStream) then
4394 {$IFDEF GLB_SUPPORT_JPEG_READ}
4395 if not LoadJPEG(aStream) then
4397 if not LoadDDS(aStream) then
4398 if not LoadTGA(aStream) then
4399 if not LoadBMP(aStream) then
4400 raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4403 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4404 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4405 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4410 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4411 GetMem(tmpData, size);
4413 FillChar(tmpData^, size, #$FF);
4414 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
4416 if Assigned(tmpData) then
4420 AddFunc(Self, aFunc, false, Format, aArgs);
4423 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4424 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
4426 rs: TResourceStream;
4428 PrepareResType(aResource, aResType);
4429 rs := TResourceStream.Create(aInstance, aResource, aResType);
4437 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4438 procedure TglBitmap.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4440 rs: TResourceStream;
4442 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
4450 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4451 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4455 fs := TFileStream.Create(aFileName, fmCreate);
4458 SaveToStream(fs, aFileType);
4464 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4465 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4468 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4469 ftPNG: SavePNG(aStream);
4471 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4472 ftJPEG: SaveJPEG(aStream);
4474 ftDDS: SaveDDS(aStream);
4475 ftTGA: SaveTGA(aStream);
4476 ftBMP: SaveBMP(aStream);
4480 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4481 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4483 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4486 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4487 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4488 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4490 DestData, TmpData, SourceData: pByte;
4491 TempHeight, TempWidth: Integer;
4492 SourceFD, DestFD: TFormatDescriptor;
4493 SourceMD, DestMD: Pointer;
4495 FuncRec: TglBitmapFunctionRec;
4497 Assert(Assigned(Data));
4498 Assert(Assigned(aSource));
4499 Assert(Assigned(aSource.Data));
4502 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4503 SourceFD := TFormatDescriptor.Get(aSource.Format);
4504 DestFD := TFormatDescriptor.Get(aFormat);
4506 if (SourceFD.IsCompressed) then
4507 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
4508 if (DestFD.IsCompressed) then
4509 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
4511 // inkompatible Formats so CreateTemp
4512 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4513 aCreateTemp := true;
4516 TempHeight := Max(1, aSource.Height);
4517 TempWidth := Max(1, aSource.Width);
4519 FuncRec.Sender := Self;
4520 FuncRec.Args := aArgs;
4523 if aCreateTemp then begin
4524 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
4525 DestData := TmpData;
4530 SourceFD.PreparePixel(FuncRec.Source);
4531 DestFD.PreparePixel (FuncRec.Dest);
4533 SourceMD := SourceFD.CreateMappingData;
4534 DestMD := DestFD.CreateMappingData;
4536 FuncRec.Size := aSource.Dimension;
4537 FuncRec.Position.Fields := FuncRec.Size.Fields;
4540 SourceData := aSource.Data;
4541 FuncRec.Position.Y := 0;
4542 while FuncRec.Position.Y < TempHeight do begin
4543 FuncRec.Position.X := 0;
4544 while FuncRec.Position.X < TempWidth do begin
4545 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4547 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4548 inc(FuncRec.Position.X);
4550 inc(FuncRec.Position.Y);
4553 // Updating Image or InternalFormat
4555 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) //be careful, Data could be freed by this method
4556 else if (aFormat <> fFormat) then
4561 SourceFD.FreeMappingData(SourceMD);
4562 DestFD.FreeMappingData(DestMD);
4565 if aCreateTemp and Assigned(TmpData) then
4573 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4574 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4576 Row, RowSize: Integer;
4577 SourceData, TmpData: PByte;
4579 FormatDesc: TFormatDescriptor;
4581 function GetRowPointer(Row: Integer): pByte;
4583 result := aSurface.pixels;
4584 Inc(result, Row * RowSize);
4590 FormatDesc := TFormatDescriptor.Get(Format);
4591 if FormatDesc.IsCompressed then
4592 raise EglBitmapUnsupportedFormat.Create(Format);
4594 if Assigned(Data) then begin
4595 case Trunc(FormatDesc.PixelSize) of
4601 raise EglBitmapUnsupportedFormat.Create(Format);
4604 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4605 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4607 RowSize := FormatDesc.GetSize(FileWidth, 1);
4609 for Row := 0 to FileHeight-1 do begin
4610 TmpData := GetRowPointer(Row);
4611 if Assigned(TmpData) then begin
4612 Move(SourceData^, TmpData^, RowSize);
4613 inc(SourceData, RowSize);
4620 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4621 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4623 pSource, pData, pTempData: PByte;
4624 Row, RowSize, TempWidth, TempHeight: Integer;
4625 IntFormat: TglBitmapFormat;
4626 FormatDesc: TFormatDescriptor;
4628 function GetRowPointer(Row: Integer): pByte;
4630 result := aSurface^.pixels;
4631 Inc(result, Row * RowSize);
4636 if (Assigned(aSurface)) then begin
4637 with aSurface^.format^ do begin
4638 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4639 FormatDesc := TFormatDescriptor.Get(IntFormat);
4640 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4643 if (IntFormat = tfEmpty) then
4644 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4647 TempWidth := aSurface^.w;
4648 TempHeight := aSurface^.h;
4649 RowSize := FormatDesc.GetSize(TempWidth, 1);
4650 GetMem(pData, TempHeight * RowSize);
4653 for Row := 0 to TempHeight -1 do begin
4654 pSource := GetRowPointer(Row);
4655 if (Assigned(pSource)) then begin
4656 Move(pSource^, pTempData^, RowSize);
4657 Inc(pTempData, RowSize);
4660 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4663 if Assigned(pData) then
4670 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4671 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4673 Row, Col, AlphaInterleave: Integer;
4674 pSource, pDest: PByte;
4676 function GetRowPointer(Row: Integer): pByte;
4678 result := aSurface.pixels;
4679 Inc(result, Row * Width);
4684 if Assigned(Data) then begin
4685 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4686 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4688 AlphaInterleave := 0;
4691 AlphaInterleave := 1;
4693 AlphaInterleave := 3;
4697 for Row := 0 to Height -1 do begin
4698 pDest := GetRowPointer(Row);
4699 if Assigned(pDest) then begin
4700 for Col := 0 to Width -1 do begin
4701 Inc(pSource, AlphaInterleave);
4713 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4714 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4718 bmp := TglBitmap2D.Create;
4720 bmp.AssignFromSurface(aSurface);
4721 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4729 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4730 function CreateGrayPalette: HPALETTE;
4735 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
4737 Pal.palVersion := $300;
4738 Pal.palNumEntries := 256;
4740 for Idx := 0 to Pal.palNumEntries - 1 do begin
4741 Pal.palPalEntry[Idx].peRed := Idx;
4742 Pal.palPalEntry[Idx].peGreen := Idx;
4743 Pal.palPalEntry[Idx].peBlue := Idx;
4744 Pal.palPalEntry[Idx].peFlags := 0;
4746 Result := CreatePalette(Pal^);
4750 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4751 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4754 pSource, pData: PByte;
4757 if Assigned(Data) then begin
4758 if Assigned(aBitmap) then begin
4759 aBitmap.Width := Width;
4760 aBitmap.Height := Height;
4763 tfAlpha8, tfLuminance8: begin
4764 aBitmap.PixelFormat := pf8bit;
4765 aBitmap.Palette := CreateGrayPalette;
4768 aBitmap.PixelFormat := pf15bit;
4770 aBitmap.PixelFormat := pf16bit;
4772 aBitmap.PixelFormat := pf24bit;
4774 aBitmap.PixelFormat := pf32bit;
4776 raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.');
4780 for Row := 0 to FileHeight -1 do begin
4781 pData := aBitmap.Scanline[Row];
4782 Move(pSource^, pData^, fRowSize);
4783 Inc(pSource, fRowSize);
4784 if (Format in [tfRGB8, tfRGBA8]) then // swap RGB(A) to BGR(A)
4785 SwapRGB(pData, FileWidth, Format = tfRGBA8);
4792 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4793 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4795 pSource, pData, pTempData: PByte;
4796 Row, RowSize, TempWidth, TempHeight: Integer;
4797 IntFormat: TglBitmapFormat;
4801 if (Assigned(aBitmap)) then begin
4802 case aBitmap.PixelFormat of
4804 IntFormat := tfLuminance8;
4806 IntFormat := tfRGB5A1;
4808 IntFormat := tfR5G6B5;
4810 IntFormat := tfBGR8;
4812 IntFormat := tfBGRA8;
4814 raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.');
4817 TempWidth := aBitmap.Width;
4818 TempHeight := aBitmap.Height;
4819 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
4820 GetMem(pData, TempHeight * RowSize);
4823 for Row := 0 to TempHeight -1 do begin
4824 pSource := aBitmap.Scanline[Row];
4825 if (Assigned(pSource)) then begin
4826 Move(pSource^, pTempData^, RowSize);
4827 Inc(pTempData, RowSize);
4830 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4833 if Assigned(pData) then
4840 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4841 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4843 Row, Col, AlphaInterleave: Integer;
4844 pSource, pDest: PByte;
4848 if Assigned(Data) then begin
4849 if (Format in [tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8]) then begin
4850 if Assigned(aBitmap) then begin
4851 aBitmap.PixelFormat := pf8bit;
4852 aBitmap.Palette := CreateGrayPalette;
4853 aBitmap.Width := Width;
4854 aBitmap.Height := Height;
4858 AlphaInterleave := 1;
4860 AlphaInterleave := 3;
4862 AlphaInterleave := 0;
4868 for Row := 0 to Height -1 do begin
4869 pDest := aBitmap.Scanline[Row];
4870 if Assigned(pDest) then begin
4871 for Col := 0 to Width -1 do begin
4872 Inc(pSource, AlphaInterleave);
4885 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4886 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4890 tex := TglBitmap2D.Create;
4892 tex.AssignFromBitmap(ABitmap);
4893 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4900 {$IFDEF GLB_LAZARUS}
4901 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4902 function TglBitmap.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4904 rid: TRawImageDescription;
4905 FormatDesc: TFormatDescriptor;
4908 if not Assigned(aImage) or (Format = tfEmpty) then
4910 FormatDesc := TFormatDescriptor.Get(Format);
4911 if FormatDesc.IsCompressed then
4914 FillChar(rid{%H-}, SizeOf(rid), 0);
4916 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
4917 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
4918 tfLuminance4Alpha4, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16]) then
4919 rid.Format := ricfGray
4921 rid.Format := ricfRGBA;
4924 rid.Height := Height;
4925 rid.Depth := CountSetBits(FormatDesc.RedMask or FormatDesc.GreenMask or FormatDesc.BlueMask or FormatDesc.AlphaMask);
4926 rid.BitOrder := riboBitsInOrder;
4927 rid.ByteOrder := riboLSBFirst;
4928 rid.LineOrder := riloTopToBottom;
4929 rid.LineEnd := rileTight;
4930 rid.BitsPerPixel := Round(8 * FormatDesc.PixelSize);
4931 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
4932 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
4933 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
4934 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
4935 rid.RedShift := FormatDesc.Shift.r;
4936 rid.GreenShift := FormatDesc.Shift.g;
4937 rid.BlueShift := FormatDesc.Shift.b;
4938 rid.AlphaShift := FormatDesc.Shift.a;
4940 rid.MaskBitsPerPixel := 0;
4941 rid.PaletteColorCount := 0;
4943 aImage.DataDescription := rid;
4946 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
4951 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4952 function TglBitmap.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
4955 FormatDesc: TFormatDescriptor;
4960 if not Assigned(aImage) then
4962 for f := High(f) downto Low(f) do begin
4963 FormatDesc := TFormatDescriptor.Get(f);
4964 with aImage.DataDescription do
4965 if FormatDesc.MaskMatch(
4966 (QWord(1 shl RedPrec )-1) shl RedShift,
4967 (QWord(1 shl GreenPrec)-1) shl GreenShift,
4968 (QWord(1 shl BluePrec )-1) shl BlueShift,
4969 (QWord(1 shl AlphaPrec)-1) shl AlphaShift) then
4973 if (f = tfEmpty) then
4976 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
4977 ImageData := GetMem(ImageSize);
4979 Move(aImage.PixelData^, ImageData^, (aImage.Width * aImage.Height * aImage.DataDescription.BitsPerPixel) shr 3);
4980 SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method
4982 if Assigned(ImageData) then
4990 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4991 function TglBitmap.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4993 rid: TRawImageDescription;
4994 FormatDesc: TFormatDescriptor;
4995 Pixel: TglBitmapPixelData;
5001 if not Assigned(aImage) or (Format = tfEmpty) then
5003 FormatDesc := TFormatDescriptor.Get(Format);
5004 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5007 FillChar(rid{%H-}, SizeOf(rid), 0);
5008 rid.Format := ricfGray;
5010 rid.Height := Height;
5011 rid.Depth := CountSetBits(FormatDesc.Range.a);
5012 rid.BitOrder := riboBitsInOrder;
5013 rid.ByteOrder := riboLSBFirst;
5014 rid.LineOrder := riloTopToBottom;
5015 rid.LineEnd := rileTight;
5016 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
5017 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
5022 rid.GreenShift := 0;
5024 rid.AlphaShift := 0;
5026 rid.MaskBitsPerPixel := 0;
5027 rid.PaletteColorCount := 0;
5029 aImage.DataDescription := rid;
5032 srcMD := FormatDesc.CreateMappingData;
5034 FormatDesc.PreparePixel(Pixel);
5036 dst := aImage.PixelData;
5037 for y := 0 to Height-1 do
5038 for x := 0 to Width-1 do begin
5039 FormatDesc.Unmap(src, Pixel, srcMD);
5040 case rid.BitsPerPixel of
5042 dst^ := Pixel.Data.a;
5046 PWord(dst)^ := Pixel.Data.a;
5050 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
5051 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
5052 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
5056 PCardinal(dst)^ := Pixel.Data.a;
5060 raise EglBitmapUnsupportedFormat.Create(Format);
5064 FormatDesc.FreeMappingData(srcMD);
5069 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5070 function TglBitmap.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5074 tex := TglBitmap2D.Create;
5076 tex.AssignFromLazIntfImage(aImage);
5077 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5084 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5085 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
5086 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5088 rs: TResourceStream;
5090 PrepareResType(aResource, aResType);
5091 rs := TResourceStream.Create(aInstance, aResource, aResType);
5093 result := AddAlphaFromStream(rs, aFunc, aArgs);
5099 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5100 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
5101 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5103 rs: TResourceStream;
5105 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
5107 result := AddAlphaFromStream(rs, aFunc, aArgs);
5113 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5114 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5116 if TFormatDescriptor.Get(Format).IsCompressed then
5117 raise EglBitmapUnsupportedFormat.Create(Format);
5118 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
5121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5122 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5126 FS := TFileStream.Create(aFileName, fmOpenRead);
5128 result := AddAlphaFromStream(FS, aFunc, aArgs);
5134 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5135 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5139 tex := TglBitmap2D.Create(aStream);
5141 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5147 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5148 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5150 DestData, DestData2, SourceData: pByte;
5151 TempHeight, TempWidth: Integer;
5152 SourceFD, DestFD: TFormatDescriptor;
5153 SourceMD, DestMD, DestMD2: Pointer;
5155 FuncRec: TglBitmapFunctionRec;
5159 Assert(Assigned(Data));
5160 Assert(Assigned(aBitmap));
5161 Assert(Assigned(aBitmap.Data));
5163 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
5164 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
5166 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
5167 DestFD := TFormatDescriptor.Get(Format);
5169 if not Assigned(aFunc) then begin
5170 aFunc := glBitmapAlphaFunc;
5171 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5173 FuncRec.Args := aArgs;
5176 TempHeight := aBitmap.FileHeight;
5177 TempWidth := aBitmap.FileWidth;
5179 FuncRec.Sender := Self;
5180 FuncRec.Size := Dimension;
5181 FuncRec.Position.Fields := FuncRec.Size.Fields;
5185 SourceData := aBitmap.Data;
5188 SourceFD.PreparePixel(FuncRec.Source);
5189 DestFD.PreparePixel (FuncRec.Dest);
5191 SourceMD := SourceFD.CreateMappingData;
5192 DestMD := DestFD.CreateMappingData;
5193 DestMD2 := DestFD.CreateMappingData;
5195 FuncRec.Position.Y := 0;
5196 while FuncRec.Position.Y < TempHeight do begin
5197 FuncRec.Position.X := 0;
5198 while FuncRec.Position.X < TempWidth do begin
5199 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5200 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5202 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5203 inc(FuncRec.Position.X);
5205 inc(FuncRec.Position.Y);
5208 SourceFD.FreeMappingData(SourceMD);
5209 DestFD.FreeMappingData(DestMD);
5210 DestFD.FreeMappingData(DestMD2);
5215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5216 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5218 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5221 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5222 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5224 PixelData: TglBitmapPixelData;
5226 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5227 result := AddAlphaFromColorKeyFloat(
5228 aRed / PixelData.Range.r,
5229 aGreen / PixelData.Range.g,
5230 aBlue / PixelData.Range.b,
5231 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5234 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5235 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5237 values: array[0..2] of Single;
5240 PixelData: TglBitmapPixelData;
5242 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5243 with PixelData do begin
5245 values[1] := aGreen;
5248 for i := 0 to 2 do begin
5249 tmp := Trunc(Range.arr[i] * aDeviation);
5250 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5251 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5256 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5259 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5260 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5262 result := AddAlphaFromValueFloat(aAlpha / $FF);
5265 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5266 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5268 PixelData: TglBitmapPixelData;
5270 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5271 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5274 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5275 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5277 PixelData: TglBitmapPixelData;
5279 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5281 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5282 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5285 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5286 function TglBitmap.RemoveAlpha: Boolean;
5288 FormatDesc: TFormatDescriptor;
5291 FormatDesc := TFormatDescriptor.Get(Format);
5292 if Assigned(Data) then begin
5293 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5294 raise EglBitmapUnsupportedFormat.Create(Format);
5295 result := ConvertTo(FormatDesc.WithoutAlpha);
5299 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5300 function TglBitmap.Clone: TglBitmap;
5307 Temp := (ClassType.Create as TglBitmap);
5309 // copy texture data if assigned
5310 if Assigned(Data) then begin
5311 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5312 GetMem(TempPtr, Size);
5314 Move(Data^, TempPtr^, Size);
5315 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5317 if Assigned(TempPtr) then
5323 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5328 Temp.fTarget := Target;
5329 Temp.fFormat := Format;
5330 Temp.fMipMap := MipMap;
5331 Temp.fAnisotropic := Anisotropic;
5332 Temp.fBorderColor := fBorderColor;
5333 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5334 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5335 Temp.fFilterMin := fFilterMin;
5336 Temp.fFilterMag := fFilterMag;
5337 Temp.fWrapS := fWrapS;
5338 Temp.fWrapT := fWrapT;
5339 Temp.fWrapR := fWrapR;
5340 Temp.fFilename := fFilename;
5341 Temp.fCustomName := fCustomName;
5342 Temp.fCustomNameW := fCustomNameW;
5343 Temp.fCustomData := fCustomData;
5352 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5353 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5355 SourceFD, DestFD: TFormatDescriptor;
5356 SourcePD, DestPD: TglBitmapPixelData;
5357 ShiftData: TShiftData;
5359 function CanCopyDirect: Boolean;
5362 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5363 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5364 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5365 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5368 function CanShift: Boolean;
5371 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5372 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5373 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5374 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5377 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5380 while (aSource > aDest) and (aSource > 0) do begin
5382 aSource := aSource shr 1;
5387 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5388 SourceFD := TFormatDescriptor.Get(Format);
5389 DestFD := TFormatDescriptor.Get(aFormat);
5391 SourceFD.PreparePixel(SourcePD);
5392 DestFD.PreparePixel (DestPD);
5394 if CanCopyDirect then
5395 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5396 else if CanShift then begin
5397 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5398 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5399 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5400 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5401 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5403 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5408 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5409 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5411 if aUseRGB or aUseAlpha then
5412 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5413 ((Byte(aUseAlpha) and 1) shl 1) or
5414 (Byte(aUseRGB) and 1) ));
5417 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5418 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5420 fBorderColor[0] := aRed;
5421 fBorderColor[1] := aGreen;
5422 fBorderColor[2] := aBlue;
5423 fBorderColor[3] := aAlpha;
5424 if (ID > 0) then begin
5426 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5430 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5431 procedure TglBitmap.FreeData;
5436 SetDataPointer(TempPtr, tfEmpty); //be careful, Data could be freed by this method
5439 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5440 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5441 const aAlpha: Byte);
5443 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5446 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5447 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5449 PixelData: TglBitmapPixelData;
5451 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5453 aRed / PixelData.Range.r,
5454 aGreen / PixelData.Range.g,
5455 aBlue / PixelData.Range.b,
5456 aAlpha / PixelData.Range.a);
5459 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5460 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5462 PixelData: TglBitmapPixelData;
5464 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5465 with PixelData do begin
5466 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5467 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5468 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5469 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5471 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5474 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5475 procedure TglBitmap.SetFilter(const aMin, aMag: GLenum);
5480 fFilterMin := GL_NEAREST;
5482 fFilterMin := GL_LINEAR;
5483 GL_NEAREST_MIPMAP_NEAREST:
5484 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5485 GL_LINEAR_MIPMAP_NEAREST:
5486 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5487 GL_NEAREST_MIPMAP_LINEAR:
5488 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5489 GL_LINEAR_MIPMAP_LINEAR:
5490 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5492 raise EglBitmap.Create('SetFilter - Unknow MIN filter.');
5498 fFilterMag := GL_NEAREST;
5500 fFilterMag := GL_LINEAR;
5502 raise EglBitmap.Create('SetFilter - Unknow MAG filter.');
5506 if (ID > 0) then begin
5508 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5510 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5512 GL_NEAREST, GL_LINEAR:
5513 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5514 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5515 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5516 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5517 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5520 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5524 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5525 procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum);
5527 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5531 aTarget := GL_CLAMP;
5534 aTarget := GL_REPEAT;
5536 GL_CLAMP_TO_EDGE: begin
5537 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5538 aTarget := GL_CLAMP_TO_EDGE
5540 aTarget := GL_CLAMP;
5543 GL_CLAMP_TO_BORDER: begin
5544 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5545 aTarget := GL_CLAMP_TO_BORDER
5547 aTarget := GL_CLAMP;
5550 GL_MIRRORED_REPEAT: begin
5551 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5552 aTarget := GL_MIRRORED_REPEAT
5554 raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5557 raise EglBitmap.Create('SetWrap - Unknow Texturewrap');
5562 CheckAndSetWrap(S, fWrapS);
5563 CheckAndSetWrap(T, fWrapT);
5564 CheckAndSetWrap(R, fWrapR);
5566 if (ID > 0) then begin
5568 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5569 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5570 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5574 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5575 procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum);
5577 procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer);
5579 if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or
5580 (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then
5581 fSwizzle[aIndex] := aValue
5583 raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value');
5587 if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
5588 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
5589 CheckAndSetValue(r, 0);
5590 CheckAndSetValue(g, 1);
5591 CheckAndSetValue(b, 2);
5592 CheckAndSetValue(a, 3);
5594 if (ID > 0) then begin
5596 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, @fSwizzle[0]);
5600 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5601 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5603 if aEnableTextureUnit then
5606 glBindTexture(Target, ID);
5609 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5610 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5612 if aDisableTextureUnit then
5614 glBindTexture(Target, 0);
5617 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5618 constructor TglBitmap.Create;
5620 if (ClassType = TglBitmap) then
5621 raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5622 {$IFDEF GLB_NATIVE_OGL}
5623 glbReadOpenGLExtensions;
5628 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5629 constructor TglBitmap.Create(const aFileName: String);
5632 LoadFromFile(aFileName);
5635 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5636 constructor TglBitmap.Create(const aStream: TStream);
5639 LoadFromStream(aStream);
5642 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5643 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
5649 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5650 GetMem(Image, ImageSize);
5652 FillChar(Image^, ImageSize, #$FF);
5653 SetDataPointer(Image, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5655 if Assigned(Image) then
5661 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5662 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
5663 const aFunc: TglBitmapFunction; const aArgs: Pointer);
5666 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5669 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5670 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5673 LoadFromResource(aInstance, aResource, aResType);
5676 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5677 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5680 LoadFromResourceID(aInstance, aResourceID, aResType);
5683 {$IFDEF GLB_SUPPORT_PNG_READ}
5684 {$IF DEFINED(GLB_LAZ_PNG)}
5685 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5686 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5687 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5688 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5691 PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A;
5693 png: TPortableNetworkGraphic;
5694 intf: TLazIntfImage;
5696 magic: String[MAGIC_LEN];
5699 StreamPos := aStream.Position;
5701 SetLength(magic, MAGIC_LEN);
5702 aStream.Read(magic[1], MAGIC_LEN);
5703 aStream.Position := StreamPos;
5704 if (magic <> PNG_MAGIC) then begin
5709 png := TPortableNetworkGraphic.Create;
5711 png.LoadFromStream(aStream);
5712 intf := png.CreateIntfImage;
5714 AssignFromLazIntfImage(intf);
5717 aStream.Position := StreamPos;
5725 aStream.Position := StreamPos;
5733 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
5734 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5735 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5737 Surface: PSDL_Surface;
5741 RWops := glBitmapCreateRWops(aStream);
5743 if IMG_isPNG(RWops) > 0 then begin
5744 Surface := IMG_LoadPNG_RW(RWops);
5746 AssignFromSurface(Surface);
5749 SDL_FreeSurface(Surface);
5757 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5758 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5759 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5761 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5764 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5765 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5768 signature: array [0..7] of byte;
5770 png_info: png_infop;
5772 TempHeight, TempWidth: Integer;
5773 Format: TglBitmapFormat;
5776 png_rows: array of pByte;
5777 Row, LineSize: Integer;
5781 if not init_libPNG then
5782 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5786 StreamPos := aStream.Position;
5787 aStream.Read(signature{%H-}, 8);
5788 aStream.Position := StreamPos;
5790 if png_check_sig(@signature, 8) <> 0 then begin
5792 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5794 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5797 png_info := png_create_info_struct(png);
5798 if png_info = nil then begin
5799 png_destroy_read_struct(@png, nil, nil);
5800 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5803 // set read callback
5804 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5806 // read informations
5807 png_read_info(png, png_info);
5810 TempHeight := png_get_image_height(png, png_info);
5811 TempWidth := png_get_image_width(png, png_info);
5814 case png_get_color_type(png, png_info) of
5815 PNG_COLOR_TYPE_GRAY:
5816 Format := tfLuminance8;
5817 PNG_COLOR_TYPE_GRAY_ALPHA:
5818 Format := tfLuminance8Alpha8;
5821 PNG_COLOR_TYPE_RGB_ALPHA:
5824 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5827 // cut upper 8 bit from 16 bit formats
5828 if png_get_bit_depth(png, png_info) > 8 then
5829 png_set_strip_16(png);
5831 // expand bitdepth smaller than 8
5832 if png_get_bit_depth(png, png_info) < 8 then
5833 png_set_expand(png);
5835 // allocating mem for scanlines
5836 LineSize := png_get_rowbytes(png, png_info);
5837 GetMem(png_data, TempHeight * LineSize);
5839 SetLength(png_rows, TempHeight);
5840 for Row := Low(png_rows) to High(png_rows) do begin
5841 png_rows[Row] := png_data;
5842 Inc(png_rows[Row], Row * LineSize);
5845 // read complete image into scanlines
5846 png_read_image(png, @png_rows[0]);
5849 png_read_end(png, png_info);
5851 // destroy read struct
5852 png_destroy_read_struct(@png, @png_info, nil);
5854 SetLength(png_rows, 0);
5857 SetDataPointer(png_data, Format, TempWidth, TempHeight); //be careful, Data could be freed by this method
5861 if Assigned(png_data) then
5871 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5872 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5873 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5878 Row, Col, PixSize, LineSize: Integer;
5879 NewImage, pSource, pDest, pAlpha: pByte;
5880 PngFormat: TglBitmapFormat;
5881 FormatDesc: TFormatDescriptor;
5884 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
5889 StreamPos := aStream.Position;
5890 aStream.Read(Header[0], SizeOf(Header));
5891 aStream.Position := StreamPos;
5893 {Test if the header matches}
5894 if Header = PngHeader then begin
5895 Png := TPNGObject.Create;
5897 Png.LoadFromStream(aStream);
5899 case Png.Header.ColorType of
5901 PngFormat := tfLuminance8;
5902 COLOR_GRAYSCALEALPHA:
5903 PngFormat := tfLuminance8Alpha8;
5905 PngFormat := tfBGR8;
5907 PngFormat := tfBGRA8;
5909 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5912 FormatDesc := TFormatDescriptor.Get(PngFormat);
5913 PixSize := Round(FormatDesc.PixelSize);
5914 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
5916 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5920 case Png.Header.ColorType of
5921 COLOR_RGB, COLOR_GRAYSCALE:
5923 for Row := 0 to Png.Height -1 do begin
5924 Move (Png.Scanline[Row]^, pDest^, LineSize);
5925 Inc(pDest, LineSize);
5928 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5930 PixSize := PixSize -1;
5932 for Row := 0 to Png.Height -1 do begin
5933 pSource := Png.Scanline[Row];
5934 pAlpha := pByte(Png.AlphaScanline[Row]);
5936 for Col := 0 to Png.Width -1 do begin
5937 Move (pSource^, pDest^, PixSize);
5938 Inc(pSource, PixSize);
5939 Inc(pDest, PixSize);
5948 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5951 SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); //be careful, Data could be freed by this method
5955 if Assigned(NewImage) then
5967 {$IFDEF GLB_SUPPORT_PNG_WRITE}
5968 {$IFDEF GLB_LIB_PNG}
5969 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5970 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5972 TStream(png_get_io_ptr(png)).Write(buffer^, size);
5976 {$IF DEFINED(GLB_LAZ_PNG)}
5977 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5978 procedure TglBitmap.SavePNG(const aStream: TStream);
5980 png: TPortableNetworkGraphic;
5981 intf: TLazIntfImage;
5984 png := TPortableNetworkGraphic.Create;
5985 intf := TLazIntfImage.Create(0, 0);
5987 if not AssignToLazIntfImage(intf) then
5988 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
5989 intf.GetRawImage(raw);
5990 png.LoadFromRawImage(raw, false);
5991 png.SaveToStream(aStream);
5998 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5999 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6000 procedure TglBitmap.SavePNG(const aStream: TStream);
6003 png_info: png_infop;
6004 png_rows: array of pByte;
6008 FormatDesc: TFormatDescriptor;
6010 if not (ftPNG in FormatGetSupportedFiles(Format)) then
6011 raise EglBitmapUnsupportedFormat.Create(Format);
6013 if not init_libPNG then
6014 raise Exception.Create('unable to initialize libPNG.');
6018 tfAlpha8, tfLuminance8:
6019 ColorType := PNG_COLOR_TYPE_GRAY;
6021 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
6023 ColorType := PNG_COLOR_TYPE_RGB;
6025 ColorType := PNG_COLOR_TYPE_RGBA;
6027 raise EglBitmapUnsupportedFormat.Create(Format);
6030 FormatDesc := TFormatDescriptor.Get(Format);
6031 LineSize := FormatDesc.GetSize(Width, 1);
6033 // creating array for scanline
6034 SetLength(png_rows, Height);
6036 for Row := 0 to Height - 1 do begin
6037 png_rows[Row] := Data;
6038 Inc(png_rows[Row], Row * LineSize)
6042 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
6044 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
6047 png_info := png_create_info_struct(png);
6048 if png_info = nil then begin
6049 png_destroy_write_struct(@png, nil);
6050 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
6053 // set read callback
6054 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
6057 png_set_compression_level(png, 6);
6059 if Format in [tfBGR8, tfBGRA8] then
6062 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
6063 png_write_info(png, png_info);
6064 png_write_image(png, @png_rows[0]);
6065 png_write_end(png, png_info);
6066 png_destroy_write_struct(@png, @png_info);
6068 SetLength(png_rows, 0);
6075 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
6076 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6077 procedure TglBitmap.SavePNG(const aStream: TStream);
6081 pSource, pDest: pByte;
6082 X, Y, PixSize: Integer;
6083 ColorType: Cardinal;
6089 if not (ftPNG in FormatGetSupportedFiles (Format)) then
6090 raise EglBitmapUnsupportedFormat.Create(Format);
6093 tfAlpha8, tfLuminance8: begin
6094 ColorType := COLOR_GRAYSCALE;
6098 tfLuminance8Alpha8: begin
6099 ColorType := COLOR_GRAYSCALEALPHA;
6103 tfBGR8, tfRGB8: begin
6104 ColorType := COLOR_RGB;
6108 tfBGRA8, tfRGBA8: begin
6109 ColorType := COLOR_RGBALPHA;
6114 raise EglBitmapUnsupportedFormat.Create(Format);
6117 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
6121 for Y := 0 to Height -1 do begin
6122 pDest := png.ScanLine[Y];
6123 for X := 0 to Width -1 do begin
6124 Move(pSource^, pDest^, PixSize);
6125 Inc(pDest, PixSize);
6126 Inc(pSource, PixSize);
6128 png.AlphaScanline[Y]^[X] := pSource^;
6133 // convert RGB line to BGR
6134 if Format in [tfRGB8, tfRGBA8] then begin
6135 pTemp := png.ScanLine[Y];
6136 for X := 0 to Width -1 do begin
6137 Temp := pByteArray(pTemp)^[0];
6138 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
6139 pByteArray(pTemp)^[2] := Temp;
6146 Png.CompressionLevel := 6;
6147 Png.SaveToStream(aStream);
6155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6156 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6157 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6158 {$IFDEF GLB_LIB_JPEG}
6160 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
6161 glBitmap_libJPEG_source_mgr = record
6162 pub: jpeg_source_mgr;
6165 SrcBuffer: array [1..4096] of byte;
6168 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
6169 glBitmap_libJPEG_dest_mgr = record
6170 pub: jpeg_destination_mgr;
6172 DestStream: TStream;
6173 DestBuffer: array [1..4096] of byte;
6176 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
6182 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
6188 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
6193 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
6199 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
6205 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6206 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
6208 src: glBitmap_libJPEG_source_mgr_ptr;
6211 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6213 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
6214 if (bytes <= 0) then begin
6215 src^.SrcBuffer[1] := $FF;
6216 src^.SrcBuffer[2] := JPEG_EOI;
6220 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
6221 src^.pub.bytes_in_buffer := bytes;
6226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6227 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
6229 src: glBitmap_libJPEG_source_mgr_ptr;
6231 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6233 if num_bytes > 0 then begin
6234 // wanted byte isn't in buffer so set stream position and read buffer
6235 if num_bytes > src^.pub.bytes_in_buffer then begin
6236 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
6237 src^.pub.fill_input_buffer(cinfo);
6239 // wanted byte is in buffer so only skip
6240 inc(src^.pub.next_input_byte, num_bytes);
6241 dec(src^.pub.bytes_in_buffer, num_bytes);
6246 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6247 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
6249 dest: glBitmap_libJPEG_dest_mgr_ptr;
6251 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6253 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
6254 // write complete buffer
6255 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
6258 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
6259 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
6265 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6266 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
6269 dest: glBitmap_libJPEG_dest_mgr_ptr;
6271 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6273 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6274 // check for endblock
6275 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6277 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6282 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6287 {$IFDEF GLB_SUPPORT_JPEG_READ}
6288 {$IF DEFINED(GLB_LAZ_JPEG)}
6289 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6290 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6293 JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
6296 intf: TLazIntfImage;
6298 magic: String[MAGIC_LEN];
6301 StreamPos := aStream.Position;
6303 SetLength(magic, MAGIC_LEN);
6304 aStream.Read(magic[1], MAGIC_LEN);
6305 aStream.Position := StreamPos;
6306 if (magic <> JPEG_MAGIC) then begin
6311 jpeg := TJPEGImage.Create;
6313 jpeg.LoadFromStream(aStream);
6314 intf := TLazIntfImage.Create(0, 0);
6316 intf.LoadFromBitmap(jpeg.BitmapHandle, jpeg.MaskHandle);
6317 AssignFromLazIntfImage(intf);
6320 aStream.Position := StreamPos;
6328 aStream.Position := StreamPos;
6336 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
6337 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6338 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6340 Surface: PSDL_Surface;
6345 RWops := glBitmapCreateRWops(aStream);
6347 if IMG_isJPG(RWops) > 0 then begin
6348 Surface := IMG_LoadJPG_RW(RWops);
6350 AssignFromSurface(Surface);
6353 SDL_FreeSurface(Surface);
6361 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6362 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6363 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6366 Temp: array[0..1]of Byte;
6368 jpeg: jpeg_decompress_struct;
6369 jpeg_err: jpeg_error_mgr;
6371 IntFormat: TglBitmapFormat;
6373 TempHeight, TempWidth: Integer;
6378 FormatDesc: TFormatDescriptor;
6382 if not init_libJPEG then
6383 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6386 // reading first two bytes to test file and set cursor back to begin
6387 StreamPos := aStream.Position;
6388 aStream.Read({%H-}Temp[0], 2);
6389 aStream.Position := StreamPos;
6391 // if Bitmap then read file.
6392 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6393 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6394 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6397 jpeg.err := jpeg_std_error(@jpeg_err);
6398 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6399 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6401 // decompression struct
6402 jpeg_create_decompress(@jpeg);
6404 // allocation space for streaming methods
6405 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6407 // seeting up custom functions
6408 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6409 pub.init_source := glBitmap_libJPEG_init_source;
6410 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6411 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6412 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6413 pub.term_source := glBitmap_libJPEG_term_source;
6415 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6416 pub.next_input_byte := nil; // until buffer loaded
6418 SrcStream := aStream;
6421 // set global decoding state
6422 jpeg.global_state := DSTATE_START;
6424 // read header of jpeg
6425 jpeg_read_header(@jpeg, false);
6427 // setting output parameter
6428 case jpeg.jpeg_color_space of
6431 jpeg.out_color_space := JCS_GRAYSCALE;
6432 IntFormat := tfLuminance8;
6435 jpeg.out_color_space := JCS_RGB;
6436 IntFormat := tfRGB8;
6440 jpeg_start_decompress(@jpeg);
6442 TempHeight := jpeg.output_height;
6443 TempWidth := jpeg.output_width;
6445 FormatDesc := TFormatDescriptor.Get(IntFormat);
6447 // creating new image
6448 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6452 for Row := 0 to TempHeight -1 do begin
6453 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6454 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6457 // finish decompression
6458 jpeg_finish_decompress(@jpeg);
6460 // destroy decompression
6461 jpeg_destroy_decompress(@jpeg);
6463 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
6467 if Assigned(pImage) then
6477 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6478 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6479 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6484 Temp: array[0..1]of Byte;
6488 // reading first two bytes to test file and set cursor back to begin
6489 StreamPos := aStream.Position;
6490 aStream.Read(Temp[0], 2);
6491 aStream.Position := StreamPos;
6493 // if Bitmap then read file.
6494 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6495 bmp := TBitmap.Create;
6497 jpg := TJPEGImage.Create;
6499 jpg.LoadFromStream(aStream);
6501 result := AssignFromBitmap(bmp);
6513 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6514 {$IF DEFINED(GLB_LAZ_JPEG)}
6515 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6516 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6519 intf: TLazIntfImage;
6522 jpeg := TJPEGImage.Create;
6523 intf := TLazIntfImage.Create(0, 0);
6525 if not AssignToLazIntfImage(intf) then
6526 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6527 intf.GetRawImage(raw);
6528 jpeg.LoadFromRawImage(raw, false);
6529 jpeg.SaveToStream(aStream);
6536 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6537 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6538 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6540 jpeg: jpeg_compress_struct;
6541 jpeg_err: jpeg_error_mgr;
6543 pTemp, pTemp2: pByte;
6545 procedure CopyRow(pDest, pSource: pByte);
6549 for X := 0 to Width - 1 do begin
6550 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6551 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6552 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6559 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6560 raise EglBitmapUnsupportedFormat.Create(Format);
6562 if not init_libJPEG then
6563 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6566 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6567 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6570 jpeg.err := jpeg_std_error(@jpeg_err);
6571 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6572 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6574 // compression struct
6575 jpeg_create_compress(@jpeg);
6577 // allocation space for streaming methods
6578 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6580 // seeting up custom functions
6581 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6582 pub.init_destination := glBitmap_libJPEG_init_destination;
6583 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6584 pub.term_destination := glBitmap_libJPEG_term_destination;
6586 pub.next_output_byte := @DestBuffer[1];
6587 pub.free_in_buffer := Length(DestBuffer);
6589 DestStream := aStream;
6592 // very important state
6593 jpeg.global_state := CSTATE_START;
6594 jpeg.image_width := Width;
6595 jpeg.image_height := Height;
6597 tfAlpha8, tfLuminance8: begin
6598 jpeg.input_components := 1;
6599 jpeg.in_color_space := JCS_GRAYSCALE;
6601 tfRGB8, tfBGR8: begin
6602 jpeg.input_components := 3;
6603 jpeg.in_color_space := JCS_RGB;
6607 jpeg_set_defaults(@jpeg);
6608 jpeg_set_quality(@jpeg, 95, true);
6609 jpeg_start_compress(@jpeg, true);
6612 if Format = tfBGR8 then
6613 GetMem(pTemp2, fRowSize)
6618 for Row := 0 to jpeg.image_height -1 do begin
6620 if Format = tfBGR8 then
6621 CopyRow(pTemp2, pTemp)
6626 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6627 inc(pTemp, fRowSize);
6631 if Format = tfBGR8 then
6634 jpeg_finish_compress(@jpeg);
6635 jpeg_destroy_compress(@jpeg);
6641 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6642 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6643 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6648 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6649 raise EglBitmapUnsupportedFormat.Create(Format);
6651 Bmp := TBitmap.Create;
6653 Jpg := TJPEGImage.Create;
6655 AssignToBitmap(Bmp);
6656 if (Format in [tfAlpha8, tfLuminance8]) then begin
6657 Jpg.Grayscale := true;
6658 Jpg.PixelFormat := jf8Bit;
6661 Jpg.SaveToStream(aStream);
6672 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6673 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6674 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6681 BMP_COMP_BITFIELDS = 3;
6684 TBMPHeader = packed record
6689 bfOffBits: Cardinal;
6692 TBMPInfo = packed record
6698 biCompression: Cardinal;
6699 biSizeImage: Cardinal;
6700 biXPelsPerMeter: Longint;
6701 biYPelsPerMeter: Longint;
6702 biClrUsed: Cardinal;
6703 biClrImportant: Cardinal;
6706 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6707 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6709 //////////////////////////////////////////////////////////////////////////////////////////////////
6710 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6713 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6714 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6717 case aInfo.biCompression of
6719 BMP_COMP_RLE8: begin
6720 raise EglBitmap.Create('RLE compression is not supported');
6722 BMP_COMP_BITFIELDS: begin
6723 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6724 aStream.Read(aMask.r, SizeOf(aMask.r));
6725 aStream.Read(aMask.g, SizeOf(aMask.g));
6726 aStream.Read(aMask.b, SizeOf(aMask.b));
6727 aStream.Read(aMask.a, SizeOf(aMask.a));
6729 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
6733 //get suitable format
6734 case aInfo.biBitCount of
6735 8: result := tfLuminance8;
6736 16: result := tfBGR5;
6737 24: result := tfBGR8;
6738 32: result := tfBGRA8;
6742 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6745 ColorTable: TbmpColorTable;
6748 if (aInfo.biBitCount >= 16) then
6750 aFormat := tfLuminance8;
6751 c := aInfo.biClrUsed;
6753 c := 1 shl aInfo.biBitCount;
6754 SetLength(ColorTable, c);
6755 for i := 0 to c-1 do begin
6756 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6757 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6761 result := TbmpColorTableFormat.Create;
6762 result.PixelSize := aInfo.biBitCount / 8;
6763 result.ColorTable := ColorTable;
6764 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6767 //////////////////////////////////////////////////////////////////////////////////////////////////
6768 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6769 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6771 TmpFormat: TglBitmapFormat;
6772 FormatDesc: TFormatDescriptor;
6775 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6776 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6777 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6778 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6779 aFormat := FormatDesc.Format;
6784 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6785 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6786 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6787 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6789 result := TbmpBitfieldFormat.Create;
6790 result.PixelSize := aInfo.biBitCount / 8;
6791 result.RedMask := aMask.r;
6792 result.GreenMask := aMask.g;
6793 result.BlueMask := aMask.b;
6794 result.AlphaMask := aMask.a;
6801 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6802 PaddingBuff: Cardinal;
6803 LineBuf, ImageData, TmpData: PByte;
6804 SourceMD, DestMD: Pointer;
6805 BmpFormat: TglBitmapFormat;
6808 Mask: TglBitmapColorRec;
6813 SpecialFormat: TFormatDescriptor;
6814 FormatDesc: TFormatDescriptor;
6816 //////////////////////////////////////////////////////////////////////////////////////////////////
6817 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6820 Pixel: TglBitmapPixelData;
6822 aStream.Read(aLineBuf^, rbLineSize);
6823 SpecialFormat.PreparePixel(Pixel);
6824 for i := 0 to Info.biWidth-1 do begin
6825 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6826 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6827 FormatDesc.Map(Pixel, aData, DestMD);
6833 BmpFormat := tfEmpty;
6834 SpecialFormat := nil;
6840 StartPos := aStream.Position;
6841 aStream.Read(Header{%H-}, SizeOf(Header));
6843 if Header.bfType = BMP_MAGIC then begin
6845 BmpFormat := ReadInfo(Info, Mask);
6846 SpecialFormat := ReadColorTable(BmpFormat, Info);
6847 if not Assigned(SpecialFormat) then
6848 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6849 aStream.Position := StartPos + Header.bfOffBits;
6851 if (BmpFormat <> tfEmpty) then begin
6852 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6853 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6854 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6855 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6858 DestMD := FormatDesc.CreateMappingData;
6859 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6860 GetMem(ImageData, ImageSize);
6861 if Assigned(SpecialFormat) then begin
6862 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6863 SourceMD := SpecialFormat.CreateMappingData;
6868 FillChar(ImageData^, ImageSize, $FF);
6869 TmpData := ImageData;
6870 if (Info.biHeight > 0) then
6871 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6872 for i := 0 to Abs(Info.biHeight)-1 do begin
6873 if Assigned(SpecialFormat) then
6874 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6876 aStream.Read(TmpData^, wbLineSize); //else only read data
6877 if (Info.biHeight > 0) then
6878 dec(TmpData, wbLineSize)
6880 inc(TmpData, wbLineSize);
6881 aStream.Read(PaddingBuff{%H-}, Padding);
6883 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method
6886 if Assigned(LineBuf) then
6888 if Assigned(SourceMD) then
6889 SpecialFormat.FreeMappingData(SourceMD);
6890 FormatDesc.FreeMappingData(DestMD);
6893 if Assigned(ImageData) then
6898 raise EglBitmap.Create('LoadBMP - No suitable format found');
6900 aStream.Position := StartPos;
6904 FreeAndNil(SpecialFormat);
6907 else aStream.Position := StartPos;
6910 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6911 procedure TglBitmap.SaveBMP(const aStream: TStream);
6915 Converter: TFormatDescriptor;
6916 FormatDesc: TFormatDescriptor;
6917 SourceFD, DestFD: Pointer;
6918 pData, srcData, dstData, ConvertBuffer: pByte;
6920 Pixel: TglBitmapPixelData;
6921 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6922 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6924 PaddingBuff: Cardinal;
6926 function GetLineWidth : Integer;
6928 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6932 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6933 raise EglBitmapUnsupportedFormat.Create(Format);
6936 FormatDesc := TFormatDescriptor.Get(Format);
6937 ImageSize := FormatDesc.GetSize(Dimension);
6939 FillChar(Header{%H-}, SizeOf(Header), 0);
6940 Header.bfType := BMP_MAGIC;
6941 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6942 Header.bfReserved1 := 0;
6943 Header.bfReserved2 := 0;
6944 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6946 FillChar(Info{%H-}, SizeOf(Info), 0);
6947 Info.biSize := SizeOf(Info);
6948 Info.biWidth := Width;
6949 Info.biHeight := Height;
6951 Info.biCompression := BMP_COMP_RGB;
6952 Info.biSizeImage := ImageSize;
6957 Info.biBitCount := 4;
6958 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6959 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6960 Converter := TbmpColorTableFormat.Create;
6961 with (Converter as TbmpColorTableFormat) do begin
6964 Range := glBitmapColorRec($F, $F, $F, $0);
6969 tfR3G3B2, tfLuminance8: begin
6970 Info.biBitCount := 8;
6971 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6972 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6973 Converter := TbmpColorTableFormat.Create;
6974 with (Converter as TbmpColorTableFormat) do begin
6977 if (Format = tfR3G3B2) then begin
6978 Range := glBitmapColorRec($7, $7, $3, $0);
6979 Shift := glBitmapShiftRec(0, 3, 6, 0);
6981 Range := glBitmapColorRec($FF, $FF, $FF, $0);
6986 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6987 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6988 Info.biBitCount := 16;
6989 Info.biCompression := BMP_COMP_BITFIELDS;
6992 tfBGR8, tfRGB8: begin
6993 Info.biBitCount := 24;
6994 if (Format = tfRGB8) then
6995 Converter := TfdBGR8.Create; //use BGR8 Format Descriptor to Swap RGB Values
6998 tfRGB10, tfRGB10A2, tfRGBA8,
6999 tfBGR10, tfBGR10A2, tfBGRA8: begin
7000 Info.biBitCount := 32;
7001 Info.biCompression := BMP_COMP_BITFIELDS;
7004 raise EglBitmapUnsupportedFormat.Create(Format);
7006 Info.biXPelsPerMeter := 2835;
7007 Info.biYPelsPerMeter := 2835;
7010 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7011 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
7012 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
7014 RedMask := FormatDesc.RedMask;
7015 GreenMask := FormatDesc.GreenMask;
7016 BlueMask := FormatDesc.BlueMask;
7017 AlphaMask := FormatDesc.AlphaMask;
7021 aStream.Write(Header, SizeOf(Header));
7022 aStream.Write(Info, SizeOf(Info));
7025 if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
7026 with (Converter as TbmpColorTableFormat) do
7027 aStream.Write(ColorTable[0].b,
7028 SizeOf(TbmpColorTableEnty) * Length(ColorTable));
7031 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7032 aStream.Write(RedMask, SizeOf(Cardinal));
7033 aStream.Write(GreenMask, SizeOf(Cardinal));
7034 aStream.Write(BlueMask, SizeOf(Cardinal));
7035 aStream.Write(AlphaMask, SizeOf(Cardinal));
7039 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
7040 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
7041 Padding := GetLineWidth - wbLineSize;
7045 inc(pData, (Height-1) * rbLineSize);
7047 // prepare row buffer. But only for RGB because RGBA supports color masks
7048 // so it's possible to change color within the image.
7049 if Assigned(Converter) then begin
7050 FormatDesc.PreparePixel(Pixel);
7051 GetMem(ConvertBuffer, wbLineSize);
7052 SourceFD := FormatDesc.CreateMappingData;
7053 DestFD := Converter.CreateMappingData;
7055 ConvertBuffer := nil;
7058 for LineIdx := 0 to Height - 1 do begin
7060 if Assigned(Converter) then begin
7062 dstData := ConvertBuffer;
7063 for PixelIdx := 0 to Info.biWidth-1 do begin
7064 FormatDesc.Unmap(srcData, Pixel, SourceFD);
7065 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
7066 Converter.Map(Pixel, dstData, DestFD);
7068 aStream.Write(ConvertBuffer^, wbLineSize);
7070 aStream.Write(pData^, rbLineSize);
7072 dec(pData, rbLineSize);
7073 if (Padding > 0) then
7074 aStream.Write(PaddingBuff, Padding);
7077 // destroy row buffer
7078 if Assigned(ConvertBuffer) then begin
7079 FormatDesc.FreeMappingData(SourceFD);
7080 Converter.FreeMappingData(DestFD);
7081 FreeMem(ConvertBuffer);
7085 if Assigned(Converter) then
7090 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7091 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7092 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7094 TTGAHeader = packed record
7098 //ColorMapSpec: Array[0..4] of Byte;
7099 ColorMapStart: Word;
7100 ColorMapLength: Word;
7101 ColorMapEntrySize: Byte;
7111 TGA_UNCOMPRESSED_RGB = 2;
7112 TGA_UNCOMPRESSED_GRAY = 3;
7113 TGA_COMPRESSED_RGB = 10;
7114 TGA_COMPRESSED_GRAY = 11;
7116 TGA_NONE_COLOR_TABLE = 0;
7118 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7119 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
7122 ImageData: System.PByte;
7123 StartPosition: Int64;
7124 PixelSize, LineSize: Integer;
7125 tgaFormat: TglBitmapFormat;
7126 FormatDesc: TFormatDescriptor;
7127 Counter: packed record
7129 low, high, dir: Integer;
7136 ////////////////////////////////////////////////////////////////////////////////////////
7137 procedure ReadUncompressed;
7140 buf, tmp1, tmp2: System.PByte;
7143 if (Counter.X.dir < 0) then
7144 GetMem(buf, LineSize);
7146 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
7148 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
7149 if (Counter.X.dir < 0) then begin //flip X
7150 aStream.Read(buf^, LineSize);
7152 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
7153 for i := 0 to Header.Width-1 do begin //for all pixels in line
7154 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
7159 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
7162 aStream.Read(tmp1^, LineSize);
7163 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
7166 if Assigned(buf) then
7171 ////////////////////////////////////////////////////////////////////////////////////////
7172 procedure ReadCompressed;
7174 /////////////////////////////////////////////////////////////////
7176 TmpData: System.PByte;
7177 LinePixelsRead: Integer;
7178 procedure CheckLine;
7180 if (LinePixelsRead >= Header.Width) then begin
7181 LinePixelsRead := 0;
7182 inc(Counter.Y.low, Counter.Y.dir); //next line index
7183 TmpData := ImageData;
7184 inc(TmpData, Counter.Y.low * LineSize); //set line
7185 if (Counter.X.dir < 0) then //if x flipped then
7186 inc(TmpData, LineSize - PixelSize); //set last pixel
7190 /////////////////////////////////////////////////////////////////
7193 CacheSize, CachePos: Integer;
7194 procedure CachedRead(out Buffer; Count: Integer);
7198 if (CachePos + Count > CacheSize) then begin
7199 //if buffer overflow save non read bytes
7201 if (CacheSize - CachePos > 0) then begin
7202 BytesRead := CacheSize - CachePos;
7203 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
7204 inc(CachePos, BytesRead);
7207 //load cache from file
7208 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
7209 aStream.Read(Cache^, CacheSize);
7212 //read rest of requested bytes
7213 if (Count - BytesRead > 0) then begin
7214 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
7215 inc(CachePos, Count - BytesRead);
7218 //if no buffer overflow just read the data
7219 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
7220 inc(CachePos, Count);
7224 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
7229 inc(aBuffer, Counter.X.dir);
7232 PWord(aBuffer)^ := PWord(aData)^;
7233 inc(aBuffer, 2 * Counter.X.dir);
7236 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
7237 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
7238 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
7239 inc(aBuffer, 3 * Counter.X.dir);
7242 PCardinal(aBuffer)^ := PCardinal(aData)^;
7243 inc(aBuffer, 4 * Counter.X.dir);
7249 TotalPixelsToRead, TotalPixelsRead: Integer;
7251 buf: array [0..3] of Byte; //1 pixel is max 32bit long
7252 PixelRepeat: Boolean;
7253 PixelsToRead, PixelCount: Integer;
7258 TotalPixelsToRead := Header.Width * Header.Height;
7259 TotalPixelsRead := 0;
7260 LinePixelsRead := 0;
7262 GetMem(Cache, CACHE_SIZE);
7264 TmpData := ImageData;
7265 inc(TmpData, Counter.Y.low * LineSize); //set line
7266 if (Counter.X.dir < 0) then //if x flipped then
7267 inc(TmpData, LineSize - PixelSize); //set last pixel
7271 CachedRead(Temp, 1);
7272 PixelRepeat := (Temp and $80) > 0;
7273 PixelsToRead := (Temp and $7F) + 1;
7274 inc(TotalPixelsRead, PixelsToRead);
7277 CachedRead(buf[0], PixelSize);
7278 while (PixelsToRead > 0) do begin
7280 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
7281 while (PixelCount > 0) do begin
7282 if not PixelRepeat then
7283 CachedRead(buf[0], PixelSize);
7284 PixelToBuffer(@buf[0], TmpData);
7285 inc(LinePixelsRead);
7290 until (TotalPixelsRead >= TotalPixelsToRead);
7296 function IsGrayFormat: Boolean;
7298 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
7304 // reading header to test file and set cursor back to begin
7305 StartPosition := aStream.Position;
7306 aStream.Read(Header{%H-}, SizeOf(Header));
7308 // no colormapped files
7309 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
7310 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
7313 if Header.ImageID <> 0 then // skip image ID
7314 aStream.Position := aStream.Position + Header.ImageID;
7316 tgaFormat := tfEmpty;
7318 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
7319 0: tgaFormat := tfLuminance8;
7320 8: tgaFormat := tfAlpha8;
7323 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
7324 0: tgaFormat := tfLuminance16;
7325 8: tgaFormat := tfLuminance8Alpha8;
7326 end else case (Header.ImageDesc and $F) of
7327 0: tgaFormat := tfBGR5;
7328 1: tgaFormat := tfBGR5A1;
7329 4: tgaFormat := tfBGRA4;
7332 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7333 0: tgaFormat := tfBGR8;
7336 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7337 2: tgaFormat := tfBGR10A2;
7338 8: tgaFormat := tfBGRA8;
7342 if (tgaFormat = tfEmpty) then
7343 raise EglBitmap.Create('LoadTga - unsupported format');
7345 FormatDesc := TFormatDescriptor.Get(tgaFormat);
7346 PixelSize := FormatDesc.GetSize(1, 1);
7347 LineSize := FormatDesc.GetSize(Header.Width, 1);
7349 GetMem(ImageData, LineSize * Header.Height);
7352 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7353 Counter.X.low := Header.Height-1;;
7354 Counter.X.high := 0;
7355 Counter.X.dir := -1;
7358 Counter.X.high := Header.Height-1;
7363 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7365 Counter.Y.high := Header.Height-1;
7368 Counter.Y.low := Header.Height-1;;
7369 Counter.Y.high := 0;
7370 Counter.Y.dir := -1;
7374 case Header.ImageType of
7375 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7377 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7381 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method
7384 if Assigned(ImageData) then
7389 aStream.Position := StartPosition;
7392 else aStream.Position := StartPosition;
7395 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7396 procedure TglBitmap.SaveTGA(const aStream: TStream);
7399 LineSize, Size, x, y: Integer;
7400 Pixel: TglBitmapPixelData;
7401 LineBuf, SourceData, DestData: PByte;
7402 SourceMD, DestMD: Pointer;
7403 FormatDesc: TFormatDescriptor;
7404 Converter: TFormatDescriptor;
7406 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7407 raise EglBitmapUnsupportedFormat.Create(Format);
7410 FillChar(Header{%H-}, SizeOf(Header), 0);
7413 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7414 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7415 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7417 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7420 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7422 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7423 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7425 else if (Format in [tfBGR8, tfRGB8]) then
7433 Header.ImageDesc := 1 and $F;
7434 tfRGB10A2, tfBGR10A2:
7435 Header.ImageDesc := 2 and $F;
7437 Header.ImageDesc := 4 and $F;
7438 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7439 Header.ImageDesc := 8 and $F;
7442 Header.Width := Width;
7443 Header.Height := Height;
7444 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7445 aStream.Write(Header, SizeOf(Header));
7447 // convert RGB(A) to BGR(A)
7449 FormatDesc := TFormatDescriptor.Get(Format);
7450 Size := FormatDesc.GetSize(Dimension);
7451 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7452 if (FormatDesc.RGBInverted = tfEmpty) then
7453 raise EglBitmap.Create('inverted RGB format is empty');
7454 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7455 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7456 (Converter.PixelSize <> FormatDesc.PixelSize) then
7457 raise EglBitmap.Create('invalid inverted RGB format');
7460 if Assigned(Converter) then begin
7461 LineSize := FormatDesc.GetSize(Width, 1);
7462 GetMem(LineBuf, LineSize);
7463 SourceMD := FormatDesc.CreateMappingData;
7464 DestMD := Converter.CreateMappingData;
7467 for y := 0 to Height-1 do begin
7468 DestData := LineBuf;
7469 for x := 0 to Width-1 do begin
7470 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7471 Converter.Map(Pixel, DestData, DestMD);
7473 aStream.Write(LineBuf^, LineSize);
7477 FormatDesc.FreeMappingData(SourceMD);
7478 FormatDesc.FreeMappingData(DestMD);
7481 aStream.Write(Data^, Size);
7484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7485 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7486 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7488 DDS_MAGIC: Cardinal = $20534444;
7490 // DDS_header.dwFlags
7491 DDSD_CAPS = $00000001;
7492 DDSD_HEIGHT = $00000002;
7493 DDSD_WIDTH = $00000004;
7494 DDSD_PIXELFORMAT = $00001000;
7496 // DDS_header.sPixelFormat.dwFlags
7497 DDPF_ALPHAPIXELS = $00000001;
7498 DDPF_ALPHA = $00000002;
7499 DDPF_FOURCC = $00000004;
7500 DDPF_RGB = $00000040;
7501 DDPF_LUMINANCE = $00020000;
7503 // DDS_header.sCaps.dwCaps1
7504 DDSCAPS_TEXTURE = $00001000;
7506 // DDS_header.sCaps.dwCaps2
7507 DDSCAPS2_CUBEMAP = $00000200;
7509 D3DFMT_DXT1 = $31545844;
7510 D3DFMT_DXT3 = $33545844;
7511 D3DFMT_DXT5 = $35545844;
7514 TDDSPixelFormat = packed record
7518 dwRGBBitCount: Cardinal;
7519 dwRBitMask: Cardinal;
7520 dwGBitMask: Cardinal;
7521 dwBBitMask: Cardinal;
7522 dwABitMask: Cardinal;
7525 TDDSCaps = packed record
7529 dwReserved: Cardinal;
7532 TDDSHeader = packed record
7537 dwPitchOrLinearSize: Cardinal;
7539 dwMipMapCount: Cardinal;
7540 dwReserved: array[0..10] of Cardinal;
7541 PixelFormat: TDDSPixelFormat;
7543 dwReserved2: Cardinal;
7546 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7547 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7550 Converter: TbmpBitfieldFormat;
7552 function GetDDSFormat: TglBitmapFormat;
7554 fd: TFormatDescriptor;
7556 Range: TglBitmapColorRec;
7560 with Header.PixelFormat do begin
7562 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7563 case Header.PixelFormat.dwFourCC of
7564 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7565 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7566 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7568 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7570 //find matching format
7571 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7572 fd := TFormatDescriptor.Get(result);
7573 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7574 (8 * fd.PixelSize = dwRGBBitCount) then
7578 //find format with same Range
7579 Range.r := dwRBitMask;
7580 Range.g := dwGBitMask;
7581 Range.b := dwBBitMask;
7582 Range.a := dwABitMask;
7583 for i := 0 to 3 do begin
7584 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7585 Range.arr[i] := Range.arr[i] shr 1;
7587 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7588 fd := TFormatDescriptor.Get(result);
7591 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7599 //no format with same range found -> use default
7600 if (result = tfEmpty) then begin
7601 if (dwABitMask > 0) then
7607 Converter := TbmpBitfieldFormat.Create;
7608 Converter.RedMask := dwRBitMask;
7609 Converter.GreenMask := dwGBitMask;
7610 Converter.BlueMask := dwBBitMask;
7611 Converter.AlphaMask := dwABitMask;
7612 Converter.PixelSize := dwRGBBitCount / 8;
7619 x, y, LineSize, RowSize, Magic: Cardinal;
7620 NewImage, TmpData, RowData, SrcData: System.PByte;
7621 SourceMD, DestMD: Pointer;
7622 Pixel: TglBitmapPixelData;
7623 ddsFormat: TglBitmapFormat;
7624 FormatDesc: TFormatDescriptor;
7629 StreamPos := aStream.Position;
7632 aStream.Read(Magic{%H-}, sizeof(Magic));
7633 if (Magic <> DDS_MAGIC) then begin
7634 aStream.Position := StreamPos;
7639 aStream.Read(Header{%H-}, sizeof(Header));
7640 if (Header.dwSize <> SizeOf(Header)) or
7641 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7642 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7644 aStream.Position := StreamPos;
7648 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7649 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
7651 ddsFormat := GetDDSFormat;
7653 if (ddsFormat = tfEmpty) then
7654 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7656 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7657 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7658 GetMem(NewImage, Header.dwHeight * LineSize);
7660 TmpData := NewImage;
7663 if Assigned(Converter) then begin
7664 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7665 GetMem(RowData, RowSize);
7666 SourceMD := Converter.CreateMappingData;
7667 DestMD := FormatDesc.CreateMappingData;
7669 for y := 0 to Header.dwHeight-1 do begin
7670 TmpData := NewImage;
7671 inc(TmpData, y * LineSize);
7673 aStream.Read(SrcData^, RowSize);
7674 for x := 0 to Header.dwWidth-1 do begin
7675 Converter.Unmap(SrcData, Pixel, SourceMD);
7676 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7677 FormatDesc.Map(Pixel, TmpData, DestMD);
7681 Converter.FreeMappingData(SourceMD);
7682 FormatDesc.FreeMappingData(DestMD);
7688 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7689 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7690 for Y := 0 to Header.dwHeight-1 do begin
7691 aStream.Read(TmpData^, RowSize);
7692 Inc(TmpData, LineSize);
7697 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7698 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7699 for Y := 0 to Header.dwHeight-1 do begin
7700 aStream.Read(TmpData^, RowSize);
7701 Inc(TmpData, LineSize);
7704 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7706 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method
7709 if Assigned(NewImage) then
7714 FreeAndNil(Converter);
7718 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7719 procedure TglBitmap.SaveDDS(const aStream: TStream);
7722 FormatDesc: TFormatDescriptor;
7724 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7725 raise EglBitmapUnsupportedFormat.Create(Format);
7727 FormatDesc := TFormatDescriptor.Get(Format);
7730 FillChar(Header{%H-}, SizeOf(Header), 0);
7731 Header.dwSize := SizeOf(Header);
7732 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7734 Header.dwWidth := Max(1, Width);
7735 Header.dwHeight := Max(1, Height);
7738 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7741 Header.PixelFormat.dwSize := sizeof(Header);
7742 if (FormatDesc.IsCompressed) then begin
7743 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7745 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7746 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7747 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7749 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7750 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7751 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7752 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7753 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7754 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7755 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7756 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7757 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7759 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7760 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7761 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7762 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7763 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7764 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7767 if (FormatDesc.HasAlpha) then
7768 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7770 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7771 aStream.Write(Header, SizeOf(Header));
7772 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7775 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7776 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7777 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7778 procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7779 const aWidth: Integer; const aHeight: Integer);
7784 if (aHeight > 1) then begin
7785 Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1);
7786 GetMem(pTemp, Size);
7788 Move(aData^, pTemp^, Size);
7797 inherited SetDataPointer(pTemp, aFormat, aWidth);
7800 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7801 function TglBitmap1D.FlipHorz: Boolean;
7804 pTempDest, pDest, pSource: PByte;
7806 result := inherited FlipHorz;
7807 if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin
7809 GetMem(pDest, fRowSize);
7812 Inc(pTempDest, fRowSize);
7813 for Col := 0 to Width-1 do begin
7814 dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data
7815 Move(pSource^, pTempDest^, fPixelSize);
7816 Inc(pSource, fPixelSize);
7818 SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method
7821 if Assigned(pDest) then
7828 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7829 procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean);
7831 FormatDesc: TFormatDescriptor;
7834 FormatDesc := TFormatDescriptor.Get(Format);
7835 if FormatDesc.IsCompressed then begin
7836 if not Assigned(glCompressedTexImage1D) then
7837 raise EglBitmap.Create('compressed formats not supported by video adapter');
7838 glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
7839 end else if aBuildWithGlu then
7840 gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7842 glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7845 if (FreeDataAfterGenTexture) then
7849 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7850 procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean);
7852 BuildWithGlu, TexRec: Boolean;
7855 if Assigned(Data) then begin
7856 // Check Texture Size
7857 if (aTestTextureSize) then begin
7858 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7860 if (Width > TexSize) then
7861 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7863 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7864 (Target = GL_TEXTURE_RECTANGLE);
7865 if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7866 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7870 SetupParameters(BuildWithGlu);
7871 UploadData(BuildWithGlu);
7872 glAreTexturesResident(1, @fID, @fIsResident);
7876 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7877 procedure TglBitmap1D.AfterConstruction;
7880 Target := GL_TEXTURE_1D;
7883 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7884 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7885 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7886 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7888 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7889 result := fLines[aIndex]
7894 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7895 procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7896 const aWidth: Integer; const aHeight: Integer);
7898 Idx, LineWidth: Integer;
7900 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7902 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7904 if Assigned(Data) then begin
7905 SetLength(fLines, GetHeight);
7906 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7908 for Idx := 0 to GetHeight-1 do begin
7909 fLines[Idx] := Data;
7910 Inc(fLines[Idx], Idx * LineWidth);
7913 else SetLength(fLines, 0);
7915 SetLength(fLines, 0);
7919 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7920 procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
7922 FormatDesc: TFormatDescriptor;
7924 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7926 FormatDesc := TFormatDescriptor.Get(Format);
7927 if FormatDesc.IsCompressed then begin
7928 if not Assigned(glCompressedTexImage2D) then
7929 raise EglBitmap.Create('compressed formats not supported by video adapter');
7930 glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7931 end else if aBuildWithGlu then begin
7932 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7933 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7935 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7936 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7940 if (FreeDataAfterGenTexture) then
7944 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7945 procedure TglBitmap2D.AfterConstruction;
7948 Target := GL_TEXTURE_2D;
7951 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7952 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7955 Size, w, h: Integer;
7956 FormatDesc: TFormatDescriptor;
7958 FormatDesc := TFormatDescriptor.Get(aFormat);
7959 if FormatDesc.IsCompressed then
7960 raise EglBitmapUnsupportedFormat.Create(aFormat);
7962 w := aRight - aLeft;
7963 h := aBottom - aTop;
7964 Size := FormatDesc.GetSize(w, h);
7967 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7968 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7969 SetDataPointer(Temp, aFormat, w, h); //be careful, Data could be freed by this method
7972 if Assigned(Temp) then
7978 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7979 procedure TglBitmap2D.GetDataFromTexture;
7982 TempWidth, TempHeight: Integer;
7983 TempIntFormat: Cardinal;
7984 IntFormat, f: TglBitmapFormat;
7985 FormatDesc: TFormatDescriptor;
7990 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7991 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7992 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7994 IntFormat := tfEmpty;
7995 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
7996 FormatDesc := TFormatDescriptor.Get(f);
7997 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
7998 IntFormat := FormatDesc.Format;
8003 // Getting data from OpenGL
8004 FormatDesc := TFormatDescriptor.Get(IntFormat);
8005 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
8007 if FormatDesc.IsCompressed then begin
8008 if not Assigned(glGetCompressedTexImage) then
8009 raise EglBitmap.Create('compressed formats not supported by video adapter');
8010 glGetCompressedTexImage(Target, 0, Temp)
8012 glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8013 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
8015 if Assigned(Temp) then
8021 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8022 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
8024 BuildWithGlu, PotTex, TexRec: Boolean;
8027 if Assigned(Data) then begin
8028 // Check Texture Size
8029 if (aTestTextureSize) then begin
8030 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8032 if ((Height > TexSize) or (Width > TexSize)) then
8033 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8035 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
8036 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
8037 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8038 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8042 SetupParameters(BuildWithGlu);
8043 UploadData(Target, BuildWithGlu);
8044 glAreTexturesResident(1, @fID, @fIsResident);
8048 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8049 function TglBitmap2D.FlipHorz: Boolean;
8052 TempDestData, DestData, SourceData: PByte;
8055 result := inherited FlipHorz;
8056 if Assigned(Data) then begin
8058 ImgSize := Height * fRowSize;
8059 GetMem(DestData, ImgSize);
8061 TempDestData := DestData;
8062 Dec(TempDestData, fRowSize + fPixelSize);
8063 for Row := 0 to Height -1 do begin
8064 Inc(TempDestData, fRowSize * 2);
8065 for Col := 0 to Width -1 do begin
8066 Move(SourceData^, TempDestData^, fPixelSize);
8067 Inc(SourceData, fPixelSize);
8068 Dec(TempDestData, fPixelSize);
8071 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8074 if Assigned(DestData) then
8081 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8082 function TglBitmap2D.FlipVert: Boolean;
8085 TempDestData, DestData, SourceData: PByte;
8087 result := inherited FlipVert;
8088 if Assigned(Data) then begin
8090 GetMem(DestData, Height * fRowSize);
8092 TempDestData := DestData;
8093 Inc(TempDestData, Width * (Height -1) * fPixelSize);
8094 for Row := 0 to Height -1 do begin
8095 Move(SourceData^, TempDestData^, fRowSize);
8096 Dec(TempDestData, fRowSize);
8097 Inc(SourceData, fRowSize);
8099 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8102 if Assigned(DestData) then
8109 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8110 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8111 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8113 TMatrixItem = record
8118 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
8119 TglBitmapToNormalMapRec = Record
8121 Heights: array of Single;
8122 MatrixU : array of TMatrixItem;
8123 MatrixV : array of TMatrixItem;
8127 ONE_OVER_255 = 1 / 255;
8129 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8130 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
8134 with FuncRec do begin
8136 Source.Data.r * LUMINANCE_WEIGHT_R +
8137 Source.Data.g * LUMINANCE_WEIGHT_G +
8138 Source.Data.b * LUMINANCE_WEIGHT_B;
8139 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
8143 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8144 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
8147 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
8150 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8151 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
8153 TVec = Array[0..2] of Single;
8160 function GetHeight(X, Y: Integer): Single;
8162 with FuncRec do begin
8163 X := Max(0, Min(Size.X -1, X));
8164 Y := Max(0, Min(Size.Y -1, Y));
8165 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
8170 with FuncRec do begin
8171 with PglBitmapToNormalMapRec(Args)^ do begin
8173 for Idx := Low(MatrixU) to High(MatrixU) do
8174 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
8177 for Idx := Low(MatrixU) to High(MatrixU) do
8178 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
8180 Vec[0] := -du * Scale;
8181 Vec[1] := -dv * Scale;
8186 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8187 if Len <> 0 then begin
8188 Vec[0] := Vec[0] * Len;
8189 Vec[1] := Vec[1] * Len;
8190 Vec[2] := Vec[2] * Len;
8194 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
8195 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
8196 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
8200 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8201 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
8203 Rec: TglBitmapToNormalMapRec;
8205 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
8207 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
8208 Matrix[Index].X := X;
8209 Matrix[Index].Y := Y;
8210 Matrix[Index].W := W;
8215 if TFormatDescriptor.Get(Format).IsCompressed then
8216 raise EglBitmapUnsupportedFormat.Create(Format);
8218 if aScale > 100 then
8220 else if aScale < -100 then
8223 Rec.Scale := aScale;
8225 SetLength(Rec.Heights, Width * Height);
8229 SetLength(Rec.MatrixU, 2);
8230 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
8231 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
8233 SetLength(Rec.MatrixV, 2);
8234 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
8235 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
8239 SetLength(Rec.MatrixU, 6);
8240 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
8241 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
8242 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
8243 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
8244 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
8245 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
8247 SetLength(Rec.MatrixV, 6);
8248 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
8249 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
8250 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
8251 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
8252 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
8253 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
8257 SetLength(Rec.MatrixU, 6);
8258 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
8259 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
8260 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
8261 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
8262 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
8263 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
8265 SetLength(Rec.MatrixV, 6);
8266 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
8267 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
8268 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
8269 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
8270 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
8271 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
8275 SetLength(Rec.MatrixU, 20);
8276 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
8277 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
8278 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
8279 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
8280 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
8281 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
8282 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
8283 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
8284 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
8285 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
8286 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
8287 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
8288 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
8289 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
8290 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
8291 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
8292 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
8293 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
8294 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
8295 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
8297 SetLength(Rec.MatrixV, 20);
8298 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
8299 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
8300 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
8301 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
8302 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
8303 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
8304 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
8305 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
8306 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
8307 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
8308 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
8309 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
8310 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
8311 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
8312 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
8313 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
8314 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
8315 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
8316 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
8317 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
8322 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
8323 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
8325 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
8326 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
8328 SetLength(Rec.Heights, 0);
8332 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8333 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8334 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8335 procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean);
8337 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8340 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8341 procedure TglBitmapCubeMap.AfterConstruction;
8345 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8346 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8349 Target := GL_TEXTURE_CUBE_MAP;
8350 fGenMode := GL_REFLECTION_MAP;
8353 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8354 procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean);
8356 BuildWithGlu: Boolean;
8359 if (aTestTextureSize) then begin
8360 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8362 if (Height > TexSize) or (Width > TexSize) then
8363 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8365 if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8366 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8371 SetupParameters(BuildWithGlu);
8372 UploadData(aCubeTarget, BuildWithGlu);
8375 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8376 procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean);
8378 inherited Bind (aEnableTextureUnit);
8379 if aEnableTexCoordsGen then begin
8380 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8381 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8382 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8383 glEnable(GL_TEXTURE_GEN_S);
8384 glEnable(GL_TEXTURE_GEN_T);
8385 glEnable(GL_TEXTURE_GEN_R);
8389 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8390 procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean);
8392 inherited Unbind(aDisableTextureUnit);
8393 if aDisableTexCoordsGen then begin
8394 glDisable(GL_TEXTURE_GEN_S);
8395 glDisable(GL_TEXTURE_GEN_T);
8396 glDisable(GL_TEXTURE_GEN_R);
8400 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8401 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8402 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8404 TVec = Array[0..2] of Single;
8405 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8407 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8408 TglBitmapNormalMapRec = record
8410 Func: TglBitmapNormalMapGetVectorFunc;
8413 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8414 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8416 aVec[0] := aHalfSize;
8417 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8418 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8421 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8422 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8424 aVec[0] := - aHalfSize;
8425 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8426 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8429 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8430 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8432 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8433 aVec[1] := aHalfSize;
8434 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8437 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8438 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8440 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8441 aVec[1] := - aHalfSize;
8442 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8445 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8446 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8448 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8449 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8450 aVec[2] := aHalfSize;
8453 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8454 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8456 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8457 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8458 aVec[2] := - aHalfSize;
8461 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8462 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8468 with FuncRec do begin
8469 with PglBitmapNormalMapRec(Args)^ do begin
8470 Func(Vec, Position, HalfSize);
8473 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8474 if Len <> 0 then begin
8475 Vec[0] := Vec[0] * Len;
8476 Vec[1] := Vec[1] * Len;
8477 Vec[2] := Vec[2] * Len;
8480 // Scale Vector and AddVectro
8481 Vec[0] := Vec[0] * 0.5 + 0.5;
8482 Vec[1] := Vec[1] * 0.5 + 0.5;
8483 Vec[2] := Vec[2] * 0.5 + 0.5;
8488 Dest.Data.arr[i] := Round(Vec[i] * 255);
8492 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8493 procedure TglBitmapNormalMap.AfterConstruction;
8496 fGenMode := GL_NORMAL_MAP;
8499 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8500 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean);
8502 Rec: TglBitmapNormalMapRec;
8503 SizeRec: TglBitmapPixelPosition;
8505 Rec.HalfSize := aSize div 2;
8506 FreeDataAfterGenTexture := false;
8508 SizeRec.Fields := [ffX, ffY];
8513 Rec.Func := glBitmapNormalMapPosX;
8514 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8515 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize);
8518 Rec.Func := glBitmapNormalMapNegX;
8519 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8520 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize);
8523 Rec.Func := glBitmapNormalMapPosY;
8524 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8525 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize);
8528 Rec.Func := glBitmapNormalMapNegY;
8529 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8530 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize);
8533 Rec.Func := glBitmapNormalMapPosZ;
8534 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8535 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize);
8538 Rec.Func := glBitmapNormalMapNegZ;
8539 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8540 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize);
8545 glBitmapSetDefaultFormat (tfEmpty);
8546 glBitmapSetDefaultMipmap (mmMipmap);
8547 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8548 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8549 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8551 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8552 glBitmapSetDefaultDeleteTextureOnFree (true);
8554 TFormatDescriptor.Init;
8556 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8557 OpenGLInitialized := false;
8558 InitOpenGLCS := TCriticalSection.Create;
8562 TFormatDescriptor.Finalize;
8564 {$IFDEF GLB_NATIVE_OGL}
8565 if Assigned(GL_LibHandle) then
8566 glbFreeLibrary(GL_LibHandle);
8568 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8569 if Assigned(GLU_LibHandle) then
8570 glbFreeLibrary(GLU_LibHandle);
8571 FreeAndNil(InitOpenGLCS);