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)
864 constructor Create(const aFormat: TglBitmapFormat); overload;
865 constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload;
868 ////////////////////////////////////////////////////////////////////////////////////////////////////
869 TglBitmapColorRec = packed record
871 0: (r, g, b, a: Cardinal);
872 1: (arr: array[0..3] of Cardinal);
875 TglBitmapPixelData = packed record
876 Data, Range: TglBitmapColorRec;
877 Format: TglBitmapFormat;
879 PglBitmapPixelData = ^TglBitmapPixelData;
881 ////////////////////////////////////////////////////////////////////////////////////////////////////
882 TglBitmapPixelPositionFields = set of (ffX, ffY);
883 TglBitmapPixelPosition = record
884 Fields : TglBitmapPixelPositionFields;
889 TglBitmapFormatDescriptor = class(TObject)
891 function GetIsCompressed: Boolean; virtual; abstract;
892 function GetHasAlpha: Boolean; virtual; abstract;
894 function GetglDataFormat: GLenum; virtual; abstract;
895 function GetglFormat: GLenum; virtual; abstract;
896 function GetglInternalFormat: GLenum; virtual; abstract;
898 property IsCompressed: Boolean read GetIsCompressed;
899 property HasAlpha: Boolean read GetHasAlpha;
901 property glFormat: GLenum read GetglFormat;
902 property glInternalFormat: GLenum read GetglInternalFormat;
903 property glDataFormat: GLenum read GetglDataFormat;
906 ////////////////////////////////////////////////////////////////////////////////////////////////////
908 TglBitmapFunctionRec = record
910 Size: TglBitmapPixelPosition;
911 Position: TglBitmapPixelPosition;
912 Source: TglBitmapPixelData;
913 Dest: TglBitmapPixelData;
916 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
918 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
921 function GetFormatDesc: TglBitmapFormatDescriptor;
925 fAnisotropic: Integer;
926 fDeleteTextureOnFree: Boolean;
927 fFreeDataAfterGenTexture: Boolean;
929 fIsResident: Boolean;
930 fBorderColor: array[0..3] of Single;
932 fDimension: TglBitmapPixelPosition;
933 fMipMap: TglBitmapMipMap;
934 fFormat: TglBitmapFormat;
950 fSwizzle: array[0..3] of GLenum;
955 fCustomNameW: WideString;
956 fCustomData: Pointer;
959 function GetWidth: Integer; virtual;
960 function GetHeight: Integer; virtual;
962 function GetFileWidth: Integer; virtual;
963 function GetFileHeight: Integer; virtual;
966 procedure SetCustomData(const aValue: Pointer);
967 procedure SetCustomName(const aValue: String);
968 procedure SetCustomNameW(const aValue: WideString);
969 procedure SetDeleteTextureOnFree(const aValue: Boolean);
970 procedure SetFormat(const aValue: TglBitmapFormat);
971 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
972 procedure SetID(const aValue: Cardinal);
973 procedure SetMipMap(const aValue: TglBitmapMipMap);
974 procedure SetTarget(const aValue: Cardinal);
975 procedure SetAnisotropic(const aValue: Integer);
978 procedure SetupParameters(out aBuildWithGlu: Boolean);
979 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
980 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; //be careful, aData could be freed by this method
981 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
983 function FlipHorz: Boolean; virtual;
984 function FlipVert: Boolean; virtual;
986 property Width: Integer read GetWidth;
987 property Height: Integer read GetHeight;
989 property FileWidth: Integer read GetFileWidth;
990 property FileHeight: Integer read GetFileHeight;
993 property ID: Cardinal read fID write SetID;
994 property Target: Cardinal read fTarget write SetTarget;
995 property Format: TglBitmapFormat read fFormat write SetFormat;
996 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
997 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
999 property FormatDesc: TglBitmapFormatDescriptor read GetFormatDesc;
1001 property Filename: String read fFilename;
1002 property CustomName: String read fCustomName write SetCustomName;
1003 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
1004 property CustomData: Pointer read fCustomData write SetCustomData;
1006 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
1007 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
1009 property Dimension: TglBitmapPixelPosition read fDimension;
1010 property Data: PByte read fData;
1011 property IsResident: Boolean read fIsResident;
1013 procedure AfterConstruction; override;
1014 procedure BeforeDestruction; override;
1016 procedure PrepareResType(var aResource: String; var aResType: PChar);
1019 procedure LoadFromFile(const aFilename: String);
1020 procedure LoadFromStream(const aStream: TStream); virtual;
1021 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
1022 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil);
1023 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil);
1024 procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
1027 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
1028 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
1031 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
1032 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
1033 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
1037 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
1038 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
1039 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
1040 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
1041 const aArgs: Pointer = nil): Boolean;
1045 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
1046 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
1047 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
1048 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
1049 const aArgs: Pointer = nil): Boolean;
1052 {$IFDEF GLB_LAZARUS}
1053 function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1054 function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
1055 function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1056 function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil;
1057 const aArgs: Pointer = nil): Boolean;
1060 function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil;
1061 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1062 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
1063 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1065 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
1066 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1067 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1068 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1070 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
1071 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
1072 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
1074 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
1075 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
1076 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
1078 function RemoveAlpha: Boolean; virtual;
1081 function Clone: TglBitmap;
1082 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
1083 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
1084 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
1088 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
1089 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
1090 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
1093 procedure SetFilter(const aMin, aMag: GLenum);
1095 const S: GLenum = GL_CLAMP_TO_EDGE;
1096 const T: GLenum = GL_CLAMP_TO_EDGE;
1097 const R: GLenum = GL_CLAMP_TO_EDGE);
1098 procedure SetSwizzle(const r, g, b, a: GLenum);
1100 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
1101 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
1104 constructor Create; overload;
1105 constructor Create(const aFileName: String); overload;
1106 constructor Create(const aStream: TStream); overload;
1107 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload;
1108 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
1109 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
1110 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
1112 {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1113 {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF}
1115 {$IFDEF GLB_SUPPORT_JPEG_READ} function LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1116 {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF}
1118 function LoadBMP(const aStream: TStream): Boolean; virtual;
1119 procedure SaveBMP(const aStream: TStream); virtual;
1121 function LoadTGA(const aStream: TStream): Boolean; virtual;
1122 procedure SaveTGA(const aStream: TStream); virtual;
1124 function LoadDDS(const aStream: TStream): Boolean; virtual;
1125 procedure SaveDDS(const aStream: TStream); virtual;
1128 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1129 TglBitmap1D = class(TglBitmap)
1131 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1132 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1133 procedure UploadData(const aBuildWithGlu: Boolean);
1136 procedure AfterConstruction; override;
1137 function FlipHorz: Boolean; override;
1138 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1142 TglBitmap2D = class(TglBitmap)
1144 fLines: array of PByte;
1145 function GetScanline(const aIndex: Integer): Pointer;
1146 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1147 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1148 procedure UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
1152 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
1154 procedure AfterConstruction; override;
1156 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
1157 procedure GetDataFromTexture;
1158 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1160 function FlipHorz: Boolean; override;
1161 function FlipVert: Boolean; override;
1163 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
1164 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1167 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1168 TglBitmapCubeMap = class(TglBitmap2D)
1171 procedure GenTexture(const aTestTextureSize: Boolean = true); reintroduce;
1173 procedure AfterConstruction; override;
1174 procedure GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean = true);
1175 procedure Bind(const aEnableTexCoordsGen: Boolean = true; const aEnableTextureUnit: Boolean = true); reintroduce; virtual;
1176 procedure Unbind(const aDisableTexCoordsGen: Boolean = true; const aDisableTextureUnit: Boolean = true); reintroduce; virtual;
1179 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1180 TglBitmapNormalMap = class(TglBitmapCubeMap)
1182 procedure AfterConstruction; override;
1183 procedure GenerateNormalMap(const aSize: Integer = 32; const aTestTextureSize: Boolean = true);
1187 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1189 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1190 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1191 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1192 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1193 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1194 procedure glBitmapSetDefaultWrap(
1195 const S: Cardinal = GL_CLAMP_TO_EDGE;
1196 const T: Cardinal = GL_CLAMP_TO_EDGE;
1197 const R: Cardinal = GL_CLAMP_TO_EDGE);
1199 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1200 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1201 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1202 function glBitmapGetDefaultFormat: TglBitmapFormat;
1203 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1204 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1206 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1207 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1208 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1211 glBitmapDefaultDeleteTextureOnFree: Boolean;
1212 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1213 glBitmapDefaultFormat: TglBitmapFormat;
1214 glBitmapDefaultMipmap: TglBitmapMipMap;
1215 glBitmapDefaultFilterMin: Cardinal;
1216 glBitmapDefaultFilterMag: Cardinal;
1217 glBitmapDefaultWrapS: Cardinal;
1218 glBitmapDefaultWrapT: Cardinal;
1219 glBitmapDefaultWrapR: Cardinal;
1220 glDefaultSwizzle: array[0..3] of GLenum;
1223 function CreateGrayPalette: HPALETTE;
1229 Math, syncobjs, typinfo
1230 {$IFDEF GLB_DELPHI}, Types{$ENDIF};
1234 QWord = System.UInt64;
1241 ////////////////////////////////////////////////////////////////////////////////////////////////////
1242 TShiftRec = packed record
1244 0: (r, g, b, a: Byte);
1245 1: (arr: array[0..3] of Byte);
1248 TFormatDescriptor = class(TglBitmapFormatDescriptor)
1250 function GetRedMask: QWord;
1251 function GetGreenMask: QWord;
1252 function GetBlueMask: QWord;
1253 function GetAlphaMask: QWord;
1255 fFormat: TglBitmapFormat;
1256 fWithAlpha: TglBitmapFormat;
1257 fWithoutAlpha: TglBitmapFormat;
1258 fRGBInverted: TglBitmapFormat;
1259 fUncompressed: TglBitmapFormat;
1261 fIsCompressed: Boolean;
1263 fRange: TglBitmapColorRec;
1267 fglInternalFormat: GLenum;
1268 fglDataFormat: GLenum;
1270 function GetIsCompressed: Boolean; override;
1271 function GetHasAlpha: Boolean; override;
1273 function GetglFormat: GLenum; override;
1274 function GetglInternalFormat: GLenum; override;
1275 function GetglDataFormat: GLenum; override;
1277 function GetComponents: Integer; virtual;
1279 property Format: TglBitmapFormat read fFormat;
1280 property WithAlpha: TglBitmapFormat read fWithAlpha;
1281 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1282 property RGBInverted: TglBitmapFormat read fRGBInverted;
1283 property Components: Integer read GetComponents;
1284 property PixelSize: Single read fPixelSize;
1286 property Range: TglBitmapColorRec read fRange;
1287 property Shift: TShiftRec read fShift;
1289 property RedMask: QWord read GetRedMask;
1290 property GreenMask: QWord read GetGreenMask;
1291 property BlueMask: QWord read GetBlueMask;
1292 property AlphaMask: QWord read GetAlphaMask;
1294 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1295 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1297 function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual;
1298 function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
1300 function CreateMappingData: Pointer; virtual;
1301 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1303 function IsEmpty: Boolean; virtual;
1304 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual;
1306 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1308 constructor Create; virtual;
1310 class procedure Init;
1311 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1312 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1313 class procedure Clear;
1314 class procedure Finalize;
1316 TFormatDescriptorClass = class of TFormatDescriptor;
1318 TfdEmpty = class(TFormatDescriptor);
1320 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1321 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1322 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1323 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1324 constructor Create; override;
1327 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1328 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1329 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1330 constructor Create; override;
1333 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1334 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1335 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1336 constructor Create; override;
1339 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1340 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1341 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1342 constructor Create; override;
1345 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1346 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1347 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1348 constructor Create; override;
1351 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1352 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1353 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1354 constructor Create; override;
1357 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1358 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1359 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1360 constructor Create; override;
1363 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1364 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1365 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1366 constructor Create; override;
1369 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1370 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1371 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1372 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1373 constructor Create; override;
1376 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1377 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1378 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1379 constructor Create; override;
1382 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1383 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1384 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1385 constructor Create; override;
1388 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1389 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1390 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1391 constructor Create; override;
1394 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1395 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1396 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1397 constructor Create; override;
1400 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1401 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1402 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1403 constructor Create; override;
1406 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1407 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1408 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1409 constructor Create; override;
1412 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1413 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1414 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1415 constructor Create; override;
1418 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1419 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1420 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1421 constructor Create; override;
1424 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1425 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1426 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1427 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1428 constructor Create; override;
1431 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1432 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1433 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1434 constructor Create; override;
1437 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1438 TfdAlpha4 = class(TfdAlpha_UB1)
1439 constructor Create; override;
1442 TfdAlpha8 = class(TfdAlpha_UB1)
1443 constructor Create; override;
1446 TfdAlpha12 = class(TfdAlpha_US1)
1447 constructor Create; override;
1450 TfdAlpha16 = class(TfdAlpha_US1)
1451 constructor Create; override;
1454 TfdLuminance4 = class(TfdLuminance_UB1)
1455 constructor Create; override;
1458 TfdLuminance8 = class(TfdLuminance_UB1)
1459 constructor Create; override;
1462 TfdLuminance12 = class(TfdLuminance_US1)
1463 constructor Create; override;
1466 TfdLuminance16 = class(TfdLuminance_US1)
1467 constructor Create; override;
1470 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1471 constructor Create; override;
1474 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1475 constructor Create; override;
1478 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1479 constructor Create; override;
1482 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1483 constructor Create; override;
1486 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1487 constructor Create; override;
1490 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1491 constructor Create; override;
1494 TfdR3G3B2 = class(TfdUniversal_UB1)
1495 constructor Create; override;
1498 TfdRGB4 = class(TfdUniversal_US1)
1499 constructor Create; override;
1502 TfdR5G6B5 = class(TfdUniversal_US1)
1503 constructor Create; override;
1506 TfdRGB5 = class(TfdUniversal_US1)
1507 constructor Create; override;
1510 TfdRGB8 = class(TfdRGB_UB3)
1511 constructor Create; override;
1514 TfdRGB10 = class(TfdUniversal_UI1)
1515 constructor Create; override;
1518 TfdRGB12 = class(TfdRGB_US3)
1519 constructor Create; override;
1522 TfdRGB16 = class(TfdRGB_US3)
1523 constructor Create; override;
1526 TfdRGBA2 = class(TfdRGBA_UB4)
1527 constructor Create; override;
1530 TfdRGBA4 = class(TfdUniversal_US1)
1531 constructor Create; override;
1534 TfdRGB5A1 = class(TfdUniversal_US1)
1535 constructor Create; override;
1538 TfdRGBA8 = class(TfdRGBA_UB4)
1539 constructor Create; override;
1542 TfdRGB10A2 = class(TfdUniversal_UI1)
1543 constructor Create; override;
1546 TfdRGBA12 = class(TfdRGBA_US4)
1547 constructor Create; override;
1550 TfdRGBA16 = class(TfdRGBA_US4)
1551 constructor Create; override;
1554 TfdBGR4 = class(TfdUniversal_US1)
1555 constructor Create; override;
1558 TfdB5G6R5 = class(TfdUniversal_US1)
1559 constructor Create; override;
1562 TfdBGR5 = class(TfdUniversal_US1)
1563 constructor Create; override;
1566 TfdBGR8 = class(TfdBGR_UB3)
1567 constructor Create; override;
1570 TfdBGR10 = class(TfdUniversal_UI1)
1571 constructor Create; override;
1574 TfdBGR12 = class(TfdBGR_US3)
1575 constructor Create; override;
1578 TfdBGR16 = class(TfdBGR_US3)
1579 constructor Create; override;
1582 TfdBGRA2 = class(TfdBGRA_UB4)
1583 constructor Create; override;
1586 TfdBGRA4 = class(TfdUniversal_US1)
1587 constructor Create; override;
1590 TfdBGR5A1 = class(TfdUniversal_US1)
1591 constructor Create; override;
1594 TfdBGRA8 = class(TfdBGRA_UB4)
1595 constructor Create; override;
1598 TfdBGR10A2 = class(TfdUniversal_UI1)
1599 constructor Create; override;
1602 TfdBGRA12 = class(TfdBGRA_US4)
1603 constructor Create; override;
1606 TfdBGRA16 = class(TfdBGRA_US4)
1607 constructor Create; override;
1610 TfdDepth16 = class(TfdDepth_US1)
1611 constructor Create; override;
1614 TfdDepth24 = class(TfdDepth_UI1)
1615 constructor Create; override;
1618 TfdDepth32 = class(TfdDepth_UI1)
1619 constructor Create; override;
1622 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1623 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1624 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1625 constructor Create; override;
1628 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1629 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1630 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1631 constructor Create; override;
1634 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1635 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1636 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1637 constructor Create; override;
1640 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1641 TbmpBitfieldFormat = class(TFormatDescriptor)
1643 procedure SetRedMask (const aValue: QWord);
1644 procedure SetGreenMask(const aValue: QWord);
1645 procedure SetBlueMask (const aValue: QWord);
1646 procedure SetAlphaMask(const aValue: QWord);
1648 procedure Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte);
1650 property RedMask: QWord read GetRedMask write SetRedMask;
1651 property GreenMask: QWord read GetGreenMask write SetGreenMask;
1652 property BlueMask: QWord read GetBlueMask write SetBlueMask;
1653 property AlphaMask: QWord read GetAlphaMask write SetAlphaMask;
1655 property PixelSize: Single read fPixelSize write fPixelSize;
1657 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1658 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1661 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1662 TbmpColorTableEnty = packed record
1665 TbmpColorTable = array of TbmpColorTableEnty;
1666 TbmpColorTableFormat = class(TFormatDescriptor)
1668 fColorTable: TbmpColorTable;
1670 property PixelSize: Single read fPixelSize write fPixelSize;
1671 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1672 property Range: TglBitmapColorRec read fRange write fRange;
1673 property Shift: TShiftRec read fShift write fShift;
1674 property Format: TglBitmapFormat read fFormat write fFormat;
1676 procedure CreateColorTable;
1678 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1679 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1680 destructor Destroy; override;
1684 LUMINANCE_WEIGHT_R = 0.30;
1685 LUMINANCE_WEIGHT_G = 0.59;
1686 LUMINANCE_WEIGHT_B = 0.11;
1688 ALPHA_WEIGHT_R = 0.30;
1689 ALPHA_WEIGHT_G = 0.59;
1690 ALPHA_WEIGHT_B = 0.11;
1692 DEPTH_WEIGHT_R = 0.333333333;
1693 DEPTH_WEIGHT_G = 0.333333333;
1694 DEPTH_WEIGHT_B = 0.333333333;
1696 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1698 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1711 TfdLuminance4Alpha4,
1712 TfdLuminance6Alpha2,
1713 TfdLuminance8Alpha8,
1714 TfdLuminance12Alpha4,
1715 TfdLuminance12Alpha12,
1716 TfdLuminance16Alpha16,
1761 FormatDescriptorCS: TCriticalSection;
1762 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1764 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1765 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1767 inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1770 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1771 constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat);
1773 inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1776 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1777 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1779 result.Fields := [];
1782 result.Fields := result.Fields + [ffX];
1784 result.Fields := result.Fields + [ffY];
1786 result.X := Max(0, X);
1787 result.Y := Max(0, Y);
1790 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1791 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1799 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1800 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1805 for i := 0 to high(r1.arr) do
1806 if (r1.arr[i] <> r2.arr[i]) then
1811 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1812 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1820 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1821 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1830 tfR3G3B2, tfLuminance8,
1833 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1834 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1840 tfRGB10, tfRGB10A2, tfRGBA8,
1841 tfBGR10, tfBGR10A2, tfBGRA8]) then
1842 result := result + [ftBMP];
1846 tfLuminance8, tfAlpha8,
1849 tfLuminance16, tfLuminance8Alpha8,
1850 tfRGB5, tfRGB5A1, tfRGBA4,
1851 tfBGR5, tfBGR5A1, tfBGRA4,
1857 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1858 result := result + [ftTGA];
1862 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1863 tfR3G3B2, tfRGBA2, tfBGRA2,
1866 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1867 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1868 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1874 tfLuminance16Alpha16,
1879 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1880 result := result + [ftDDS];
1882 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1884 tfAlpha8, tfLuminance8, tfLuminance8Alpha8,
1886 tfBGR8, tfBGRA8] then
1887 result := result + [ftPNG];
1890 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1891 if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then
1892 result := result + [ftJPEG];
1896 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1897 function IsPowerOfTwo(aNumber: Integer): Boolean;
1899 while (aNumber and 1) = 0 do
1900 aNumber := aNumber shr 1;
1901 result := aNumber = 1;
1904 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1905 function GetTopMostBit(aBitSet: QWord): Integer;
1908 while aBitSet > 0 do begin
1910 aBitSet := aBitSet shr 1;
1914 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1915 function CountSetBits(aBitSet: QWord): Integer;
1918 while aBitSet > 0 do begin
1919 if (aBitSet and 1) = 1 then
1921 aBitSet := aBitSet shr 1;
1925 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1926 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1929 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1930 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1931 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1934 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1935 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1938 DEPTH_WEIGHT_R * aPixel.Data.r +
1939 DEPTH_WEIGHT_G * aPixel.Data.g +
1940 DEPTH_WEIGHT_B * aPixel.Data.b);
1943 {$IFDEF GLB_NATIVE_OGL}
1944 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1945 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1946 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1948 GL_LibHandle: Pointer = nil;
1950 function glbGetProcAddress(aProcName: PAnsiChar; aLibHandle: Pointer = nil; const aRaiseOnErr: Boolean = true): Pointer;
1952 if not Assigned(aLibHandle) then
1953 aLibHandle := GL_LibHandle;
1955 {$IF DEFINED(GLB_WIN)}
1956 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1957 if Assigned(result) then
1960 if Assigned(wglGetProcAddress) then
1961 result := wglGetProcAddress(aProcName);
1962 {$ELSEIF DEFINED(GLB_LINUX)}
1963 if Assigned(glXGetProcAddress) then begin
1964 result := glXGetProcAddress(aProcName);
1965 if Assigned(result) then
1969 if Assigned(glXGetProcAddressARB) then begin
1970 result := glXGetProcAddressARB(aProcName);
1971 if Assigned(result) then
1975 result := dlsym(aLibHandle, aProcName);
1977 if not Assigned(result) and aRaiseOnErr then
1978 raise EglBitmap.Create('unable to load procedure form library: ' + aProcName);
1981 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1983 GLU_LibHandle: Pointer = nil;
1984 OpenGLInitialized: Boolean;
1985 InitOpenGLCS: TCriticalSection;
1987 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1988 procedure glbInitOpenGL;
1990 ////////////////////////////////////////////////////////////////////////////////
1991 function glbLoadLibrary(const aName: PChar): Pointer;
1993 {$IF DEFINED(GLB_WIN)}
1994 result := {%H-}Pointer(LoadLibrary(aName));
1995 {$ELSEIF DEFINED(GLB_LINUX)}
1996 result := dlopen(Name, RTLD_LAZY);
2002 ////////////////////////////////////////////////////////////////////////////////
2003 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
2006 if not Assigned(aLibHandle) then
2009 {$IF DEFINED(GLB_WIN)}
2010 Result := FreeLibrary({%H-}HINST(aLibHandle));
2011 {$ELSEIF DEFINED(GLB_LINUX)}
2012 Result := dlclose(aLibHandle) = 0;
2017 if Assigned(GL_LibHandle) then
2018 glbFreeLibrary(GL_LibHandle);
2020 if Assigned(GLU_LibHandle) then
2021 glbFreeLibrary(GLU_LibHandle);
2023 GL_LibHandle := glbLoadLibrary(libopengl);
2024 if not Assigned(GL_LibHandle) then
2025 raise EglBitmap.Create('unable to load library: ' + libopengl);
2027 GLU_LibHandle := glbLoadLibrary(libglu);
2028 if not Assigned(GLU_LibHandle) then
2029 raise EglBitmap.Create('unable to load library: ' + libglu);
2031 {$IF DEFINED(GLB_WIN)}
2032 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
2033 {$ELSEIF DEFINED(GLB_LINUX)}
2034 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
2035 glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
2038 glEnable := glbGetProcAddress('glEnable');
2039 glDisable := glbGetProcAddress('glDisable');
2040 glGetString := glbGetProcAddress('glGetString');
2041 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
2042 glTexParameteri := glbGetProcAddress('glTexParameteri');
2043 glTexParameteriv := glbGetProcAddress('glTexParameteriv');
2044 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
2045 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
2046 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
2047 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
2048 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
2049 glTexGeni := glbGetProcAddress('glTexGeni');
2050 glGenTextures := glbGetProcAddress('glGenTextures');
2051 glBindTexture := glbGetProcAddress('glBindTexture');
2052 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
2053 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
2054 glReadPixels := glbGetProcAddress('glReadPixels');
2055 glPixelStorei := glbGetProcAddress('glPixelStorei');
2056 glTexImage1D := glbGetProcAddress('glTexImage1D');
2057 glTexImage2D := glbGetProcAddress('glTexImage2D');
2058 glGetTexImage := glbGetProcAddress('glGetTexImage');
2060 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
2061 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
2065 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2066 procedure glbReadOpenGLExtensions;
2069 MajorVersion, MinorVersion: Integer;
2071 ///////////////////////////////////////////////////////////////////////////////////////////
2072 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
2079 Separator := Pos(AnsiString('.'), aBuffer);
2080 if (Separator > 1) and (Separator < Length(aBuffer)) and
2081 (aBuffer[Separator - 1] in ['0'..'9']) and
2082 (aBuffer[Separator + 1] in ['0'..'9']) then begin
2085 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
2088 Delete(aBuffer, 1, Separator);
2089 Separator := Pos(AnsiString('.'), aBuffer) + 1;
2091 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
2094 Delete(aBuffer, Separator, 255);
2095 Separator := Pos(AnsiString('.'), aBuffer);
2097 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
2098 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2102 ///////////////////////////////////////////////////////////////////////////////////////////
2103 function CheckExtension(const Extension: AnsiString): Boolean;
2107 ExtPos := Pos(Extension, Buffer);
2108 result := ExtPos > 0;
2110 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2113 ///////////////////////////////////////////////////////////////////////////////////////////
2114 function CheckVersion(const aMajor, aMinor: Integer): Boolean;
2116 result := (MajorVersion > aMajor) or ((MajorVersion = aMajor) and (MinorVersion >= aMinor));
2120 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2123 if not OpenGLInitialized then begin
2125 OpenGLInitialized := true;
2133 Buffer := glGetString(GL_VERSION);
2134 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2136 GL_VERSION_1_2 := CheckVersion(1, 2);
2137 GL_VERSION_1_3 := CheckVersion(1, 3);
2138 GL_VERSION_1_4 := CheckVersion(1, 4);
2139 GL_VERSION_2_0 := CheckVersion(2, 0);
2140 GL_VERSION_3_3 := CheckVersion(3, 3);
2143 Buffer := glGetString(GL_EXTENSIONS);
2144 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2145 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2146 GL_ARB_texture_swizzle := CheckExtension('GL_ARB_texture_swizzle');
2147 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
2148 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2149 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2150 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2151 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2152 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2153 GL_EXT_texture_swizzle := CheckExtension('GL_EXT_texture_swizzle');
2154 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
2155 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2156 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2157 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2159 if GL_VERSION_1_3 then begin
2160 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2161 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2162 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2164 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB', nil, false);
2165 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB', nil, false);
2166 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB', nil, false);
2171 {$IFDEF GLB_SDL_IMAGE}
2172 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2173 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2174 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2175 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2177 result := TStream(context^.unknown.data1).Seek(offset, whence);
2180 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2182 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2185 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2187 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2190 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2195 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2197 result := SDL_AllocRW;
2199 if result = nil then
2200 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2202 result^.seek := glBitmapRWseek;
2203 result^.read := glBitmapRWread;
2204 result^.write := glBitmapRWwrite;
2205 result^.close := glBitmapRWclose;
2206 result^.unknown.data1 := Stream;
2210 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2211 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2213 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2217 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2219 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2222 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2223 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2225 glBitmapDefaultMipmap := aValue;
2228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2229 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2231 glBitmapDefaultFormat := aFormat;
2234 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2235 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2237 glBitmapDefaultFilterMin := aMin;
2238 glBitmapDefaultFilterMag := aMag;
2241 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2242 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2244 glBitmapDefaultWrapS := S;
2245 glBitmapDefaultWrapT := T;
2246 glBitmapDefaultWrapR := R;
2249 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2250 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
2252 glDefaultSwizzle[0] := r;
2253 glDefaultSwizzle[1] := g;
2254 glDefaultSwizzle[2] := b;
2255 glDefaultSwizzle[3] := a;
2258 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2259 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2261 result := glBitmapDefaultDeleteTextureOnFree;
2264 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2265 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2267 result := glBitmapDefaultFreeDataAfterGenTextures;
2270 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2271 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2273 result := glBitmapDefaultMipmap;
2276 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2277 function glBitmapGetDefaultFormat: TglBitmapFormat;
2279 result := glBitmapDefaultFormat;
2282 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2283 procedure glBitmapGetDefaultFilter(var aMin, aMag: GLenum);
2285 aMin := glBitmapDefaultFilterMin;
2286 aMag := glBitmapDefaultFilterMag;
2289 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2290 procedure glBitmapGetDefaultTextureWrap(var S, T, R: GLenum);
2292 S := glBitmapDefaultWrapS;
2293 T := glBitmapDefaultWrapT;
2294 R := glBitmapDefaultWrapR;
2297 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2298 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
2300 r := glDefaultSwizzle[0];
2301 g := glDefaultSwizzle[1];
2302 b := glDefaultSwizzle[2];
2303 a := glDefaultSwizzle[3];
2306 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2307 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2308 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2309 function TFormatDescriptor.GetRedMask: QWord;
2311 result := fRange.r shl fShift.r;
2314 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2315 function TFormatDescriptor.GetGreenMask: QWord;
2317 result := fRange.g shl fShift.g;
2320 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2321 function TFormatDescriptor.GetBlueMask: QWord;
2323 result := fRange.b shl fShift.b;
2326 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2327 function TFormatDescriptor.GetAlphaMask: QWord;
2329 result := fRange.a shl fShift.a;
2332 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2333 function TFormatDescriptor.GetIsCompressed: Boolean;
2335 result := fIsCompressed;
2338 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2339 function TFormatDescriptor.GetHasAlpha: Boolean;
2341 result := (fRange.a > 0);
2344 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2345 function TFormatDescriptor.GetglFormat: GLenum;
2347 result := fglFormat;
2350 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2351 function TFormatDescriptor.GetglInternalFormat: GLenum;
2353 result := fglInternalFormat;
2356 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2357 function TFormatDescriptor.GetglDataFormat: GLenum;
2359 result := fglDataFormat;
2362 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2363 function TFormatDescriptor.GetComponents: Integer;
2369 if (fRange.arr[i] > 0) then
2373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2374 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2378 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2379 w := Max(1, aSize.X);
2380 h := Max(1, aSize.Y);
2381 result := GetSize(w, h);
2386 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2387 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2390 if (aWidth <= 0) or (aHeight <= 0) then
2392 result := Ceil(aWidth * aHeight * fPixelSize);
2395 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2396 function TFormatDescriptor.CreateMappingData: Pointer;
2401 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2402 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2407 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2408 function TFormatDescriptor.IsEmpty: Boolean;
2410 result := (fFormat = tfEmpty);
2413 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2414 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2417 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2418 raise EglBitmap.Create('FormatCheckFormat - All Masks are 0');
2419 if (aRedMask <> RedMask) then
2421 if (aGreenMask <> GreenMask) then
2423 if (aBlueMask <> BlueMask) then
2425 if (aAlphaMask <> AlphaMask) then
2430 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2431 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2433 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2434 aPixel.Data := fRange;
2435 aPixel.Range := fRange;
2436 aPixel.Format := fFormat;
2439 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2440 constructor TFormatDescriptor.Create;
2445 fWithAlpha := tfEmpty;
2446 fWithoutAlpha := tfEmpty;
2447 fRGBInverted := tfEmpty;
2448 fUncompressed := tfEmpty;
2450 fIsCompressed := false;
2453 fglInternalFormat := 0;
2456 FillChar(fRange, 0, SizeOf(fRange));
2457 FillChar(fShift, 0, SizeOf(fShift));
2460 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2461 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2462 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2463 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2465 aData^ := aPixel.Data.a;
2469 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2474 aPixel.Data.a := aData^;
2478 constructor TfdAlpha_UB1.Create;
2483 fglFormat := GL_ALPHA;
2484 fglDataFormat := GL_UNSIGNED_BYTE;
2487 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2488 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2489 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2490 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2492 aData^ := LuminanceWeight(aPixel);
2496 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2498 aPixel.Data.r := aData^;
2499 aPixel.Data.g := aData^;
2500 aPixel.Data.b := aData^;
2505 constructor TfdLuminance_UB1.Create;
2512 fglFormat := GL_LUMINANCE;
2513 fglDataFormat := GL_UNSIGNED_BYTE;
2516 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2517 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2518 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2519 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2525 if (fRange.arr[i] > 0) then
2526 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2530 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2535 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2539 constructor TfdUniversal_UB1.Create;
2545 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2546 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2547 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2548 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2550 inherited Map(aPixel, aData, aMapData);
2551 aData^ := aPixel.Data.a;
2555 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2557 inherited Unmap(aData, aPixel, aMapData);
2558 aPixel.Data.a := aData^;
2562 constructor TfdLuminanceAlpha_UB2.Create;
2568 fglFormat := GL_LUMINANCE_ALPHA;
2569 fglDataFormat := GL_UNSIGNED_BYTE;
2572 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2573 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2574 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2575 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2577 aData^ := aPixel.Data.r;
2579 aData^ := aPixel.Data.g;
2581 aData^ := aPixel.Data.b;
2585 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2587 aPixel.Data.r := aData^;
2589 aPixel.Data.g := aData^;
2591 aPixel.Data.b := aData^;
2596 constructor TfdRGB_UB3.Create;
2606 fglFormat := GL_RGB;
2607 fglDataFormat := GL_UNSIGNED_BYTE;
2610 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2611 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2612 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2613 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2615 aData^ := aPixel.Data.b;
2617 aData^ := aPixel.Data.g;
2619 aData^ := aPixel.Data.r;
2623 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2625 aPixel.Data.b := aData^;
2627 aPixel.Data.g := aData^;
2629 aPixel.Data.r := aData^;
2634 constructor TfdBGR_UB3.Create;
2643 fglFormat := GL_BGR;
2644 fglDataFormat := GL_UNSIGNED_BYTE;
2647 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2648 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2649 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2650 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2652 inherited Map(aPixel, aData, aMapData);
2653 aData^ := aPixel.Data.a;
2657 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2659 inherited Unmap(aData, aPixel, aMapData);
2660 aPixel.Data.a := aData^;
2664 constructor TfdRGBA_UB4.Create;
2670 fglFormat := GL_RGBA;
2671 fglDataFormat := GL_UNSIGNED_BYTE;
2674 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2675 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2676 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2677 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2679 inherited Map(aPixel, aData, aMapData);
2680 aData^ := aPixel.Data.a;
2684 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2686 inherited Unmap(aData, aPixel, aMapData);
2687 aPixel.Data.a := aData^;
2691 constructor TfdBGRA_UB4.Create;
2697 fglFormat := GL_BGRA;
2698 fglDataFormat := GL_UNSIGNED_BYTE;
2701 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2702 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2703 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2704 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2706 PWord(aData)^ := aPixel.Data.a;
2710 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2715 aPixel.Data.a := PWord(aData)^;
2719 constructor TfdAlpha_US1.Create;
2724 fglFormat := GL_ALPHA;
2725 fglDataFormat := GL_UNSIGNED_SHORT;
2728 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2729 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2730 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2731 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2733 PWord(aData)^ := LuminanceWeight(aPixel);
2737 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2739 aPixel.Data.r := PWord(aData)^;
2740 aPixel.Data.g := PWord(aData)^;
2741 aPixel.Data.b := PWord(aData)^;
2746 constructor TfdLuminance_US1.Create;
2753 fglFormat := GL_LUMINANCE;
2754 fglDataFormat := GL_UNSIGNED_SHORT;
2757 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2758 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2759 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2760 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2766 if (fRange.arr[i] > 0) then
2767 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2771 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2776 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2780 constructor TfdUniversal_US1.Create;
2786 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2787 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2788 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2789 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2791 PWord(aData)^ := DepthWeight(aPixel);
2795 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2797 aPixel.Data.r := PWord(aData)^;
2798 aPixel.Data.g := PWord(aData)^;
2799 aPixel.Data.b := PWord(aData)^;
2804 constructor TfdDepth_US1.Create;
2811 fglFormat := GL_DEPTH_COMPONENT;
2812 fglDataFormat := GL_UNSIGNED_SHORT;
2815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2816 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2817 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2818 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2820 inherited Map(aPixel, aData, aMapData);
2821 PWord(aData)^ := aPixel.Data.a;
2825 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2827 inherited Unmap(aData, aPixel, aMapData);
2828 aPixel.Data.a := PWord(aData)^;
2832 constructor TfdLuminanceAlpha_US2.Create;
2838 fglFormat := GL_LUMINANCE_ALPHA;
2839 fglDataFormat := GL_UNSIGNED_SHORT;
2842 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2843 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2844 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2845 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2847 PWord(aData)^ := aPixel.Data.r;
2849 PWord(aData)^ := aPixel.Data.g;
2851 PWord(aData)^ := aPixel.Data.b;
2855 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2857 aPixel.Data.r := PWord(aData)^;
2859 aPixel.Data.g := PWord(aData)^;
2861 aPixel.Data.b := PWord(aData)^;
2866 constructor TfdRGB_US3.Create;
2876 fglFormat := GL_RGB;
2877 fglDataFormat := GL_UNSIGNED_SHORT;
2880 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2881 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2882 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2883 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2885 PWord(aData)^ := aPixel.Data.b;
2887 PWord(aData)^ := aPixel.Data.g;
2889 PWord(aData)^ := aPixel.Data.r;
2893 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2895 aPixel.Data.b := PWord(aData)^;
2897 aPixel.Data.g := PWord(aData)^;
2899 aPixel.Data.r := PWord(aData)^;
2904 constructor TfdBGR_US3.Create;
2914 fglFormat := GL_BGR;
2915 fglDataFormat := GL_UNSIGNED_SHORT;
2918 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2919 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2920 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2921 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2923 inherited Map(aPixel, aData, aMapData);
2924 PWord(aData)^ := aPixel.Data.a;
2928 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2930 inherited Unmap(aData, aPixel, aMapData);
2931 aPixel.Data.a := PWord(aData)^;
2935 constructor TfdRGBA_US4.Create;
2941 fglFormat := GL_RGBA;
2942 fglDataFormat := GL_UNSIGNED_SHORT;
2945 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2946 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2947 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2948 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2950 inherited Map(aPixel, aData, aMapData);
2951 PWord(aData)^ := aPixel.Data.a;
2955 procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2957 inherited Unmap(aData, aPixel, aMapData);
2958 aPixel.Data.a := PWord(aData)^;
2962 constructor TfdBGRA_US4.Create;
2968 fglFormat := GL_BGRA;
2969 fglDataFormat := GL_UNSIGNED_SHORT;
2972 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2973 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2974 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2975 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2979 PCardinal(aData)^ := 0;
2981 if (fRange.arr[i] > 0) then
2982 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2986 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2991 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2995 constructor TfdUniversal_UI1.Create;
3001 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3002 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3003 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3004 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3006 PCardinal(aData)^ := DepthWeight(aPixel);
3010 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3012 aPixel.Data.r := PCardinal(aData)^;
3013 aPixel.Data.g := PCardinal(aData)^;
3014 aPixel.Data.b := PCardinal(aData)^;
3019 constructor TfdDepth_UI1.Create;
3023 fRange.r := $FFFFFFFF;
3024 fRange.g := $FFFFFFFF;
3025 fRange.b := $FFFFFFFF;
3026 fglFormat := GL_DEPTH_COMPONENT;
3027 fglDataFormat := GL_UNSIGNED_INT;
3030 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3031 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3032 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3033 constructor TfdAlpha4.Create;
3036 fFormat := tfAlpha4;
3037 fWithAlpha := tfAlpha4;
3038 fglInternalFormat := GL_ALPHA4;
3041 constructor TfdAlpha8.Create;
3044 fFormat := tfAlpha8;
3045 fWithAlpha := tfAlpha8;
3046 fglInternalFormat := GL_ALPHA8;
3049 constructor TfdAlpha12.Create;
3052 fFormat := tfAlpha12;
3053 fWithAlpha := tfAlpha12;
3054 fglInternalFormat := GL_ALPHA12;
3057 constructor TfdAlpha16.Create;
3060 fFormat := tfAlpha16;
3061 fWithAlpha := tfAlpha16;
3062 fglInternalFormat := GL_ALPHA16;
3065 constructor TfdLuminance4.Create;
3068 fFormat := tfLuminance4;
3069 fWithAlpha := tfLuminance4Alpha4;
3070 fWithoutAlpha := tfLuminance4;
3071 fglInternalFormat := GL_LUMINANCE4;
3074 constructor TfdLuminance8.Create;
3077 fFormat := tfLuminance8;
3078 fWithAlpha := tfLuminance8Alpha8;
3079 fWithoutAlpha := tfLuminance8;
3080 fglInternalFormat := GL_LUMINANCE8;
3083 constructor TfdLuminance12.Create;
3086 fFormat := tfLuminance12;
3087 fWithAlpha := tfLuminance12Alpha12;
3088 fWithoutAlpha := tfLuminance12;
3089 fglInternalFormat := GL_LUMINANCE12;
3092 constructor TfdLuminance16.Create;
3095 fFormat := tfLuminance16;
3096 fWithAlpha := tfLuminance16Alpha16;
3097 fWithoutAlpha := tfLuminance16;
3098 fglInternalFormat := GL_LUMINANCE16;
3101 constructor TfdLuminance4Alpha4.Create;
3104 fFormat := tfLuminance4Alpha4;
3105 fWithAlpha := tfLuminance4Alpha4;
3106 fWithoutAlpha := tfLuminance4;
3107 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3110 constructor TfdLuminance6Alpha2.Create;
3113 fFormat := tfLuminance6Alpha2;
3114 fWithAlpha := tfLuminance6Alpha2;
3115 fWithoutAlpha := tfLuminance8;
3116 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3119 constructor TfdLuminance8Alpha8.Create;
3122 fFormat := tfLuminance8Alpha8;
3123 fWithAlpha := tfLuminance8Alpha8;
3124 fWithoutAlpha := tfLuminance8;
3125 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3128 constructor TfdLuminance12Alpha4.Create;
3131 fFormat := tfLuminance12Alpha4;
3132 fWithAlpha := tfLuminance12Alpha4;
3133 fWithoutAlpha := tfLuminance12;
3134 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3137 constructor TfdLuminance12Alpha12.Create;
3140 fFormat := tfLuminance12Alpha12;
3141 fWithAlpha := tfLuminance12Alpha12;
3142 fWithoutAlpha := tfLuminance12;
3143 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3146 constructor TfdLuminance16Alpha16.Create;
3149 fFormat := tfLuminance16Alpha16;
3150 fWithAlpha := tfLuminance16Alpha16;
3151 fWithoutAlpha := tfLuminance16;
3152 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3155 constructor TfdR3G3B2.Create;
3158 fFormat := tfR3G3B2;
3159 fWithAlpha := tfRGBA2;
3160 fWithoutAlpha := tfR3G3B2;
3167 fglFormat := GL_RGB;
3168 fglInternalFormat := GL_R3_G3_B2;
3169 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3172 constructor TfdRGB4.Create;
3176 fWithAlpha := tfRGBA4;
3177 fWithoutAlpha := tfRGB4;
3178 fRGBInverted := tfBGR4;
3185 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3186 fglInternalFormat := GL_RGB4;
3187 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3190 constructor TfdR5G6B5.Create;
3193 fFormat := tfR5G6B5;
3194 fWithAlpha := tfRGBA4;
3195 fWithoutAlpha := tfR5G6B5;
3196 fRGBInverted := tfB5G6R5;
3203 fglFormat := GL_RGB;
3204 fglInternalFormat := GL_RGB565;
3205 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3208 constructor TfdRGB5.Create;
3212 fWithAlpha := tfRGB5A1;
3213 fWithoutAlpha := tfRGB5;
3214 fRGBInverted := tfBGR5;
3221 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3222 fglInternalFormat := GL_RGB5;
3223 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3226 constructor TfdRGB8.Create;
3230 fWithAlpha := tfRGBA8;
3231 fWithoutAlpha := tfRGB8;
3232 fRGBInverted := tfBGR8;
3233 fglInternalFormat := GL_RGB8;
3236 constructor TfdRGB10.Create;
3240 fWithAlpha := tfRGB10A2;
3241 fWithoutAlpha := tfRGB10;
3242 fRGBInverted := tfBGR10;
3249 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3250 fglInternalFormat := GL_RGB10;
3251 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3254 constructor TfdRGB12.Create;
3258 fWithAlpha := tfRGBA12;
3259 fWithoutAlpha := tfRGB12;
3260 fRGBInverted := tfBGR12;
3261 fglInternalFormat := GL_RGB12;
3264 constructor TfdRGB16.Create;
3268 fWithAlpha := tfRGBA16;
3269 fWithoutAlpha := tfRGB16;
3270 fRGBInverted := tfBGR16;
3271 fglInternalFormat := GL_RGB16;
3274 constructor TfdRGBA2.Create;
3278 fWithAlpha := tfRGBA2;
3279 fWithoutAlpha := tfR3G3B2;
3280 fRGBInverted := tfBGRA2;
3281 fglInternalFormat := GL_RGBA2;
3284 constructor TfdRGBA4.Create;
3288 fWithAlpha := tfRGBA4;
3289 fWithoutAlpha := tfRGB4;
3290 fRGBInverted := tfBGRA4;
3299 fglFormat := GL_RGBA;
3300 fglInternalFormat := GL_RGBA4;
3301 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3304 constructor TfdRGB5A1.Create;
3307 fFormat := tfRGB5A1;
3308 fWithAlpha := tfRGB5A1;
3309 fWithoutAlpha := tfRGB5;
3310 fRGBInverted := tfBGR5A1;
3319 fglFormat := GL_RGBA;
3320 fglInternalFormat := GL_RGB5_A1;
3321 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3324 constructor TfdRGBA8.Create;
3328 fWithAlpha := tfRGBA8;
3329 fWithoutAlpha := tfRGB8;
3330 fRGBInverted := tfBGRA8;
3331 fglInternalFormat := GL_RGBA8;
3334 constructor TfdRGB10A2.Create;
3337 fFormat := tfRGB10A2;
3338 fWithAlpha := tfRGB10A2;
3339 fWithoutAlpha := tfRGB10;
3340 fRGBInverted := tfBGR10A2;
3349 fglFormat := GL_RGBA;
3350 fglInternalFormat := GL_RGB10_A2;
3351 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3354 constructor TfdRGBA12.Create;
3357 fFormat := tfRGBA12;
3358 fWithAlpha := tfRGBA12;
3359 fWithoutAlpha := tfRGB12;
3360 fRGBInverted := tfBGRA12;
3361 fglInternalFormat := GL_RGBA12;
3364 constructor TfdRGBA16.Create;
3367 fFormat := tfRGBA16;
3368 fWithAlpha := tfRGBA16;
3369 fWithoutAlpha := tfRGB16;
3370 fRGBInverted := tfBGRA16;
3371 fglInternalFormat := GL_RGBA16;
3374 constructor TfdBGR4.Create;
3379 fWithAlpha := tfBGRA4;
3380 fWithoutAlpha := tfBGR4;
3381 fRGBInverted := tfRGB4;
3390 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3391 fglInternalFormat := GL_RGB4;
3392 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3395 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3396 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3397 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3398 constructor TfdB5G6R5.Create;
3401 fFormat := tfB5G6R5;
3402 fWithAlpha := tfBGRA4;
3403 fWithoutAlpha := tfB5G6R5;
3404 fRGBInverted := tfR5G6B5;
3411 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3412 fglInternalFormat := GL_RGB8;
3413 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3416 constructor TfdBGR5.Create;
3421 fWithAlpha := tfBGR5A1;
3422 fWithoutAlpha := tfBGR5;
3423 fRGBInverted := tfRGB5;
3432 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3433 fglInternalFormat := GL_RGB5;
3434 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3437 constructor TfdBGR8.Create;
3441 fWithAlpha := tfBGRA8;
3442 fWithoutAlpha := tfBGR8;
3443 fRGBInverted := tfRGB8;
3444 fglInternalFormat := GL_RGB8;
3447 constructor TfdBGR10.Create;
3451 fWithAlpha := tfBGR10A2;
3452 fWithoutAlpha := tfBGR10;
3453 fRGBInverted := tfRGB10;
3462 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3463 fglInternalFormat := GL_RGB10;
3464 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3467 constructor TfdBGR12.Create;
3471 fWithAlpha := tfBGRA12;
3472 fWithoutAlpha := tfBGR12;
3473 fRGBInverted := tfRGB12;
3474 fglInternalFormat := GL_RGB12;
3477 constructor TfdBGR16.Create;
3481 fWithAlpha := tfBGRA16;
3482 fWithoutAlpha := tfBGR16;
3483 fRGBInverted := tfRGB16;
3484 fglInternalFormat := GL_RGB16;
3487 constructor TfdBGRA2.Create;
3491 fWithAlpha := tfBGRA4;
3492 fWithoutAlpha := tfBGR4;
3493 fRGBInverted := tfRGBA2;
3494 fglInternalFormat := GL_RGBA2;
3497 constructor TfdBGRA4.Create;
3501 fWithAlpha := tfBGRA4;
3502 fWithoutAlpha := tfBGR4;
3503 fRGBInverted := tfRGBA4;
3512 fglFormat := GL_BGRA;
3513 fglInternalFormat := GL_RGBA4;
3514 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3517 constructor TfdBGR5A1.Create;
3520 fFormat := tfBGR5A1;
3521 fWithAlpha := tfBGR5A1;
3522 fWithoutAlpha := tfBGR5;
3523 fRGBInverted := tfRGB5A1;
3532 fglFormat := GL_BGRA;
3533 fglInternalFormat := GL_RGB5_A1;
3534 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3537 constructor TfdBGRA8.Create;
3541 fWithAlpha := tfBGRA8;
3542 fWithoutAlpha := tfBGR8;
3543 fRGBInverted := tfRGBA8;
3544 fglInternalFormat := GL_RGBA8;
3547 constructor TfdBGR10A2.Create;
3550 fFormat := tfBGR10A2;
3551 fWithAlpha := tfBGR10A2;
3552 fWithoutAlpha := tfBGR10;
3553 fRGBInverted := tfRGB10A2;
3562 fglFormat := GL_BGRA;
3563 fglInternalFormat := GL_RGB10_A2;
3564 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3567 constructor TfdBGRA12.Create;
3570 fFormat := tfBGRA12;
3571 fWithAlpha := tfBGRA12;
3572 fWithoutAlpha := tfBGR12;
3573 fRGBInverted := tfRGBA12;
3574 fglInternalFormat := GL_RGBA12;
3577 constructor TfdBGRA16.Create;
3580 fFormat := tfBGRA16;
3581 fWithAlpha := tfBGRA16;
3582 fWithoutAlpha := tfBGR16;
3583 fRGBInverted := tfRGBA16;
3584 fglInternalFormat := GL_RGBA16;
3587 constructor TfdDepth16.Create;
3590 fFormat := tfDepth16;
3591 fWithAlpha := tfEmpty;
3592 fWithoutAlpha := tfDepth16;
3593 fglInternalFormat := GL_DEPTH_COMPONENT16;
3596 constructor TfdDepth24.Create;
3599 fFormat := tfDepth24;
3600 fWithAlpha := tfEmpty;
3601 fWithoutAlpha := tfDepth24;
3602 fglInternalFormat := GL_DEPTH_COMPONENT24;
3605 constructor TfdDepth32.Create;
3608 fFormat := tfDepth32;
3609 fWithAlpha := tfEmpty;
3610 fWithoutAlpha := tfDepth32;
3611 fglInternalFormat := GL_DEPTH_COMPONENT32;
3614 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3615 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3616 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3617 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3619 raise EglBitmap.Create('mapping for compressed formats is not supported');
3622 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3624 raise EglBitmap.Create('mapping for compressed formats is not supported');
3627 constructor TfdS3tcDtx1RGBA.Create;
3630 fFormat := tfS3tcDtx1RGBA;
3631 fWithAlpha := tfS3tcDtx1RGBA;
3632 fUncompressed := tfRGB5A1;
3634 fIsCompressed := true;
3635 fglFormat := GL_COMPRESSED_RGBA;
3636 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3637 fglDataFormat := GL_UNSIGNED_BYTE;
3640 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3641 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3642 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3643 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3645 raise EglBitmap.Create('mapping for compressed formats is not supported');
3648 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3650 raise EglBitmap.Create('mapping for compressed formats is not supported');
3653 constructor TfdS3tcDtx3RGBA.Create;
3656 fFormat := tfS3tcDtx3RGBA;
3657 fWithAlpha := tfS3tcDtx3RGBA;
3658 fUncompressed := tfRGBA8;
3660 fIsCompressed := true;
3661 fglFormat := GL_COMPRESSED_RGBA;
3662 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3663 fglDataFormat := GL_UNSIGNED_BYTE;
3666 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3667 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3668 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3669 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3671 raise EglBitmap.Create('mapping for compressed formats is not supported');
3674 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3676 raise EglBitmap.Create('mapping for compressed formats is not supported');
3679 constructor TfdS3tcDtx5RGBA.Create;
3682 fFormat := tfS3tcDtx3RGBA;
3683 fWithAlpha := tfS3tcDtx3RGBA;
3684 fUncompressed := tfRGBA8;
3686 fIsCompressed := true;
3687 fglFormat := GL_COMPRESSED_RGBA;
3688 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3689 fglDataFormat := GL_UNSIGNED_BYTE;
3692 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3693 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3694 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3695 class procedure TFormatDescriptor.Init;
3697 if not Assigned(FormatDescriptorCS) then
3698 FormatDescriptorCS := TCriticalSection.Create;
3701 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3702 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3704 FormatDescriptorCS.Enter;
3706 result := FormatDescriptors[aFormat];
3707 if not Assigned(result) then begin
3708 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3709 FormatDescriptors[aFormat] := result;
3712 FormatDescriptorCS.Leave;
3716 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3717 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3719 result := Get(Get(aFormat).WithAlpha);
3722 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3723 class procedure TFormatDescriptor.Clear;
3727 FormatDescriptorCS.Enter;
3729 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3730 FreeAndNil(FormatDescriptors[f]);
3732 FormatDescriptorCS.Leave;
3736 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3737 class procedure TFormatDescriptor.Finalize;
3740 FreeAndNil(FormatDescriptorCS);
3743 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3744 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3745 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3746 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3748 Update(aValue, fRange.r, fShift.r);
3751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3752 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3754 Update(aValue, fRange.g, fShift.g);
3757 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3758 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3760 Update(aValue, fRange.b, fShift.b);
3763 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3764 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3766 Update(aValue, fRange.a, fShift.a);
3769 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3770 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3777 while (aMask > 0) and ((aMask and 1) = 0) do begin
3779 aMask := aMask shr 1;
3782 while (aMask > 0) do begin
3783 aRange := aRange shl 1;
3784 aMask := aMask shr 1;
3788 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3791 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3792 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3798 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3799 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3800 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3801 ((aPixel.Data.a and fRange.a) shl fShift.a);
3802 s := Round(fPixelSize);
3805 2: PWord(aData)^ := data;
3806 4: PCardinal(aData)^ := data;
3807 8: PQWord(aData)^ := data;
3809 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3814 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3815 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3820 s := Round(fPixelSize);
3823 2: data := PWord(aData)^;
3824 4: data := PCardinal(aData)^;
3825 8: data := PQWord(aData)^;
3827 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3830 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3834 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3835 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3836 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3837 procedure TbmpColorTableFormat.CreateColorTable;
3841 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3842 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3844 if (Format = tfLuminance4) then
3845 SetLength(fColorTable, 16)
3847 SetLength(fColorTable, 256);
3851 for i := 0 to High(fColorTable) do begin
3852 fColorTable[i].r := 16 * i;
3853 fColorTable[i].g := 16 * i;
3854 fColorTable[i].b := 16 * i;
3855 fColorTable[i].a := 0;
3860 for i := 0 to High(fColorTable) do begin
3861 fColorTable[i].r := i;
3862 fColorTable[i].g := i;
3863 fColorTable[i].b := i;
3864 fColorTable[i].a := 0;
3869 for i := 0 to High(fColorTable) do begin
3870 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3871 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3872 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3873 fColorTable[i].a := 0;
3879 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3880 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3884 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3885 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3889 if (aMapData = nil) then
3891 d := LuminanceWeight(aPixel) and Range.r;
3892 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3893 inc(PByte(aMapData), 4);
3894 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3901 aData^ := LuminanceWeight(aPixel) and Range.r;
3907 ((aPixel.Data.r and Range.r) shl Shift.r) or
3908 ((aPixel.Data.g and Range.g) shl Shift.g) or
3909 ((aPixel.Data.b and Range.b) shl Shift.b));
3915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3916 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3923 s := Trunc(fPixelSize);
3924 f := fPixelSize - s;
3925 bits := Round(8 * f);
3927 0: idx := (aData^ shr (8 - bits - {%H-}PtrInt(aMapData))) and ((1 shl bits) - 1);
3929 2: idx := PWord(aData)^;
3930 4: idx := PCardinal(aData)^;
3931 8: idx := PQWord(aData)^;
3933 raise EglBitmap.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3935 if (idx >= Length(fColorTable)) then
3936 raise EglBitmap.CreateFmt('invalid color index: %d', [idx]);
3937 with fColorTable[idx] do begin
3943 inc(PByte(aMapData), bits);
3944 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3946 dec(PByte(aMapData), 8);
3951 destructor TbmpColorTableFormat.Destroy;
3953 SetLength(fColorTable, 0);
3957 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3958 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3959 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3960 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
3964 for i := 0 to 3 do begin
3965 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
3966 if (aSourceFD.Range.arr[i] > 0) then
3967 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
3969 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
3974 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3975 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
3977 with aFuncRec do begin
3978 if (Source.Range.r > 0) then
3979 Dest.Data.r := Source.Data.r;
3980 if (Source.Range.g > 0) then
3981 Dest.Data.g := Source.Data.g;
3982 if (Source.Range.b > 0) then
3983 Dest.Data.b := Source.Data.b;
3984 if (Source.Range.a > 0) then
3985 Dest.Data.a := Source.Data.a;
3989 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3990 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3994 with aFuncRec do begin
3996 if (Source.Range.arr[i] > 0) then
3997 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4002 TShiftData = packed record
4004 0: (r, g, b, a: SmallInt);
4005 1: (arr: array[0..3] of SmallInt);
4007 PShiftData = ^TShiftData;
4009 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4010 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4016 if (Source.Range.arr[i] > 0) then
4017 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4020 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4021 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4023 with aFuncRec do begin
4024 Dest.Data := Source.Data;
4025 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4026 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4027 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4028 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4030 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4031 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4036 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4037 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4041 with aFuncRec do begin
4043 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4047 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4048 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4052 with FuncRec do begin
4053 if (FuncRec.Args = nil) then begin //source has no alpha
4055 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4056 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4057 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4058 Dest.Data.a := Round(Dest.Range.a * Temp);
4060 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4064 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4065 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4067 PglBitmapPixelData = ^TglBitmapPixelData;
4069 with FuncRec do begin
4070 Dest.Data.r := Source.Data.r;
4071 Dest.Data.g := Source.Data.g;
4072 Dest.Data.b := Source.Data.b;
4074 with PglBitmapPixelData(Args)^ do
4075 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4076 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4077 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4080 Dest.Data.a := Dest.Range.a;
4084 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4085 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4087 with FuncRec do begin
4088 Dest.Data.r := Source.Data.r;
4089 Dest.Data.g := Source.Data.g;
4090 Dest.Data.b := Source.Data.b;
4091 Dest.Data.a := PCardinal(Args)^;
4095 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4096 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4099 TRGBPix = array [0..2] of byte;
4103 while aWidth > 0 do begin
4104 Temp := PRGBPix(aData)^[0];
4105 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4106 PRGBPix(aData)^[2] := Temp;
4116 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4117 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4118 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4119 function TglBitmap.GetFormatDesc: TglBitmapFormatDescriptor;
4121 result := TFormatDescriptor.Get(Format);
4124 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4125 function TglBitmap.GetWidth: Integer;
4127 if (ffX in fDimension.Fields) then
4128 result := fDimension.X
4133 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4134 function TglBitmap.GetHeight: Integer;
4136 if (ffY in fDimension.Fields) then
4137 result := fDimension.Y
4142 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4143 function TglBitmap.GetFileWidth: Integer;
4145 result := Max(1, Width);
4148 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4149 function TglBitmap.GetFileHeight: Integer;
4151 result := Max(1, Height);
4154 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4155 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4157 if fCustomData = aValue then
4159 fCustomData := aValue;
4162 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4163 procedure TglBitmap.SetCustomName(const aValue: String);
4165 if fCustomName = aValue then
4167 fCustomName := aValue;
4170 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4171 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4173 if fCustomNameW = aValue then
4175 fCustomNameW := aValue;
4178 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4179 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4181 if fDeleteTextureOnFree = aValue then
4183 fDeleteTextureOnFree := aValue;
4186 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4187 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4189 if fFormat = aValue then
4191 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4192 raise EglBitmapUnsupportedFormat.Create(Format);
4193 SetDataPointer(fData, aValue, Width, Height); //be careful, Data could be freed by this method
4196 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4197 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4199 if fFreeDataAfterGenTexture = aValue then
4201 fFreeDataAfterGenTexture := aValue;
4204 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4205 procedure TglBitmap.SetID(const aValue: Cardinal);
4207 if fID = aValue then
4212 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4213 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4215 if fMipMap = aValue then
4220 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4221 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4223 if fTarget = aValue then
4228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4229 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4231 MaxAnisotropic: Integer;
4233 fAnisotropic := aValue;
4234 if (ID > 0) then begin
4235 if GL_EXT_texture_filter_anisotropic then begin
4236 if fAnisotropic > 0 then begin
4238 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4239 if aValue > MaxAnisotropic then
4240 fAnisotropic := MaxAnisotropic;
4241 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4249 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4250 procedure TglBitmap.CreateID;
4253 glDeleteTextures(1, @fID);
4254 glGenTextures(1, @fID);
4258 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4259 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4261 // Set Up Parameters
4262 SetWrap(fWrapS, fWrapT, fWrapR);
4263 SetFilter(fFilterMin, fFilterMag);
4264 SetAnisotropic(fAnisotropic);
4265 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4267 if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
4268 SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4270 // Mip Maps Generation Mode
4271 aBuildWithGlu := false;
4272 if (MipMap = mmMipmap) then begin
4273 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4274 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4276 aBuildWithGlu := true;
4277 end else if (MipMap = mmMipmapGlu) then
4278 aBuildWithGlu := true;
4281 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4282 procedure TglBitmap.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
4283 const aWidth: Integer; const aHeight: Integer);
4287 if (Data <> aData) then begin
4288 if (Assigned(Data)) then
4293 if not Assigned(fData) then begin
4297 FillChar(fDimension, SizeOf(fDimension), 0);
4298 if aWidth <> -1 then begin
4299 fDimension.Fields := fDimension.Fields + [ffX];
4300 fDimension.X := aWidth;
4303 if aHeight <> -1 then begin
4304 fDimension.Fields := fDimension.Fields + [ffY];
4305 fDimension.Y := aHeight;
4308 s := TFormatDescriptor.Get(aFormat).PixelSize;
4310 fPixelSize := Ceil(s);
4311 fRowSize := Ceil(s * aWidth);
4315 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4316 function TglBitmap.FlipHorz: Boolean;
4321 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4322 function TglBitmap.FlipVert: Boolean;
4327 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4328 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4329 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4330 procedure TglBitmap.AfterConstruction;
4332 inherited AfterConstruction;
4336 fIsResident := false;
4338 fFormat := glBitmapGetDefaultFormat;
4339 fMipMap := glBitmapDefaultMipmap;
4340 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4341 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4343 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4344 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4345 glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4348 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4349 procedure TglBitmap.BeforeDestruction;
4354 SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
4355 if (fID > 0) and fDeleteTextureOnFree then
4356 glDeleteTextures(1, @fID);
4357 inherited BeforeDestruction;
4360 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4361 procedure TglBitmap.PrepareResType(var aResource: String; var aResType: PChar);
4365 if not Assigned(aResType) then begin
4366 TempPos := Pos('.', aResource);
4367 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4368 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4372 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4373 procedure TglBitmap.LoadFromFile(const aFilename: String);
4377 if not FileExists(aFilename) then
4378 raise EglBitmap.Create('file does not exist: ' + aFilename);
4379 fFilename := aFilename;
4380 fs := TFileStream.Create(fFilename, fmOpenRead);
4389 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4390 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4392 {$IFDEF GLB_SUPPORT_PNG_READ}
4393 if not LoadPNG(aStream) then
4395 {$IFDEF GLB_SUPPORT_JPEG_READ}
4396 if not LoadJPEG(aStream) then
4398 if not LoadDDS(aStream) then
4399 if not LoadTGA(aStream) then
4400 if not LoadBMP(aStream) then
4401 raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4404 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4405 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4406 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4411 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4412 GetMem(tmpData, size);
4414 FillChar(tmpData^, size, #$FF);
4415 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
4417 if Assigned(tmpData) then
4421 AddFunc(Self, aFunc, false, Format, aArgs);
4424 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4425 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
4427 rs: TResourceStream;
4429 PrepareResType(aResource, aResType);
4430 rs := TResourceStream.Create(aInstance, aResource, aResType);
4438 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4439 procedure TglBitmap.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4441 rs: TResourceStream;
4443 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
4451 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4452 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4456 fs := TFileStream.Create(aFileName, fmCreate);
4459 SaveToStream(fs, aFileType);
4465 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4466 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4469 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4470 ftPNG: SavePNG(aStream);
4472 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4473 ftJPEG: SaveJPEG(aStream);
4475 ftDDS: SaveDDS(aStream);
4476 ftTGA: SaveTGA(aStream);
4477 ftBMP: SaveBMP(aStream);
4481 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4482 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4484 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4487 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4488 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4489 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4491 DestData, TmpData, SourceData: pByte;
4492 TempHeight, TempWidth: Integer;
4493 SourceFD, DestFD: TFormatDescriptor;
4494 SourceMD, DestMD: Pointer;
4496 FuncRec: TglBitmapFunctionRec;
4498 Assert(Assigned(Data));
4499 Assert(Assigned(aSource));
4500 Assert(Assigned(aSource.Data));
4503 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4504 SourceFD := TFormatDescriptor.Get(aSource.Format);
4505 DestFD := TFormatDescriptor.Get(aFormat);
4507 if (SourceFD.IsCompressed) then
4508 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
4509 if (DestFD.IsCompressed) then
4510 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
4512 // inkompatible Formats so CreateTemp
4513 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4514 aCreateTemp := true;
4517 TempHeight := Max(1, aSource.Height);
4518 TempWidth := Max(1, aSource.Width);
4520 FuncRec.Sender := Self;
4521 FuncRec.Args := aArgs;
4524 if aCreateTemp then begin
4525 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
4526 DestData := TmpData;
4531 SourceFD.PreparePixel(FuncRec.Source);
4532 DestFD.PreparePixel (FuncRec.Dest);
4534 SourceMD := SourceFD.CreateMappingData;
4535 DestMD := DestFD.CreateMappingData;
4537 FuncRec.Size := aSource.Dimension;
4538 FuncRec.Position.Fields := FuncRec.Size.Fields;
4541 SourceData := aSource.Data;
4542 FuncRec.Position.Y := 0;
4543 while FuncRec.Position.Y < TempHeight do begin
4544 FuncRec.Position.X := 0;
4545 while FuncRec.Position.X < TempWidth do begin
4546 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4548 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4549 inc(FuncRec.Position.X);
4551 inc(FuncRec.Position.Y);
4554 // Updating Image or InternalFormat
4556 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) //be careful, Data could be freed by this method
4557 else if (aFormat <> fFormat) then
4562 SourceFD.FreeMappingData(SourceMD);
4563 DestFD.FreeMappingData(DestMD);
4566 if aCreateTemp and Assigned(TmpData) then
4574 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4575 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4577 Row, RowSize: Integer;
4578 SourceData, TmpData: PByte;
4580 FormatDesc: TFormatDescriptor;
4582 function GetRowPointer(Row: Integer): pByte;
4584 result := aSurface.pixels;
4585 Inc(result, Row * RowSize);
4591 FormatDesc := TFormatDescriptor.Get(Format);
4592 if FormatDesc.IsCompressed then
4593 raise EglBitmapUnsupportedFormat.Create(Format);
4595 if Assigned(Data) then begin
4596 case Trunc(FormatDesc.PixelSize) of
4602 raise EglBitmapUnsupportedFormat.Create(Format);
4605 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4606 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4608 RowSize := FormatDesc.GetSize(FileWidth, 1);
4610 for Row := 0 to FileHeight-1 do begin
4611 TmpData := GetRowPointer(Row);
4612 if Assigned(TmpData) then begin
4613 Move(SourceData^, TmpData^, RowSize);
4614 inc(SourceData, RowSize);
4621 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4622 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4624 pSource, pData, pTempData: PByte;
4625 Row, RowSize, TempWidth, TempHeight: Integer;
4626 IntFormat: TglBitmapFormat;
4627 FormatDesc: TFormatDescriptor;
4629 function GetRowPointer(Row: Integer): pByte;
4631 result := aSurface^.pixels;
4632 Inc(result, Row * RowSize);
4637 if (Assigned(aSurface)) then begin
4638 with aSurface^.format^ do begin
4639 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4640 FormatDesc := TFormatDescriptor.Get(IntFormat);
4641 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4644 if (IntFormat = tfEmpty) then
4645 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4648 TempWidth := aSurface^.w;
4649 TempHeight := aSurface^.h;
4650 RowSize := FormatDesc.GetSize(TempWidth, 1);
4651 GetMem(pData, TempHeight * RowSize);
4654 for Row := 0 to TempHeight -1 do begin
4655 pSource := GetRowPointer(Row);
4656 if (Assigned(pSource)) then begin
4657 Move(pSource^, pTempData^, RowSize);
4658 Inc(pTempData, RowSize);
4661 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4664 if Assigned(pData) then
4671 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4672 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4674 Row, Col, AlphaInterleave: Integer;
4675 pSource, pDest: PByte;
4677 function GetRowPointer(Row: Integer): pByte;
4679 result := aSurface.pixels;
4680 Inc(result, Row * Width);
4685 if Assigned(Data) then begin
4686 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4687 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4689 AlphaInterleave := 0;
4692 AlphaInterleave := 1;
4694 AlphaInterleave := 3;
4698 for Row := 0 to Height -1 do begin
4699 pDest := GetRowPointer(Row);
4700 if Assigned(pDest) then begin
4701 for Col := 0 to Width -1 do begin
4702 Inc(pSource, AlphaInterleave);
4714 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4715 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4719 bmp := TglBitmap2D.Create;
4721 bmp.AssignFromSurface(aSurface);
4722 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4730 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4731 function CreateGrayPalette: HPALETTE;
4736 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
4738 Pal.palVersion := $300;
4739 Pal.palNumEntries := 256;
4741 for Idx := 0 to Pal.palNumEntries - 1 do begin
4742 Pal.palPalEntry[Idx].peRed := Idx;
4743 Pal.palPalEntry[Idx].peGreen := Idx;
4744 Pal.palPalEntry[Idx].peBlue := Idx;
4745 Pal.palPalEntry[Idx].peFlags := 0;
4747 Result := CreatePalette(Pal^);
4751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4752 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4755 pSource, pData: PByte;
4758 if Assigned(Data) then begin
4759 if Assigned(aBitmap) then begin
4760 aBitmap.Width := Width;
4761 aBitmap.Height := Height;
4764 tfAlpha8, tfLuminance8: begin
4765 aBitmap.PixelFormat := pf8bit;
4766 aBitmap.Palette := CreateGrayPalette;
4769 aBitmap.PixelFormat := pf15bit;
4771 aBitmap.PixelFormat := pf16bit;
4773 aBitmap.PixelFormat := pf24bit;
4775 aBitmap.PixelFormat := pf32bit;
4777 raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.');
4781 for Row := 0 to FileHeight -1 do begin
4782 pData := aBitmap.Scanline[Row];
4783 Move(pSource^, pData^, fRowSize);
4784 Inc(pSource, fRowSize);
4785 if (Format in [tfRGB8, tfRGBA8]) then // swap RGB(A) to BGR(A)
4786 SwapRGB(pData, FileWidth, Format = tfRGBA8);
4793 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4794 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4796 pSource, pData, pTempData: PByte;
4797 Row, RowSize, TempWidth, TempHeight: Integer;
4798 IntFormat: TglBitmapFormat;
4802 if (Assigned(aBitmap)) then begin
4803 case aBitmap.PixelFormat of
4805 IntFormat := tfLuminance8;
4807 IntFormat := tfRGB5A1;
4809 IntFormat := tfR5G6B5;
4811 IntFormat := tfBGR8;
4813 IntFormat := tfBGRA8;
4815 raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.');
4818 TempWidth := aBitmap.Width;
4819 TempHeight := aBitmap.Height;
4820 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
4821 GetMem(pData, TempHeight * RowSize);
4824 for Row := 0 to TempHeight -1 do begin
4825 pSource := aBitmap.Scanline[Row];
4826 if (Assigned(pSource)) then begin
4827 Move(pSource^, pTempData^, RowSize);
4828 Inc(pTempData, RowSize);
4831 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4834 if Assigned(pData) then
4841 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4842 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4844 Row, Col, AlphaInterleave: Integer;
4845 pSource, pDest: PByte;
4849 if Assigned(Data) then begin
4850 if (Format in [tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8]) then begin
4851 if Assigned(aBitmap) then begin
4852 aBitmap.PixelFormat := pf8bit;
4853 aBitmap.Palette := CreateGrayPalette;
4854 aBitmap.Width := Width;
4855 aBitmap.Height := Height;
4859 AlphaInterleave := 1;
4861 AlphaInterleave := 3;
4863 AlphaInterleave := 0;
4869 for Row := 0 to Height -1 do begin
4870 pDest := aBitmap.Scanline[Row];
4871 if Assigned(pDest) then begin
4872 for Col := 0 to Width -1 do begin
4873 Inc(pSource, AlphaInterleave);
4886 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4887 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4891 tex := TglBitmap2D.Create;
4893 tex.AssignFromBitmap(ABitmap);
4894 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4901 {$IFDEF GLB_LAZARUS}
4902 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4903 function TglBitmap.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4905 rid: TRawImageDescription;
4906 FormatDesc: TFormatDescriptor;
4909 if not Assigned(aImage) or (Format = tfEmpty) then
4911 FormatDesc := TFormatDescriptor.Get(Format);
4912 if FormatDesc.IsCompressed then
4915 FillChar(rid{%H-}, SizeOf(rid), 0);
4917 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
4918 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
4919 tfLuminance4Alpha4, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16]) then
4920 rid.Format := ricfGray
4922 rid.Format := ricfRGBA;
4925 rid.Height := Height;
4926 rid.Depth := CountSetBits(FormatDesc.RedMask or FormatDesc.GreenMask or FormatDesc.BlueMask or FormatDesc.AlphaMask);
4927 rid.BitOrder := riboBitsInOrder;
4928 rid.ByteOrder := riboLSBFirst;
4929 rid.LineOrder := riloTopToBottom;
4930 rid.LineEnd := rileTight;
4931 rid.BitsPerPixel := Round(8 * FormatDesc.PixelSize);
4932 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
4933 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
4934 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
4935 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
4936 rid.RedShift := FormatDesc.Shift.r;
4937 rid.GreenShift := FormatDesc.Shift.g;
4938 rid.BlueShift := FormatDesc.Shift.b;
4939 rid.AlphaShift := FormatDesc.Shift.a;
4941 rid.MaskBitsPerPixel := 0;
4942 rid.PaletteColorCount := 0;
4944 aImage.DataDescription := rid;
4947 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
4952 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4953 function TglBitmap.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
4956 FormatDesc: TFormatDescriptor;
4961 if not Assigned(aImage) then
4963 for f := High(f) downto Low(f) do begin
4964 FormatDesc := TFormatDescriptor.Get(f);
4965 with aImage.DataDescription do
4966 if FormatDesc.MaskMatch(
4967 (QWord(1 shl RedPrec )-1) shl RedShift,
4968 (QWord(1 shl GreenPrec)-1) shl GreenShift,
4969 (QWord(1 shl BluePrec )-1) shl BlueShift,
4970 (QWord(1 shl AlphaPrec)-1) shl AlphaShift) then
4974 if (f = tfEmpty) then
4977 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
4978 ImageData := GetMem(ImageSize);
4980 Move(aImage.PixelData^, ImageData^, (aImage.Width * aImage.Height * aImage.DataDescription.BitsPerPixel) shr 3);
4981 SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method
4983 if Assigned(ImageData) then
4991 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4992 function TglBitmap.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4994 rid: TRawImageDescription;
4995 FormatDesc: TFormatDescriptor;
4996 Pixel: TglBitmapPixelData;
5002 if not Assigned(aImage) or (Format = tfEmpty) then
5004 FormatDesc := TFormatDescriptor.Get(Format);
5005 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5008 FillChar(rid{%H-}, SizeOf(rid), 0);
5009 rid.Format := ricfGray;
5011 rid.Height := Height;
5012 rid.Depth := CountSetBits(FormatDesc.Range.a);
5013 rid.BitOrder := riboBitsInOrder;
5014 rid.ByteOrder := riboLSBFirst;
5015 rid.LineOrder := riloTopToBottom;
5016 rid.LineEnd := rileTight;
5017 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
5018 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
5023 rid.GreenShift := 0;
5025 rid.AlphaShift := 0;
5027 rid.MaskBitsPerPixel := 0;
5028 rid.PaletteColorCount := 0;
5030 aImage.DataDescription := rid;
5033 srcMD := FormatDesc.CreateMappingData;
5035 FormatDesc.PreparePixel(Pixel);
5037 dst := aImage.PixelData;
5038 for y := 0 to Height-1 do
5039 for x := 0 to Width-1 do begin
5040 FormatDesc.Unmap(src, Pixel, srcMD);
5041 case rid.BitsPerPixel of
5043 dst^ := Pixel.Data.a;
5047 PWord(dst)^ := Pixel.Data.a;
5051 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
5052 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
5053 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
5057 PCardinal(dst)^ := Pixel.Data.a;
5061 raise EglBitmapUnsupportedFormat.Create(Format);
5065 FormatDesc.FreeMappingData(srcMD);
5070 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5071 function TglBitmap.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5075 tex := TglBitmap2D.Create;
5077 tex.AssignFromLazIntfImage(aImage);
5078 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5085 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5086 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
5087 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5089 rs: TResourceStream;
5091 PrepareResType(aResource, aResType);
5092 rs := TResourceStream.Create(aInstance, aResource, aResType);
5094 result := AddAlphaFromStream(rs, aFunc, aArgs);
5100 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5101 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
5102 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5104 rs: TResourceStream;
5106 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
5108 result := AddAlphaFromStream(rs, aFunc, aArgs);
5114 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5115 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5117 if TFormatDescriptor.Get(Format).IsCompressed then
5118 raise EglBitmapUnsupportedFormat.Create(Format);
5119 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
5122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5123 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5127 FS := TFileStream.Create(aFileName, fmOpenRead);
5129 result := AddAlphaFromStream(FS, aFunc, aArgs);
5135 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5136 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5140 tex := TglBitmap2D.Create(aStream);
5142 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5148 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5149 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5151 DestData, DestData2, SourceData: pByte;
5152 TempHeight, TempWidth: Integer;
5153 SourceFD, DestFD: TFormatDescriptor;
5154 SourceMD, DestMD, DestMD2: Pointer;
5156 FuncRec: TglBitmapFunctionRec;
5160 Assert(Assigned(Data));
5161 Assert(Assigned(aBitmap));
5162 Assert(Assigned(aBitmap.Data));
5164 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
5165 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
5167 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
5168 DestFD := TFormatDescriptor.Get(Format);
5170 if not Assigned(aFunc) then begin
5171 aFunc := glBitmapAlphaFunc;
5172 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5174 FuncRec.Args := aArgs;
5177 TempHeight := aBitmap.FileHeight;
5178 TempWidth := aBitmap.FileWidth;
5180 FuncRec.Sender := Self;
5181 FuncRec.Size := Dimension;
5182 FuncRec.Position.Fields := FuncRec.Size.Fields;
5186 SourceData := aBitmap.Data;
5189 SourceFD.PreparePixel(FuncRec.Source);
5190 DestFD.PreparePixel (FuncRec.Dest);
5192 SourceMD := SourceFD.CreateMappingData;
5193 DestMD := DestFD.CreateMappingData;
5194 DestMD2 := DestFD.CreateMappingData;
5196 FuncRec.Position.Y := 0;
5197 while FuncRec.Position.Y < TempHeight do begin
5198 FuncRec.Position.X := 0;
5199 while FuncRec.Position.X < TempWidth do begin
5200 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5201 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5203 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5204 inc(FuncRec.Position.X);
5206 inc(FuncRec.Position.Y);
5209 SourceFD.FreeMappingData(SourceMD);
5210 DestFD.FreeMappingData(DestMD);
5211 DestFD.FreeMappingData(DestMD2);
5216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5217 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5219 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5222 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5223 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5225 PixelData: TglBitmapPixelData;
5227 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5228 result := AddAlphaFromColorKeyFloat(
5229 aRed / PixelData.Range.r,
5230 aGreen / PixelData.Range.g,
5231 aBlue / PixelData.Range.b,
5232 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5235 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5236 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5238 values: array[0..2] of Single;
5241 PixelData: TglBitmapPixelData;
5243 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5244 with PixelData do begin
5246 values[1] := aGreen;
5249 for i := 0 to 2 do begin
5250 tmp := Trunc(Range.arr[i] * aDeviation);
5251 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5252 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5257 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5260 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5261 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5263 result := AddAlphaFromValueFloat(aAlpha / $FF);
5266 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5267 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5269 PixelData: TglBitmapPixelData;
5271 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5272 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5275 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5276 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5278 PixelData: TglBitmapPixelData;
5280 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5282 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5283 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5286 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5287 function TglBitmap.RemoveAlpha: Boolean;
5289 FormatDesc: TFormatDescriptor;
5292 FormatDesc := TFormatDescriptor.Get(Format);
5293 if Assigned(Data) then begin
5294 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5295 raise EglBitmapUnsupportedFormat.Create(Format);
5296 result := ConvertTo(FormatDesc.WithoutAlpha);
5300 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5301 function TglBitmap.Clone: TglBitmap;
5308 Temp := (ClassType.Create as TglBitmap);
5310 // copy texture data if assigned
5311 if Assigned(Data) then begin
5312 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5313 GetMem(TempPtr, Size);
5315 Move(Data^, TempPtr^, Size);
5316 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5318 if Assigned(TempPtr) then
5324 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5329 Temp.fTarget := Target;
5330 Temp.fFormat := Format;
5331 Temp.fMipMap := MipMap;
5332 Temp.fAnisotropic := Anisotropic;
5333 Temp.fBorderColor := fBorderColor;
5334 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5335 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5336 Temp.fFilterMin := fFilterMin;
5337 Temp.fFilterMag := fFilterMag;
5338 Temp.fWrapS := fWrapS;
5339 Temp.fWrapT := fWrapT;
5340 Temp.fWrapR := fWrapR;
5341 Temp.fFilename := fFilename;
5342 Temp.fCustomName := fCustomName;
5343 Temp.fCustomNameW := fCustomNameW;
5344 Temp.fCustomData := fCustomData;
5353 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5354 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5356 SourceFD, DestFD: TFormatDescriptor;
5357 SourcePD, DestPD: TglBitmapPixelData;
5358 ShiftData: TShiftData;
5360 function CanCopyDirect: Boolean;
5363 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5364 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5365 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5366 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5369 function CanShift: Boolean;
5372 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5373 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5374 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5375 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5378 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5381 while (aSource > aDest) and (aSource > 0) do begin
5383 aSource := aSource shr 1;
5388 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5389 SourceFD := TFormatDescriptor.Get(Format);
5390 DestFD := TFormatDescriptor.Get(aFormat);
5392 SourceFD.PreparePixel(SourcePD);
5393 DestFD.PreparePixel (DestPD);
5395 if CanCopyDirect then
5396 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5397 else if CanShift then begin
5398 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5399 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5400 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5401 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5402 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5404 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5409 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5410 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5412 if aUseRGB or aUseAlpha then
5413 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5414 ((Byte(aUseAlpha) and 1) shl 1) or
5415 (Byte(aUseRGB) and 1) ));
5418 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5419 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5421 fBorderColor[0] := aRed;
5422 fBorderColor[1] := aGreen;
5423 fBorderColor[2] := aBlue;
5424 fBorderColor[3] := aAlpha;
5425 if (ID > 0) then begin
5427 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5431 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5432 procedure TglBitmap.FreeData;
5437 SetDataPointer(TempPtr, tfEmpty); //be careful, Data could be freed by this method
5440 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5441 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5442 const aAlpha: Byte);
5444 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5447 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5448 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5450 PixelData: TglBitmapPixelData;
5452 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5454 aRed / PixelData.Range.r,
5455 aGreen / PixelData.Range.g,
5456 aBlue / PixelData.Range.b,
5457 aAlpha / PixelData.Range.a);
5460 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5461 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5463 PixelData: TglBitmapPixelData;
5465 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5466 with PixelData do begin
5467 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5468 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5469 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5470 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5472 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5475 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5476 procedure TglBitmap.SetFilter(const aMin, aMag: GLenum);
5481 fFilterMin := GL_NEAREST;
5483 fFilterMin := GL_LINEAR;
5484 GL_NEAREST_MIPMAP_NEAREST:
5485 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5486 GL_LINEAR_MIPMAP_NEAREST:
5487 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5488 GL_NEAREST_MIPMAP_LINEAR:
5489 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5490 GL_LINEAR_MIPMAP_LINEAR:
5491 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5493 raise EglBitmap.Create('SetFilter - Unknow MIN filter.');
5499 fFilterMag := GL_NEAREST;
5501 fFilterMag := GL_LINEAR;
5503 raise EglBitmap.Create('SetFilter - Unknow MAG filter.');
5507 if (ID > 0) then begin
5509 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5511 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5513 GL_NEAREST, GL_LINEAR:
5514 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5515 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5516 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5517 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5518 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5521 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5525 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5526 procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum);
5528 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5532 aTarget := GL_CLAMP;
5535 aTarget := GL_REPEAT;
5537 GL_CLAMP_TO_EDGE: begin
5538 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5539 aTarget := GL_CLAMP_TO_EDGE
5541 aTarget := GL_CLAMP;
5544 GL_CLAMP_TO_BORDER: begin
5545 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5546 aTarget := GL_CLAMP_TO_BORDER
5548 aTarget := GL_CLAMP;
5551 GL_MIRRORED_REPEAT: begin
5552 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5553 aTarget := GL_MIRRORED_REPEAT
5555 raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5558 raise EglBitmap.Create('SetWrap - Unknow Texturewrap');
5563 CheckAndSetWrap(S, fWrapS);
5564 CheckAndSetWrap(T, fWrapT);
5565 CheckAndSetWrap(R, fWrapR);
5567 if (ID > 0) then begin
5569 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5570 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5571 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5575 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5576 procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum);
5578 procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer);
5580 if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or
5581 (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then
5582 fSwizzle[aIndex] := aValue
5584 raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value');
5588 if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
5589 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
5590 CheckAndSetValue(r, 0);
5591 CheckAndSetValue(g, 1);
5592 CheckAndSetValue(b, 2);
5593 CheckAndSetValue(a, 3);
5595 if (ID > 0) then begin
5597 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, @fSwizzle[0]);
5601 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5602 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5604 if aEnableTextureUnit then
5607 glBindTexture(Target, ID);
5610 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5611 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5613 if aDisableTextureUnit then
5615 glBindTexture(Target, 0);
5618 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5619 constructor TglBitmap.Create;
5621 if (ClassType = TglBitmap) then
5622 raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5623 {$IFDEF GLB_NATIVE_OGL}
5624 glbReadOpenGLExtensions;
5629 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5630 constructor TglBitmap.Create(const aFileName: String);
5633 LoadFromFile(aFileName);
5636 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5637 constructor TglBitmap.Create(const aStream: TStream);
5640 LoadFromStream(aStream);
5643 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5644 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
5650 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5651 GetMem(Image, ImageSize);
5653 FillChar(Image^, ImageSize, #$FF);
5654 SetDataPointer(Image, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5656 if Assigned(Image) then
5662 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5663 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
5664 const aFunc: TglBitmapFunction; const aArgs: Pointer);
5667 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5670 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5671 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5674 LoadFromResource(aInstance, aResource, aResType);
5677 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5678 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5681 LoadFromResourceID(aInstance, aResourceID, aResType);
5684 {$IFDEF GLB_SUPPORT_PNG_READ}
5685 {$IF DEFINED(GLB_LAZ_PNG)}
5686 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5687 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5688 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5689 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5692 PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A;
5694 png: TPortableNetworkGraphic;
5695 intf: TLazIntfImage;
5697 magic: String[MAGIC_LEN];
5700 StreamPos := aStream.Position;
5702 SetLength(magic, MAGIC_LEN);
5703 aStream.Read(magic[1], MAGIC_LEN);
5704 aStream.Position := StreamPos;
5705 if (magic <> PNG_MAGIC) then begin
5710 png := TPortableNetworkGraphic.Create;
5712 png.LoadFromStream(aStream);
5713 intf := png.CreateIntfImage;
5715 AssignFromLazIntfImage(intf);
5718 aStream.Position := StreamPos;
5726 aStream.Position := StreamPos;
5734 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
5735 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5736 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5738 Surface: PSDL_Surface;
5742 RWops := glBitmapCreateRWops(aStream);
5744 if IMG_isPNG(RWops) > 0 then begin
5745 Surface := IMG_LoadPNG_RW(RWops);
5747 AssignFromSurface(Surface);
5750 SDL_FreeSurface(Surface);
5758 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5759 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5760 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5762 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5765 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5766 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5769 signature: array [0..7] of byte;
5771 png_info: png_infop;
5773 TempHeight, TempWidth: Integer;
5774 Format: TglBitmapFormat;
5777 png_rows: array of pByte;
5778 Row, LineSize: Integer;
5782 if not init_libPNG then
5783 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5787 StreamPos := aStream.Position;
5788 aStream.Read(signature{%H-}, 8);
5789 aStream.Position := StreamPos;
5791 if png_check_sig(@signature, 8) <> 0 then begin
5793 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5795 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5798 png_info := png_create_info_struct(png);
5799 if png_info = nil then begin
5800 png_destroy_read_struct(@png, nil, nil);
5801 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5804 // set read callback
5805 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5807 // read informations
5808 png_read_info(png, png_info);
5811 TempHeight := png_get_image_height(png, png_info);
5812 TempWidth := png_get_image_width(png, png_info);
5815 case png_get_color_type(png, png_info) of
5816 PNG_COLOR_TYPE_GRAY:
5817 Format := tfLuminance8;
5818 PNG_COLOR_TYPE_GRAY_ALPHA:
5819 Format := tfLuminance8Alpha8;
5822 PNG_COLOR_TYPE_RGB_ALPHA:
5825 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5828 // cut upper 8 bit from 16 bit formats
5829 if png_get_bit_depth(png, png_info) > 8 then
5830 png_set_strip_16(png);
5832 // expand bitdepth smaller than 8
5833 if png_get_bit_depth(png, png_info) < 8 then
5834 png_set_expand(png);
5836 // allocating mem for scanlines
5837 LineSize := png_get_rowbytes(png, png_info);
5838 GetMem(png_data, TempHeight * LineSize);
5840 SetLength(png_rows, TempHeight);
5841 for Row := Low(png_rows) to High(png_rows) do begin
5842 png_rows[Row] := png_data;
5843 Inc(png_rows[Row], Row * LineSize);
5846 // read complete image into scanlines
5847 png_read_image(png, @png_rows[0]);
5850 png_read_end(png, png_info);
5852 // destroy read struct
5853 png_destroy_read_struct(@png, @png_info, nil);
5855 SetLength(png_rows, 0);
5858 SetDataPointer(png_data, Format, TempWidth, TempHeight); //be careful, Data could be freed by this method
5862 if Assigned(png_data) then
5872 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5873 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5874 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5879 Row, Col, PixSize, LineSize: Integer;
5880 NewImage, pSource, pDest, pAlpha: pByte;
5881 PngFormat: TglBitmapFormat;
5882 FormatDesc: TFormatDescriptor;
5885 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
5890 StreamPos := aStream.Position;
5891 aStream.Read(Header[0], SizeOf(Header));
5892 aStream.Position := StreamPos;
5894 {Test if the header matches}
5895 if Header = PngHeader then begin
5896 Png := TPNGObject.Create;
5898 Png.LoadFromStream(aStream);
5900 case Png.Header.ColorType of
5902 PngFormat := tfLuminance8;
5903 COLOR_GRAYSCALEALPHA:
5904 PngFormat := tfLuminance8Alpha8;
5906 PngFormat := tfBGR8;
5908 PngFormat := tfBGRA8;
5910 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5913 FormatDesc := TFormatDescriptor.Get(PngFormat);
5914 PixSize := Round(FormatDesc.PixelSize);
5915 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
5917 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5921 case Png.Header.ColorType of
5922 COLOR_RGB, COLOR_GRAYSCALE:
5924 for Row := 0 to Png.Height -1 do begin
5925 Move (Png.Scanline[Row]^, pDest^, LineSize);
5926 Inc(pDest, LineSize);
5929 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5931 PixSize := PixSize -1;
5933 for Row := 0 to Png.Height -1 do begin
5934 pSource := Png.Scanline[Row];
5935 pAlpha := pByte(Png.AlphaScanline[Row]);
5937 for Col := 0 to Png.Width -1 do begin
5938 Move (pSource^, pDest^, PixSize);
5939 Inc(pSource, PixSize);
5940 Inc(pDest, PixSize);
5949 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5952 SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); //be careful, Data could be freed by this method
5956 if Assigned(NewImage) then
5968 {$IFDEF GLB_SUPPORT_PNG_WRITE}
5969 {$IFDEF GLB_LIB_PNG}
5970 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5971 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5973 TStream(png_get_io_ptr(png)).Write(buffer^, size);
5977 {$IF DEFINED(GLB_LAZ_PNG)}
5978 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5979 procedure TglBitmap.SavePNG(const aStream: TStream);
5981 png: TPortableNetworkGraphic;
5982 intf: TLazIntfImage;
5985 png := TPortableNetworkGraphic.Create;
5986 intf := TLazIntfImage.Create(0, 0);
5988 if not AssignToLazIntfImage(intf) then
5989 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
5990 intf.GetRawImage(raw);
5991 png.LoadFromRawImage(raw, false);
5992 png.SaveToStream(aStream);
5999 {$ELSEIF DEFINED(GLB_LIB_PNG)}
6000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6001 procedure TglBitmap.SavePNG(const aStream: TStream);
6004 png_info: png_infop;
6005 png_rows: array of pByte;
6009 FormatDesc: TFormatDescriptor;
6011 if not (ftPNG in FormatGetSupportedFiles(Format)) then
6012 raise EglBitmapUnsupportedFormat.Create(Format);
6014 if not init_libPNG then
6015 raise Exception.Create('unable to initialize libPNG.');
6019 tfAlpha8, tfLuminance8:
6020 ColorType := PNG_COLOR_TYPE_GRAY;
6022 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
6024 ColorType := PNG_COLOR_TYPE_RGB;
6026 ColorType := PNG_COLOR_TYPE_RGBA;
6028 raise EglBitmapUnsupportedFormat.Create(Format);
6031 FormatDesc := TFormatDescriptor.Get(Format);
6032 LineSize := FormatDesc.GetSize(Width, 1);
6034 // creating array for scanline
6035 SetLength(png_rows, Height);
6037 for Row := 0 to Height - 1 do begin
6038 png_rows[Row] := Data;
6039 Inc(png_rows[Row], Row * LineSize)
6043 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
6045 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
6048 png_info := png_create_info_struct(png);
6049 if png_info = nil then begin
6050 png_destroy_write_struct(@png, nil);
6051 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
6054 // set read callback
6055 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
6058 png_set_compression_level(png, 6);
6060 if Format in [tfBGR8, tfBGRA8] then
6063 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
6064 png_write_info(png, png_info);
6065 png_write_image(png, @png_rows[0]);
6066 png_write_end(png, png_info);
6067 png_destroy_write_struct(@png, @png_info);
6069 SetLength(png_rows, 0);
6076 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
6077 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6078 procedure TglBitmap.SavePNG(const aStream: TStream);
6082 pSource, pDest: pByte;
6083 X, Y, PixSize: Integer;
6084 ColorType: Cardinal;
6090 if not (ftPNG in FormatGetSupportedFiles (Format)) then
6091 raise EglBitmapUnsupportedFormat.Create(Format);
6094 tfAlpha8, tfLuminance8: begin
6095 ColorType := COLOR_GRAYSCALE;
6099 tfLuminance8Alpha8: begin
6100 ColorType := COLOR_GRAYSCALEALPHA;
6104 tfBGR8, tfRGB8: begin
6105 ColorType := COLOR_RGB;
6109 tfBGRA8, tfRGBA8: begin
6110 ColorType := COLOR_RGBALPHA;
6115 raise EglBitmapUnsupportedFormat.Create(Format);
6118 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
6122 for Y := 0 to Height -1 do begin
6123 pDest := png.ScanLine[Y];
6124 for X := 0 to Width -1 do begin
6125 Move(pSource^, pDest^, PixSize);
6126 Inc(pDest, PixSize);
6127 Inc(pSource, PixSize);
6129 png.AlphaScanline[Y]^[X] := pSource^;
6134 // convert RGB line to BGR
6135 if Format in [tfRGB8, tfRGBA8] then begin
6136 pTemp := png.ScanLine[Y];
6137 for X := 0 to Width -1 do begin
6138 Temp := pByteArray(pTemp)^[0];
6139 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
6140 pByteArray(pTemp)^[2] := Temp;
6147 Png.CompressionLevel := 6;
6148 Png.SaveToStream(aStream);
6156 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6157 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6159 {$IFDEF GLB_LIB_JPEG}
6161 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
6162 glBitmap_libJPEG_source_mgr = record
6163 pub: jpeg_source_mgr;
6166 SrcBuffer: array [1..4096] of byte;
6169 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
6170 glBitmap_libJPEG_dest_mgr = record
6171 pub: jpeg_destination_mgr;
6173 DestStream: TStream;
6174 DestBuffer: array [1..4096] of byte;
6177 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
6183 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
6189 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
6194 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
6200 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
6206 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6207 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
6209 src: glBitmap_libJPEG_source_mgr_ptr;
6212 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6214 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
6215 if (bytes <= 0) then begin
6216 src^.SrcBuffer[1] := $FF;
6217 src^.SrcBuffer[2] := JPEG_EOI;
6221 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
6222 src^.pub.bytes_in_buffer := bytes;
6227 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6228 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
6230 src: glBitmap_libJPEG_source_mgr_ptr;
6232 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6234 if num_bytes > 0 then begin
6235 // wanted byte isn't in buffer so set stream position and read buffer
6236 if num_bytes > src^.pub.bytes_in_buffer then begin
6237 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
6238 src^.pub.fill_input_buffer(cinfo);
6240 // wanted byte is in buffer so only skip
6241 inc(src^.pub.next_input_byte, num_bytes);
6242 dec(src^.pub.bytes_in_buffer, num_bytes);
6247 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6248 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
6250 dest: glBitmap_libJPEG_dest_mgr_ptr;
6252 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6254 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
6255 // write complete buffer
6256 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
6259 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
6260 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
6266 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6267 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
6270 dest: glBitmap_libJPEG_dest_mgr_ptr;
6272 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6274 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6275 // check for endblock
6276 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6278 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6283 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6288 {$IFDEF GLB_SUPPORT_JPEG_READ}
6289 {$IF DEFINED(GLB_LAZ_JPEG)}
6290 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6291 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6294 JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
6297 intf: TLazIntfImage;
6299 magic: String[MAGIC_LEN];
6302 StreamPos := aStream.Position;
6304 SetLength(magic, MAGIC_LEN);
6305 aStream.Read(magic[1], MAGIC_LEN);
6306 aStream.Position := StreamPos;
6307 if (magic <> JPEG_MAGIC) then begin
6312 jpeg := TJPEGImage.Create;
6314 jpeg.LoadFromStream(aStream);
6315 intf := TLazIntfImage.Create(0, 0);
6317 intf.LoadFromBitmap(jpeg.BitmapHandle, jpeg.MaskHandle);
6318 AssignFromLazIntfImage(intf);
6321 aStream.Position := StreamPos;
6329 aStream.Position := StreamPos;
6337 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
6338 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6339 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6341 Surface: PSDL_Surface;
6346 RWops := glBitmapCreateRWops(aStream);
6348 if IMG_isJPG(RWops) > 0 then begin
6349 Surface := IMG_LoadJPG_RW(RWops);
6351 AssignFromSurface(Surface);
6354 SDL_FreeSurface(Surface);
6362 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6363 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6364 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6367 Temp: array[0..1]of Byte;
6369 jpeg: jpeg_decompress_struct;
6370 jpeg_err: jpeg_error_mgr;
6372 IntFormat: TglBitmapFormat;
6374 TempHeight, TempWidth: Integer;
6379 FormatDesc: TFormatDescriptor;
6383 if not init_libJPEG then
6384 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6387 // reading first two bytes to test file and set cursor back to begin
6388 StreamPos := aStream.Position;
6389 aStream.Read({%H-}Temp[0], 2);
6390 aStream.Position := StreamPos;
6392 // if Bitmap then read file.
6393 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6394 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6395 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6398 jpeg.err := jpeg_std_error(@jpeg_err);
6399 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6400 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6402 // decompression struct
6403 jpeg_create_decompress(@jpeg);
6405 // allocation space for streaming methods
6406 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6408 // seeting up custom functions
6409 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6410 pub.init_source := glBitmap_libJPEG_init_source;
6411 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6412 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6413 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6414 pub.term_source := glBitmap_libJPEG_term_source;
6416 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6417 pub.next_input_byte := nil; // until buffer loaded
6419 SrcStream := aStream;
6422 // set global decoding state
6423 jpeg.global_state := DSTATE_START;
6425 // read header of jpeg
6426 jpeg_read_header(@jpeg, false);
6428 // setting output parameter
6429 case jpeg.jpeg_color_space of
6432 jpeg.out_color_space := JCS_GRAYSCALE;
6433 IntFormat := tfLuminance8;
6436 jpeg.out_color_space := JCS_RGB;
6437 IntFormat := tfRGB8;
6441 jpeg_start_decompress(@jpeg);
6443 TempHeight := jpeg.output_height;
6444 TempWidth := jpeg.output_width;
6446 FormatDesc := TFormatDescriptor.Get(IntFormat);
6448 // creating new image
6449 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6453 for Row := 0 to TempHeight -1 do begin
6454 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6455 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6458 // finish decompression
6459 jpeg_finish_decompress(@jpeg);
6461 // destroy decompression
6462 jpeg_destroy_decompress(@jpeg);
6464 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
6468 if Assigned(pImage) then
6478 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6479 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6480 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6485 Temp: array[0..1]of Byte;
6489 // reading first two bytes to test file and set cursor back to begin
6490 StreamPos := aStream.Position;
6491 aStream.Read(Temp[0], 2);
6492 aStream.Position := StreamPos;
6494 // if Bitmap then read file.
6495 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6496 bmp := TBitmap.Create;
6498 jpg := TJPEGImage.Create;
6500 jpg.LoadFromStream(aStream);
6502 result := AssignFromBitmap(bmp);
6514 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6515 {$IF DEFINED(GLB_LAZ_JPEG)}
6516 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6517 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6520 intf: TLazIntfImage;
6523 jpeg := TJPEGImage.Create;
6524 intf := TLazIntfImage.Create(0, 0);
6526 if not AssignToLazIntfImage(intf) then
6527 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6528 intf.GetRawImage(raw);
6529 jpeg.LoadFromRawImage(raw, false);
6530 jpeg.SaveToStream(aStream);
6537 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6538 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6539 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6541 jpeg: jpeg_compress_struct;
6542 jpeg_err: jpeg_error_mgr;
6544 pTemp, pTemp2: pByte;
6546 procedure CopyRow(pDest, pSource: pByte);
6550 for X := 0 to Width - 1 do begin
6551 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6552 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6553 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6560 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6561 raise EglBitmapUnsupportedFormat.Create(Format);
6563 if not init_libJPEG then
6564 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6567 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6568 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6571 jpeg.err := jpeg_std_error(@jpeg_err);
6572 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6573 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6575 // compression struct
6576 jpeg_create_compress(@jpeg);
6578 // allocation space for streaming methods
6579 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6581 // seeting up custom functions
6582 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6583 pub.init_destination := glBitmap_libJPEG_init_destination;
6584 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6585 pub.term_destination := glBitmap_libJPEG_term_destination;
6587 pub.next_output_byte := @DestBuffer[1];
6588 pub.free_in_buffer := Length(DestBuffer);
6590 DestStream := aStream;
6593 // very important state
6594 jpeg.global_state := CSTATE_START;
6595 jpeg.image_width := Width;
6596 jpeg.image_height := Height;
6598 tfAlpha8, tfLuminance8: begin
6599 jpeg.input_components := 1;
6600 jpeg.in_color_space := JCS_GRAYSCALE;
6602 tfRGB8, tfBGR8: begin
6603 jpeg.input_components := 3;
6604 jpeg.in_color_space := JCS_RGB;
6608 jpeg_set_defaults(@jpeg);
6609 jpeg_set_quality(@jpeg, 95, true);
6610 jpeg_start_compress(@jpeg, true);
6613 if Format = tfBGR8 then
6614 GetMem(pTemp2, fRowSize)
6619 for Row := 0 to jpeg.image_height -1 do begin
6621 if Format = tfBGR8 then
6622 CopyRow(pTemp2, pTemp)
6627 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6628 inc(pTemp, fRowSize);
6632 if Format = tfBGR8 then
6635 jpeg_finish_compress(@jpeg);
6636 jpeg_destroy_compress(@jpeg);
6642 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6643 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6644 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6649 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6650 raise EglBitmapUnsupportedFormat.Create(Format);
6652 Bmp := TBitmap.Create;
6654 Jpg := TJPEGImage.Create;
6656 AssignToBitmap(Bmp);
6657 if (Format in [tfAlpha8, tfLuminance8]) then begin
6658 Jpg.Grayscale := true;
6659 Jpg.PixelFormat := jf8Bit;
6662 Jpg.SaveToStream(aStream);
6673 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6674 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6675 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6682 BMP_COMP_BITFIELDS = 3;
6685 TBMPHeader = packed record
6690 bfOffBits: Cardinal;
6693 TBMPInfo = packed record
6699 biCompression: Cardinal;
6700 biSizeImage: Cardinal;
6701 biXPelsPerMeter: Longint;
6702 biYPelsPerMeter: Longint;
6703 biClrUsed: Cardinal;
6704 biClrImportant: Cardinal;
6707 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6708 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6710 //////////////////////////////////////////////////////////////////////////////////////////////////
6711 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6714 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6715 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6718 case aInfo.biCompression of
6720 BMP_COMP_RLE8: begin
6721 raise EglBitmap.Create('RLE compression is not supported');
6723 BMP_COMP_BITFIELDS: begin
6724 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6725 aStream.Read(aMask.r, SizeOf(aMask.r));
6726 aStream.Read(aMask.g, SizeOf(aMask.g));
6727 aStream.Read(aMask.b, SizeOf(aMask.b));
6728 aStream.Read(aMask.a, SizeOf(aMask.a));
6730 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
6734 //get suitable format
6735 case aInfo.biBitCount of
6736 8: result := tfLuminance8;
6737 16: result := tfBGR5;
6738 24: result := tfBGR8;
6739 32: result := tfBGRA8;
6743 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6746 ColorTable: TbmpColorTable;
6749 if (aInfo.biBitCount >= 16) then
6751 aFormat := tfLuminance8;
6752 c := aInfo.biClrUsed;
6754 c := 1 shl aInfo.biBitCount;
6755 SetLength(ColorTable, c);
6756 for i := 0 to c-1 do begin
6757 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6758 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6762 result := TbmpColorTableFormat.Create;
6763 result.PixelSize := aInfo.biBitCount / 8;
6764 result.ColorTable := ColorTable;
6765 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6768 //////////////////////////////////////////////////////////////////////////////////////////////////
6769 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6770 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6772 TmpFormat: TglBitmapFormat;
6773 FormatDesc: TFormatDescriptor;
6776 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6777 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6778 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6779 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6780 aFormat := FormatDesc.Format;
6785 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6786 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6787 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6788 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6790 result := TbmpBitfieldFormat.Create;
6791 result.PixelSize := aInfo.biBitCount / 8;
6792 result.RedMask := aMask.r;
6793 result.GreenMask := aMask.g;
6794 result.BlueMask := aMask.b;
6795 result.AlphaMask := aMask.a;
6802 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6803 PaddingBuff: Cardinal;
6804 LineBuf, ImageData, TmpData: PByte;
6805 SourceMD, DestMD: Pointer;
6806 BmpFormat: TglBitmapFormat;
6809 Mask: TglBitmapColorRec;
6814 SpecialFormat: TFormatDescriptor;
6815 FormatDesc: TFormatDescriptor;
6817 //////////////////////////////////////////////////////////////////////////////////////////////////
6818 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6821 Pixel: TglBitmapPixelData;
6823 aStream.Read(aLineBuf^, rbLineSize);
6824 SpecialFormat.PreparePixel(Pixel);
6825 for i := 0 to Info.biWidth-1 do begin
6826 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6827 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6828 FormatDesc.Map(Pixel, aData, DestMD);
6834 BmpFormat := tfEmpty;
6835 SpecialFormat := nil;
6841 StartPos := aStream.Position;
6842 aStream.Read(Header{%H-}, SizeOf(Header));
6844 if Header.bfType = BMP_MAGIC then begin
6846 BmpFormat := ReadInfo(Info, Mask);
6847 SpecialFormat := ReadColorTable(BmpFormat, Info);
6848 if not Assigned(SpecialFormat) then
6849 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6850 aStream.Position := StartPos + Header.bfOffBits;
6852 if (BmpFormat <> tfEmpty) then begin
6853 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6854 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6855 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6856 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6859 DestMD := FormatDesc.CreateMappingData;
6860 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6861 GetMem(ImageData, ImageSize);
6862 if Assigned(SpecialFormat) then begin
6863 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6864 SourceMD := SpecialFormat.CreateMappingData;
6869 FillChar(ImageData^, ImageSize, $FF);
6870 TmpData := ImageData;
6871 if (Info.biHeight > 0) then
6872 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6873 for i := 0 to Abs(Info.biHeight)-1 do begin
6874 if Assigned(SpecialFormat) then
6875 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6877 aStream.Read(TmpData^, wbLineSize); //else only read data
6878 if (Info.biHeight > 0) then
6879 dec(TmpData, wbLineSize)
6881 inc(TmpData, wbLineSize);
6882 aStream.Read(PaddingBuff{%H-}, Padding);
6884 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method
6887 if Assigned(LineBuf) then
6889 if Assigned(SourceMD) then
6890 SpecialFormat.FreeMappingData(SourceMD);
6891 FormatDesc.FreeMappingData(DestMD);
6894 if Assigned(ImageData) then
6899 raise EglBitmap.Create('LoadBMP - No suitable format found');
6901 aStream.Position := StartPos;
6905 FreeAndNil(SpecialFormat);
6908 else aStream.Position := StartPos;
6911 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6912 procedure TglBitmap.SaveBMP(const aStream: TStream);
6916 Converter: TFormatDescriptor;
6917 FormatDesc: TFormatDescriptor;
6918 SourceFD, DestFD: Pointer;
6919 pData, srcData, dstData, ConvertBuffer: pByte;
6921 Pixel: TglBitmapPixelData;
6922 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6923 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6925 PaddingBuff: Cardinal;
6927 function GetLineWidth : Integer;
6929 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6933 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6934 raise EglBitmapUnsupportedFormat.Create(Format);
6937 FormatDesc := TFormatDescriptor.Get(Format);
6938 ImageSize := FormatDesc.GetSize(Dimension);
6940 FillChar(Header{%H-}, SizeOf(Header), 0);
6941 Header.bfType := BMP_MAGIC;
6942 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6943 Header.bfReserved1 := 0;
6944 Header.bfReserved2 := 0;
6945 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6947 FillChar(Info{%H-}, SizeOf(Info), 0);
6948 Info.biSize := SizeOf(Info);
6949 Info.biWidth := Width;
6950 Info.biHeight := Height;
6952 Info.biCompression := BMP_COMP_RGB;
6953 Info.biSizeImage := ImageSize;
6958 Info.biBitCount := 4;
6959 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6960 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6961 Converter := TbmpColorTableFormat.Create;
6962 with (Converter as TbmpColorTableFormat) do begin
6965 Range := glBitmapColorRec($F, $F, $F, $0);
6970 tfR3G3B2, tfLuminance8: begin
6971 Info.biBitCount := 8;
6972 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6973 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6974 Converter := TbmpColorTableFormat.Create;
6975 with (Converter as TbmpColorTableFormat) do begin
6978 if (Format = tfR3G3B2) then begin
6979 Range := glBitmapColorRec($7, $7, $3, $0);
6980 Shift := glBitmapShiftRec(0, 3, 6, 0);
6982 Range := glBitmapColorRec($FF, $FF, $FF, $0);
6987 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6988 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6989 Info.biBitCount := 16;
6990 Info.biCompression := BMP_COMP_BITFIELDS;
6993 tfBGR8, tfRGB8: begin
6994 Info.biBitCount := 24;
6995 if (Format = tfRGB8) then
6996 Converter := TfdBGR8.Create; //use BGR8 Format Descriptor to Swap RGB Values
6999 tfRGB10, tfRGB10A2, tfRGBA8,
7000 tfBGR10, tfBGR10A2, tfBGRA8: begin
7001 Info.biBitCount := 32;
7002 Info.biCompression := BMP_COMP_BITFIELDS;
7005 raise EglBitmapUnsupportedFormat.Create(Format);
7007 Info.biXPelsPerMeter := 2835;
7008 Info.biYPelsPerMeter := 2835;
7011 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7012 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
7013 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
7015 RedMask := FormatDesc.RedMask;
7016 GreenMask := FormatDesc.GreenMask;
7017 BlueMask := FormatDesc.BlueMask;
7018 AlphaMask := FormatDesc.AlphaMask;
7022 aStream.Write(Header, SizeOf(Header));
7023 aStream.Write(Info, SizeOf(Info));
7026 if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
7027 with (Converter as TbmpColorTableFormat) do
7028 aStream.Write(ColorTable[0].b,
7029 SizeOf(TbmpColorTableEnty) * Length(ColorTable));
7032 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7033 aStream.Write(RedMask, SizeOf(Cardinal));
7034 aStream.Write(GreenMask, SizeOf(Cardinal));
7035 aStream.Write(BlueMask, SizeOf(Cardinal));
7036 aStream.Write(AlphaMask, SizeOf(Cardinal));
7040 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
7041 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
7042 Padding := GetLineWidth - wbLineSize;
7046 inc(pData, (Height-1) * rbLineSize);
7048 // prepare row buffer. But only for RGB because RGBA supports color masks
7049 // so it's possible to change color within the image.
7050 if Assigned(Converter) then begin
7051 FormatDesc.PreparePixel(Pixel);
7052 GetMem(ConvertBuffer, wbLineSize);
7053 SourceFD := FormatDesc.CreateMappingData;
7054 DestFD := Converter.CreateMappingData;
7056 ConvertBuffer := nil;
7059 for LineIdx := 0 to Height - 1 do begin
7061 if Assigned(Converter) then begin
7063 dstData := ConvertBuffer;
7064 for PixelIdx := 0 to Info.biWidth-1 do begin
7065 FormatDesc.Unmap(srcData, Pixel, SourceFD);
7066 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
7067 Converter.Map(Pixel, dstData, DestFD);
7069 aStream.Write(ConvertBuffer^, wbLineSize);
7071 aStream.Write(pData^, rbLineSize);
7073 dec(pData, rbLineSize);
7074 if (Padding > 0) then
7075 aStream.Write(PaddingBuff, Padding);
7078 // destroy row buffer
7079 if Assigned(ConvertBuffer) then begin
7080 FormatDesc.FreeMappingData(SourceFD);
7081 Converter.FreeMappingData(DestFD);
7082 FreeMem(ConvertBuffer);
7086 if Assigned(Converter) then
7091 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7092 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7093 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7095 TTGAHeader = packed record
7099 //ColorMapSpec: Array[0..4] of Byte;
7100 ColorMapStart: Word;
7101 ColorMapLength: Word;
7102 ColorMapEntrySize: Byte;
7112 TGA_UNCOMPRESSED_RGB = 2;
7113 TGA_UNCOMPRESSED_GRAY = 3;
7114 TGA_COMPRESSED_RGB = 10;
7115 TGA_COMPRESSED_GRAY = 11;
7117 TGA_NONE_COLOR_TABLE = 0;
7119 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7120 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
7123 ImageData: System.PByte;
7124 StartPosition: Int64;
7125 PixelSize, LineSize: Integer;
7126 tgaFormat: TglBitmapFormat;
7127 FormatDesc: TFormatDescriptor;
7128 Counter: packed record
7130 low, high, dir: Integer;
7137 ////////////////////////////////////////////////////////////////////////////////////////
7138 procedure ReadUncompressed;
7141 buf, tmp1, tmp2: System.PByte;
7144 if (Counter.X.dir < 0) then
7145 GetMem(buf, LineSize);
7147 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
7149 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
7150 if (Counter.X.dir < 0) then begin //flip X
7151 aStream.Read(buf^, LineSize);
7153 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
7154 for i := 0 to Header.Width-1 do begin //for all pixels in line
7155 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
7160 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
7163 aStream.Read(tmp1^, LineSize);
7164 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
7167 if Assigned(buf) then
7172 ////////////////////////////////////////////////////////////////////////////////////////
7173 procedure ReadCompressed;
7175 /////////////////////////////////////////////////////////////////
7177 TmpData: System.PByte;
7178 LinePixelsRead: Integer;
7179 procedure CheckLine;
7181 if (LinePixelsRead >= Header.Width) then begin
7182 LinePixelsRead := 0;
7183 inc(Counter.Y.low, Counter.Y.dir); //next line index
7184 TmpData := ImageData;
7185 inc(TmpData, Counter.Y.low * LineSize); //set line
7186 if (Counter.X.dir < 0) then //if x flipped then
7187 inc(TmpData, LineSize - PixelSize); //set last pixel
7191 /////////////////////////////////////////////////////////////////
7194 CacheSize, CachePos: Integer;
7195 procedure CachedRead(out Buffer; Count: Integer);
7199 if (CachePos + Count > CacheSize) then begin
7200 //if buffer overflow save non read bytes
7202 if (CacheSize - CachePos > 0) then begin
7203 BytesRead := CacheSize - CachePos;
7204 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
7205 inc(CachePos, BytesRead);
7208 //load cache from file
7209 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
7210 aStream.Read(Cache^, CacheSize);
7213 //read rest of requested bytes
7214 if (Count - BytesRead > 0) then begin
7215 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
7216 inc(CachePos, Count - BytesRead);
7219 //if no buffer overflow just read the data
7220 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
7221 inc(CachePos, Count);
7225 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
7230 inc(aBuffer, Counter.X.dir);
7233 PWord(aBuffer)^ := PWord(aData)^;
7234 inc(aBuffer, 2 * Counter.X.dir);
7237 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
7238 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
7239 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
7240 inc(aBuffer, 3 * Counter.X.dir);
7243 PCardinal(aBuffer)^ := PCardinal(aData)^;
7244 inc(aBuffer, 4 * Counter.X.dir);
7250 TotalPixelsToRead, TotalPixelsRead: Integer;
7252 buf: array [0..3] of Byte; //1 pixel is max 32bit long
7253 PixelRepeat: Boolean;
7254 PixelsToRead, PixelCount: Integer;
7259 TotalPixelsToRead := Header.Width * Header.Height;
7260 TotalPixelsRead := 0;
7261 LinePixelsRead := 0;
7263 GetMem(Cache, CACHE_SIZE);
7265 TmpData := ImageData;
7266 inc(TmpData, Counter.Y.low * LineSize); //set line
7267 if (Counter.X.dir < 0) then //if x flipped then
7268 inc(TmpData, LineSize - PixelSize); //set last pixel
7272 CachedRead(Temp, 1);
7273 PixelRepeat := (Temp and $80) > 0;
7274 PixelsToRead := (Temp and $7F) + 1;
7275 inc(TotalPixelsRead, PixelsToRead);
7278 CachedRead(buf[0], PixelSize);
7279 while (PixelsToRead > 0) do begin
7281 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
7282 while (PixelCount > 0) do begin
7283 if not PixelRepeat then
7284 CachedRead(buf[0], PixelSize);
7285 PixelToBuffer(@buf[0], TmpData);
7286 inc(LinePixelsRead);
7291 until (TotalPixelsRead >= TotalPixelsToRead);
7297 function IsGrayFormat: Boolean;
7299 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
7305 // reading header to test file and set cursor back to begin
7306 StartPosition := aStream.Position;
7307 aStream.Read(Header{%H-}, SizeOf(Header));
7309 // no colormapped files
7310 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
7311 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
7314 if Header.ImageID <> 0 then // skip image ID
7315 aStream.Position := aStream.Position + Header.ImageID;
7317 tgaFormat := tfEmpty;
7319 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
7320 0: tgaFormat := tfLuminance8;
7321 8: tgaFormat := tfAlpha8;
7324 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
7325 0: tgaFormat := tfLuminance16;
7326 8: tgaFormat := tfLuminance8Alpha8;
7327 end else case (Header.ImageDesc and $F) of
7328 0: tgaFormat := tfBGR5;
7329 1: tgaFormat := tfBGR5A1;
7330 4: tgaFormat := tfBGRA4;
7333 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7334 0: tgaFormat := tfBGR8;
7337 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7338 2: tgaFormat := tfBGR10A2;
7339 8: tgaFormat := tfBGRA8;
7343 if (tgaFormat = tfEmpty) then
7344 raise EglBitmap.Create('LoadTga - unsupported format');
7346 FormatDesc := TFormatDescriptor.Get(tgaFormat);
7347 PixelSize := FormatDesc.GetSize(1, 1);
7348 LineSize := FormatDesc.GetSize(Header.Width, 1);
7350 GetMem(ImageData, LineSize * Header.Height);
7353 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7354 Counter.X.low := Header.Height-1;;
7355 Counter.X.high := 0;
7356 Counter.X.dir := -1;
7359 Counter.X.high := Header.Height-1;
7364 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7366 Counter.Y.high := Header.Height-1;
7369 Counter.Y.low := Header.Height-1;;
7370 Counter.Y.high := 0;
7371 Counter.Y.dir := -1;
7375 case Header.ImageType of
7376 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7378 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7382 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method
7385 if Assigned(ImageData) then
7390 aStream.Position := StartPosition;
7393 else aStream.Position := StartPosition;
7396 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7397 procedure TglBitmap.SaveTGA(const aStream: TStream);
7400 LineSize, Size, x, y: Integer;
7401 Pixel: TglBitmapPixelData;
7402 LineBuf, SourceData, DestData: PByte;
7403 SourceMD, DestMD: Pointer;
7404 FormatDesc: TFormatDescriptor;
7405 Converter: TFormatDescriptor;
7407 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7408 raise EglBitmapUnsupportedFormat.Create(Format);
7411 FillChar(Header{%H-}, SizeOf(Header), 0);
7414 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7415 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7416 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7418 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7421 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7423 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7424 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7426 else if (Format in [tfBGR8, tfRGB8]) then
7434 Header.ImageDesc := 1 and $F;
7435 tfRGB10A2, tfBGR10A2:
7436 Header.ImageDesc := 2 and $F;
7438 Header.ImageDesc := 4 and $F;
7439 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7440 Header.ImageDesc := 8 and $F;
7443 Header.Width := Width;
7444 Header.Height := Height;
7445 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7446 aStream.Write(Header, SizeOf(Header));
7448 // convert RGB(A) to BGR(A)
7450 FormatDesc := TFormatDescriptor.Get(Format);
7451 Size := FormatDesc.GetSize(Dimension);
7452 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7453 if (FormatDesc.RGBInverted = tfEmpty) then
7454 raise EglBitmap.Create('inverted RGB format is empty');
7455 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7456 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7457 (Converter.PixelSize <> FormatDesc.PixelSize) then
7458 raise EglBitmap.Create('invalid inverted RGB format');
7461 if Assigned(Converter) then begin
7462 LineSize := FormatDesc.GetSize(Width, 1);
7463 GetMem(LineBuf, LineSize);
7464 SourceMD := FormatDesc.CreateMappingData;
7465 DestMD := Converter.CreateMappingData;
7468 for y := 0 to Height-1 do begin
7469 DestData := LineBuf;
7470 for x := 0 to Width-1 do begin
7471 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7472 Converter.Map(Pixel, DestData, DestMD);
7474 aStream.Write(LineBuf^, LineSize);
7478 FormatDesc.FreeMappingData(SourceMD);
7479 FormatDesc.FreeMappingData(DestMD);
7482 aStream.Write(Data^, Size);
7485 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7486 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7487 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7489 DDS_MAGIC: Cardinal = $20534444;
7491 // DDS_header.dwFlags
7492 DDSD_CAPS = $00000001;
7493 DDSD_HEIGHT = $00000002;
7494 DDSD_WIDTH = $00000004;
7495 DDSD_PIXELFORMAT = $00001000;
7497 // DDS_header.sPixelFormat.dwFlags
7498 DDPF_ALPHAPIXELS = $00000001;
7499 DDPF_ALPHA = $00000002;
7500 DDPF_FOURCC = $00000004;
7501 DDPF_RGB = $00000040;
7502 DDPF_LUMINANCE = $00020000;
7504 // DDS_header.sCaps.dwCaps1
7505 DDSCAPS_TEXTURE = $00001000;
7507 // DDS_header.sCaps.dwCaps2
7508 DDSCAPS2_CUBEMAP = $00000200;
7510 D3DFMT_DXT1 = $31545844;
7511 D3DFMT_DXT3 = $33545844;
7512 D3DFMT_DXT5 = $35545844;
7515 TDDSPixelFormat = packed record
7519 dwRGBBitCount: Cardinal;
7520 dwRBitMask: Cardinal;
7521 dwGBitMask: Cardinal;
7522 dwBBitMask: Cardinal;
7523 dwABitMask: Cardinal;
7526 TDDSCaps = packed record
7530 dwReserved: Cardinal;
7533 TDDSHeader = packed record
7538 dwPitchOrLinearSize: Cardinal;
7540 dwMipMapCount: Cardinal;
7541 dwReserved: array[0..10] of Cardinal;
7542 PixelFormat: TDDSPixelFormat;
7544 dwReserved2: Cardinal;
7547 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7548 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7551 Converter: TbmpBitfieldFormat;
7553 function GetDDSFormat: TglBitmapFormat;
7555 fd: TFormatDescriptor;
7557 Range: TglBitmapColorRec;
7561 with Header.PixelFormat do begin
7563 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7564 case Header.PixelFormat.dwFourCC of
7565 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7566 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7567 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7569 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7571 //find matching format
7572 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7573 fd := TFormatDescriptor.Get(result);
7574 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7575 (8 * fd.PixelSize = dwRGBBitCount) then
7579 //find format with same Range
7580 Range.r := dwRBitMask;
7581 Range.g := dwGBitMask;
7582 Range.b := dwBBitMask;
7583 Range.a := dwABitMask;
7584 for i := 0 to 3 do begin
7585 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7586 Range.arr[i] := Range.arr[i] shr 1;
7588 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7589 fd := TFormatDescriptor.Get(result);
7592 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7600 //no format with same range found -> use default
7601 if (result = tfEmpty) then begin
7602 if (dwABitMask > 0) then
7608 Converter := TbmpBitfieldFormat.Create;
7609 Converter.RedMask := dwRBitMask;
7610 Converter.GreenMask := dwGBitMask;
7611 Converter.BlueMask := dwBBitMask;
7612 Converter.AlphaMask := dwABitMask;
7613 Converter.PixelSize := dwRGBBitCount / 8;
7620 x, y, LineSize, RowSize, Magic: Cardinal;
7621 NewImage, TmpData, RowData, SrcData: System.PByte;
7622 SourceMD, DestMD: Pointer;
7623 Pixel: TglBitmapPixelData;
7624 ddsFormat: TglBitmapFormat;
7625 FormatDesc: TFormatDescriptor;
7630 StreamPos := aStream.Position;
7633 aStream.Read(Magic{%H-}, sizeof(Magic));
7634 if (Magic <> DDS_MAGIC) then begin
7635 aStream.Position := StreamPos;
7640 aStream.Read(Header{%H-}, sizeof(Header));
7641 if (Header.dwSize <> SizeOf(Header)) or
7642 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7643 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7645 aStream.Position := StreamPos;
7649 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7650 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
7652 ddsFormat := GetDDSFormat;
7654 if (ddsFormat = tfEmpty) then
7655 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7657 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7658 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7659 GetMem(NewImage, Header.dwHeight * LineSize);
7661 TmpData := NewImage;
7664 if Assigned(Converter) then begin
7665 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7666 GetMem(RowData, RowSize);
7667 SourceMD := Converter.CreateMappingData;
7668 DestMD := FormatDesc.CreateMappingData;
7670 for y := 0 to Header.dwHeight-1 do begin
7671 TmpData := NewImage;
7672 inc(TmpData, y * LineSize);
7674 aStream.Read(SrcData^, RowSize);
7675 for x := 0 to Header.dwWidth-1 do begin
7676 Converter.Unmap(SrcData, Pixel, SourceMD);
7677 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7678 FormatDesc.Map(Pixel, TmpData, DestMD);
7682 Converter.FreeMappingData(SourceMD);
7683 FormatDesc.FreeMappingData(DestMD);
7689 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7690 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7691 for Y := 0 to Header.dwHeight-1 do begin
7692 aStream.Read(TmpData^, RowSize);
7693 Inc(TmpData, LineSize);
7698 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7699 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7700 for Y := 0 to Header.dwHeight-1 do begin
7701 aStream.Read(TmpData^, RowSize);
7702 Inc(TmpData, LineSize);
7705 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7707 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method
7710 if Assigned(NewImage) then
7715 FreeAndNil(Converter);
7719 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7720 procedure TglBitmap.SaveDDS(const aStream: TStream);
7723 FormatDesc: TFormatDescriptor;
7725 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7726 raise EglBitmapUnsupportedFormat.Create(Format);
7728 FormatDesc := TFormatDescriptor.Get(Format);
7731 FillChar(Header{%H-}, SizeOf(Header), 0);
7732 Header.dwSize := SizeOf(Header);
7733 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7735 Header.dwWidth := Max(1, Width);
7736 Header.dwHeight := Max(1, Height);
7739 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7742 Header.PixelFormat.dwSize := sizeof(Header);
7743 if (FormatDesc.IsCompressed) then begin
7744 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7746 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7747 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7748 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7750 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7751 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7752 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7753 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7754 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7755 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7756 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7757 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7758 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7760 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7761 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7762 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7763 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7764 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7765 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7768 if (FormatDesc.HasAlpha) then
7769 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7771 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7772 aStream.Write(Header, SizeOf(Header));
7773 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7776 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7777 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7778 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7779 procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7780 const aWidth: Integer; const aHeight: Integer);
7785 if (aHeight > 1) then begin
7786 Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1);
7787 GetMem(pTemp, Size);
7789 Move(aData^, pTemp^, Size);
7798 inherited SetDataPointer(pTemp, aFormat, aWidth);
7801 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7802 function TglBitmap1D.FlipHorz: Boolean;
7805 pTempDest, pDest, pSource: PByte;
7807 result := inherited FlipHorz;
7808 if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin
7810 GetMem(pDest, fRowSize);
7813 Inc(pTempDest, fRowSize);
7814 for Col := 0 to Width-1 do begin
7815 dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data
7816 Move(pSource^, pTempDest^, fPixelSize);
7817 Inc(pSource, fPixelSize);
7819 SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method
7822 if Assigned(pDest) then
7829 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7830 procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean);
7832 FormatDesc: TFormatDescriptor;
7835 FormatDesc := TFormatDescriptor.Get(Format);
7836 if FormatDesc.IsCompressed then begin
7837 if not Assigned(glCompressedTexImage1D) then
7838 raise EglBitmap.Create('compressed formats not supported by video adapter');
7839 glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
7840 end else if aBuildWithGlu then
7841 gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7843 glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7846 if (FreeDataAfterGenTexture) then
7850 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7851 procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean);
7853 BuildWithGlu, TexRec: Boolean;
7856 if Assigned(Data) then begin
7857 // Check Texture Size
7858 if (aTestTextureSize) then begin
7859 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7861 if (Width > TexSize) then
7862 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7864 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7865 (Target = GL_TEXTURE_RECTANGLE);
7866 if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7867 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7871 SetupParameters(BuildWithGlu);
7872 UploadData(BuildWithGlu);
7873 glAreTexturesResident(1, @fID, @fIsResident);
7877 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7878 procedure TglBitmap1D.AfterConstruction;
7881 Target := GL_TEXTURE_1D;
7884 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7885 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7886 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7887 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7889 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7890 result := fLines[aIndex]
7895 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7896 procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7897 const aWidth: Integer; const aHeight: Integer);
7899 Idx, LineWidth: Integer;
7901 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7903 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7905 if Assigned(Data) then begin
7906 SetLength(fLines, GetHeight);
7907 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7909 for Idx := 0 to GetHeight-1 do begin
7910 fLines[Idx] := Data;
7911 Inc(fLines[Idx], Idx * LineWidth);
7914 else SetLength(fLines, 0);
7916 SetLength(fLines, 0);
7920 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7921 procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
7923 FormatDesc: TFormatDescriptor;
7925 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7927 FormatDesc := TFormatDescriptor.Get(Format);
7928 if FormatDesc.IsCompressed then begin
7929 if not Assigned(glCompressedTexImage2D) then
7930 raise EglBitmap.Create('compressed formats not supported by video adapter');
7931 glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7932 end else if aBuildWithGlu then begin
7933 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7934 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7936 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7937 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7941 if (FreeDataAfterGenTexture) then
7945 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7946 procedure TglBitmap2D.AfterConstruction;
7949 Target := GL_TEXTURE_2D;
7952 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7953 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7956 Size, w, h: Integer;
7957 FormatDesc: TFormatDescriptor;
7959 FormatDesc := TFormatDescriptor.Get(aFormat);
7960 if FormatDesc.IsCompressed then
7961 raise EglBitmapUnsupportedFormat.Create(aFormat);
7963 w := aRight - aLeft;
7964 h := aBottom - aTop;
7965 Size := FormatDesc.GetSize(w, h);
7968 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7969 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7970 SetDataPointer(Temp, aFormat, w, h); //be careful, Data could be freed by this method
7973 if Assigned(Temp) then
7979 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7980 procedure TglBitmap2D.GetDataFromTexture;
7983 TempWidth, TempHeight: Integer;
7984 TempIntFormat: Cardinal;
7985 IntFormat, f: TglBitmapFormat;
7986 FormatDesc: TFormatDescriptor;
7991 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7992 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7993 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7995 IntFormat := tfEmpty;
7996 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
7997 FormatDesc := TFormatDescriptor.Get(f);
7998 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
7999 IntFormat := FormatDesc.Format;
8004 // Getting data from OpenGL
8005 FormatDesc := TFormatDescriptor.Get(IntFormat);
8006 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
8008 if FormatDesc.IsCompressed then begin
8009 if not Assigned(glGetCompressedTexImage) then
8010 raise EglBitmap.Create('compressed formats not supported by video adapter');
8011 glGetCompressedTexImage(Target, 0, Temp)
8013 glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8014 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
8016 if Assigned(Temp) then
8022 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8023 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
8025 BuildWithGlu, PotTex, TexRec: Boolean;
8028 if Assigned(Data) then begin
8029 // Check Texture Size
8030 if (aTestTextureSize) then begin
8031 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8033 if ((Height > TexSize) or (Width > TexSize)) then
8034 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8036 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
8037 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
8038 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8039 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8043 SetupParameters(BuildWithGlu);
8044 UploadData(Target, BuildWithGlu);
8045 glAreTexturesResident(1, @fID, @fIsResident);
8049 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8050 function TglBitmap2D.FlipHorz: Boolean;
8053 TempDestData, DestData, SourceData: PByte;
8056 result := inherited FlipHorz;
8057 if Assigned(Data) then begin
8059 ImgSize := Height * fRowSize;
8060 GetMem(DestData, ImgSize);
8062 TempDestData := DestData;
8063 Dec(TempDestData, fRowSize + fPixelSize);
8064 for Row := 0 to Height -1 do begin
8065 Inc(TempDestData, fRowSize * 2);
8066 for Col := 0 to Width -1 do begin
8067 Move(SourceData^, TempDestData^, fPixelSize);
8068 Inc(SourceData, fPixelSize);
8069 Dec(TempDestData, fPixelSize);
8072 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8075 if Assigned(DestData) then
8082 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8083 function TglBitmap2D.FlipVert: Boolean;
8086 TempDestData, DestData, SourceData: PByte;
8088 result := inherited FlipVert;
8089 if Assigned(Data) then begin
8091 GetMem(DestData, Height * fRowSize);
8093 TempDestData := DestData;
8094 Inc(TempDestData, Width * (Height -1) * fPixelSize);
8095 for Row := 0 to Height -1 do begin
8096 Move(SourceData^, TempDestData^, fRowSize);
8097 Dec(TempDestData, fRowSize);
8098 Inc(SourceData, fRowSize);
8100 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8103 if Assigned(DestData) then
8110 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8111 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8112 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8114 TMatrixItem = record
8119 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
8120 TglBitmapToNormalMapRec = Record
8122 Heights: array of Single;
8123 MatrixU : array of TMatrixItem;
8124 MatrixV : array of TMatrixItem;
8128 ONE_OVER_255 = 1 / 255;
8130 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8131 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
8135 with FuncRec do begin
8137 Source.Data.r * LUMINANCE_WEIGHT_R +
8138 Source.Data.g * LUMINANCE_WEIGHT_G +
8139 Source.Data.b * LUMINANCE_WEIGHT_B;
8140 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
8144 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8145 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
8148 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
8151 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8152 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
8154 TVec = Array[0..2] of Single;
8161 function GetHeight(X, Y: Integer): Single;
8163 with FuncRec do begin
8164 X := Max(0, Min(Size.X -1, X));
8165 Y := Max(0, Min(Size.Y -1, Y));
8166 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
8171 with FuncRec do begin
8172 with PglBitmapToNormalMapRec(Args)^ do begin
8174 for Idx := Low(MatrixU) to High(MatrixU) do
8175 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
8178 for Idx := Low(MatrixU) to High(MatrixU) do
8179 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
8181 Vec[0] := -du * Scale;
8182 Vec[1] := -dv * Scale;
8187 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8188 if Len <> 0 then begin
8189 Vec[0] := Vec[0] * Len;
8190 Vec[1] := Vec[1] * Len;
8191 Vec[2] := Vec[2] * Len;
8195 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
8196 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
8197 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
8201 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8202 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
8204 Rec: TglBitmapToNormalMapRec;
8206 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
8208 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
8209 Matrix[Index].X := X;
8210 Matrix[Index].Y := Y;
8211 Matrix[Index].W := W;
8216 if TFormatDescriptor.Get(Format).IsCompressed then
8217 raise EglBitmapUnsupportedFormat.Create(Format);
8219 if aScale > 100 then
8221 else if aScale < -100 then
8224 Rec.Scale := aScale;
8226 SetLength(Rec.Heights, Width * Height);
8230 SetLength(Rec.MatrixU, 2);
8231 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
8232 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
8234 SetLength(Rec.MatrixV, 2);
8235 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
8236 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
8240 SetLength(Rec.MatrixU, 6);
8241 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
8242 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
8243 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
8244 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
8245 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
8246 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
8248 SetLength(Rec.MatrixV, 6);
8249 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
8250 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
8251 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
8252 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
8253 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
8254 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
8258 SetLength(Rec.MatrixU, 6);
8259 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
8260 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
8261 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
8262 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
8263 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
8264 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
8266 SetLength(Rec.MatrixV, 6);
8267 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
8268 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
8269 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
8270 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
8271 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
8272 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
8276 SetLength(Rec.MatrixU, 20);
8277 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
8278 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
8279 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
8280 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
8281 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
8282 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
8283 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
8284 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
8285 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
8286 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
8287 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
8288 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
8289 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
8290 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
8291 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
8292 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
8293 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
8294 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
8295 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
8296 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
8298 SetLength(Rec.MatrixV, 20);
8299 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
8300 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
8301 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
8302 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
8303 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
8304 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
8305 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
8306 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
8307 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
8308 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
8309 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
8310 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
8311 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
8312 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
8313 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
8314 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
8315 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
8316 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
8317 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
8318 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
8323 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
8324 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
8326 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
8327 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
8329 SetLength(Rec.Heights, 0);
8333 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8334 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8335 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8336 procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean);
8338 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8341 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8342 procedure TglBitmapCubeMap.AfterConstruction;
8346 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8347 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8350 Target := GL_TEXTURE_CUBE_MAP;
8351 fGenMode := GL_REFLECTION_MAP;
8354 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8355 procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean);
8357 BuildWithGlu: Boolean;
8360 if (aTestTextureSize) then begin
8361 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8363 if (Height > TexSize) or (Width > TexSize) then
8364 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8366 if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8367 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8372 SetupParameters(BuildWithGlu);
8373 UploadData(aCubeTarget, BuildWithGlu);
8376 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8377 procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean);
8379 inherited Bind (aEnableTextureUnit);
8380 if aEnableTexCoordsGen then begin
8381 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8382 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8383 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8384 glEnable(GL_TEXTURE_GEN_S);
8385 glEnable(GL_TEXTURE_GEN_T);
8386 glEnable(GL_TEXTURE_GEN_R);
8390 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8391 procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean);
8393 inherited Unbind(aDisableTextureUnit);
8394 if aDisableTexCoordsGen then begin
8395 glDisable(GL_TEXTURE_GEN_S);
8396 glDisable(GL_TEXTURE_GEN_T);
8397 glDisable(GL_TEXTURE_GEN_R);
8401 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8402 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8403 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8405 TVec = Array[0..2] of Single;
8406 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8408 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8409 TglBitmapNormalMapRec = record
8411 Func: TglBitmapNormalMapGetVectorFunc;
8414 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8415 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8417 aVec[0] := aHalfSize;
8418 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8419 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8422 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8423 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8425 aVec[0] := - aHalfSize;
8426 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8427 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8430 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8431 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8433 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8434 aVec[1] := aHalfSize;
8435 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8438 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8439 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8441 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8442 aVec[1] := - aHalfSize;
8443 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8446 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8447 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8449 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8450 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8451 aVec[2] := aHalfSize;
8454 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8455 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8457 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8458 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8459 aVec[2] := - aHalfSize;
8462 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8463 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8469 with FuncRec do begin
8470 with PglBitmapNormalMapRec(Args)^ do begin
8471 Func(Vec, Position, HalfSize);
8474 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8475 if Len <> 0 then begin
8476 Vec[0] := Vec[0] * Len;
8477 Vec[1] := Vec[1] * Len;
8478 Vec[2] := Vec[2] * Len;
8481 // Scale Vector and AddVectro
8482 Vec[0] := Vec[0] * 0.5 + 0.5;
8483 Vec[1] := Vec[1] * 0.5 + 0.5;
8484 Vec[2] := Vec[2] * 0.5 + 0.5;
8489 Dest.Data.arr[i] := Round(Vec[i] * 255);
8493 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8494 procedure TglBitmapNormalMap.AfterConstruction;
8497 fGenMode := GL_NORMAL_MAP;
8500 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8501 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean);
8503 Rec: TglBitmapNormalMapRec;
8504 SizeRec: TglBitmapPixelPosition;
8506 Rec.HalfSize := aSize div 2;
8507 FreeDataAfterGenTexture := false;
8509 SizeRec.Fields := [ffX, ffY];
8514 Rec.Func := glBitmapNormalMapPosX;
8515 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8516 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize);
8519 Rec.Func := glBitmapNormalMapNegX;
8520 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8521 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize);
8524 Rec.Func := glBitmapNormalMapPosY;
8525 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8526 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize);
8529 Rec.Func := glBitmapNormalMapNegY;
8530 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8531 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize);
8534 Rec.Func := glBitmapNormalMapPosZ;
8535 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8536 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize);
8539 Rec.Func := glBitmapNormalMapNegZ;
8540 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8541 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize);
8546 glBitmapSetDefaultFormat (tfEmpty);
8547 glBitmapSetDefaultMipmap (mmMipmap);
8548 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8549 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8550 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8552 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8553 glBitmapSetDefaultDeleteTextureOnFree (true);
8555 TFormatDescriptor.Init;
8557 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8558 OpenGLInitialized := false;
8559 InitOpenGLCS := TCriticalSection.Create;
8563 TFormatDescriptor.Finalize;
8565 {$IFDEF GLB_NATIVE_OGL}
8566 if Assigned(GL_LibHandle) then
8567 glbFreeLibrary(GL_LibHandle);
8569 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8570 if Assigned(GLU_LibHandle) then
8571 glbFreeLibrary(GLU_LibHandle);
8572 FreeAndNil(InitOpenGLCS);