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 GetHasRed: Boolean; virtual; abstract;
893 function GetHasGreen: Boolean; virtual; abstract;
894 function GetHasBlue: Boolean; virtual; abstract;
895 function GetHasAlpha: Boolean; virtual; abstract;
897 function GetglDataFormat: GLenum; virtual; abstract;
898 function GetglFormat: GLenum; virtual; abstract;
899 function GetglInternalFormat: GLenum; virtual; abstract;
901 property IsCompressed: Boolean read GetIsCompressed;
902 property HasRed: Boolean read GetHasRed;
903 property HasGreen: Boolean read GetHasGreen;
904 property HasBlue: Boolean read GetHasBlue;
905 property HasAlpha: Boolean read GetHasAlpha;
907 property glFormat: GLenum read GetglFormat;
908 property glInternalFormat: GLenum read GetglInternalFormat;
909 property glDataFormat: GLenum read GetglDataFormat;
912 ////////////////////////////////////////////////////////////////////////////////////////////////////
914 TglBitmapFunctionRec = record
916 Size: TglBitmapPixelPosition;
917 Position: TglBitmapPixelPosition;
918 Source: TglBitmapPixelData;
919 Dest: TglBitmapPixelData;
922 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
924 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
927 function GetFormatDesc: TglBitmapFormatDescriptor;
931 fAnisotropic: Integer;
932 fDeleteTextureOnFree: Boolean;
933 fFreeDataOnDestroy: Boolean;
934 fFreeDataAfterGenTexture: Boolean;
936 fIsResident: GLboolean;
937 fBorderColor: array[0..3] of Single;
939 fDimension: TglBitmapPixelPosition;
940 fMipMap: TglBitmapMipMap;
941 fFormat: TglBitmapFormat;
957 fSwizzle: array[0..3] of GLenum;
962 fCustomNameW: WideString;
963 fCustomData: Pointer;
966 function GetWidth: Integer; virtual;
967 function GetHeight: Integer; virtual;
969 function GetFileWidth: Integer; virtual;
970 function GetFileHeight: Integer; virtual;
973 procedure SetCustomData(const aValue: Pointer);
974 procedure SetCustomName(const aValue: String);
975 procedure SetCustomNameW(const aValue: WideString);
976 procedure SetFreeDataOnDestroy(const aValue: Boolean);
977 procedure SetDeleteTextureOnFree(const aValue: Boolean);
978 procedure SetFormat(const aValue: TglBitmapFormat);
979 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
980 procedure SetID(const aValue: Cardinal);
981 procedure SetMipMap(const aValue: TglBitmapMipMap);
982 procedure SetTarget(const aValue: Cardinal);
983 procedure SetAnisotropic(const aValue: Integer);
986 procedure SetupParameters(out aBuildWithGlu: Boolean);
987 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
988 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; //be careful, aData could be freed by this method
989 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
991 function FlipHorz: Boolean; virtual;
992 function FlipVert: Boolean; virtual;
994 property Width: Integer read GetWidth;
995 property Height: Integer read GetHeight;
997 property FileWidth: Integer read GetFileWidth;
998 property FileHeight: Integer read GetFileHeight;
1001 property ID: Cardinal read fID write SetID;
1002 property Target: Cardinal read fTarget write SetTarget;
1003 property Format: TglBitmapFormat read fFormat write SetFormat;
1004 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
1005 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
1007 property FormatDesc: TglBitmapFormatDescriptor read GetFormatDesc;
1009 property Filename: String read fFilename;
1010 property CustomName: String read fCustomName write SetCustomName;
1011 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
1012 property CustomData: Pointer read fCustomData write SetCustomData;
1014 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
1015 property FreeDataOnDestroy: Boolean read fFreeDataOnDestroy write SetFreeDataOnDestroy;
1016 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
1018 property Dimension: TglBitmapPixelPosition read fDimension;
1019 property Data: PByte read fData;
1020 property IsResident: GLboolean read fIsResident;
1022 procedure AfterConstruction; override;
1023 procedure BeforeDestruction; override;
1025 procedure PrepareResType(var aResource: String; var aResType: PChar);
1028 procedure LoadFromFile(const aFilename: String);
1029 procedure LoadFromStream(const aStream: TStream); virtual;
1030 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
1031 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil);
1032 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil);
1033 procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
1036 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
1037 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
1040 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
1041 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
1042 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
1046 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
1047 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
1048 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
1049 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
1050 const aArgs: Pointer = nil): Boolean;
1054 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
1055 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
1056 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
1057 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
1058 const aArgs: Pointer = nil): Boolean;
1061 {$IFDEF GLB_LAZARUS}
1062 function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1063 function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
1064 function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1065 function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil;
1066 const aArgs: Pointer = nil): Boolean;
1069 function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil;
1070 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1071 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
1072 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1074 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
1075 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1076 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1077 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1079 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
1080 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
1081 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
1083 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
1084 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
1085 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
1087 function RemoveAlpha: Boolean; virtual;
1090 function Clone: TglBitmap;
1091 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
1092 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
1093 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
1097 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
1098 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
1099 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
1102 procedure SetFilter(const aMin, aMag: GLenum);
1104 const S: GLenum = GL_CLAMP_TO_EDGE;
1105 const T: GLenum = GL_CLAMP_TO_EDGE;
1106 const R: GLenum = GL_CLAMP_TO_EDGE);
1107 procedure SetSwizzle(const r, g, b, a: GLenum);
1109 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
1110 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
1113 constructor Create; overload;
1114 constructor Create(const aFileName: String); overload;
1115 constructor Create(const aStream: TStream); overload;
1116 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte = nil); overload;
1117 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
1118 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
1119 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
1121 {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1122 {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF}
1124 {$IFDEF GLB_SUPPORT_JPEG_READ} function LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1125 {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF}
1127 function LoadBMP(const aStream: TStream): Boolean; virtual;
1128 procedure SaveBMP(const aStream: TStream); virtual;
1130 function LoadTGA(const aStream: TStream): Boolean; virtual;
1131 procedure SaveTGA(const aStream: TStream); virtual;
1133 function LoadDDS(const aStream: TStream): Boolean; virtual;
1134 procedure SaveDDS(const aStream: TStream); virtual;
1137 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1138 TglBitmap1D = class(TglBitmap)
1140 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1141 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1142 procedure UploadData(const aBuildWithGlu: Boolean);
1145 procedure AfterConstruction; override;
1146 function FlipHorz: Boolean; override;
1147 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1150 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1151 TglBitmap2D = class(TglBitmap)
1153 fLines: array of PByte;
1154 function GetScanline(const aIndex: Integer): Pointer;
1155 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1156 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1157 procedure UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
1161 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
1163 procedure AfterConstruction; override;
1165 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
1166 procedure GetDataFromTexture;
1167 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1169 function FlipHorz: Boolean; override;
1170 function FlipVert: Boolean; override;
1172 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
1173 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1176 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1177 TglBitmapCubeMap = class(TglBitmap2D)
1180 procedure GenTexture(const aTestTextureSize: Boolean = true); reintroduce;
1182 procedure AfterConstruction; override;
1183 procedure GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean = true);
1184 procedure Bind(const aEnableTexCoordsGen: Boolean = true; const aEnableTextureUnit: Boolean = true); reintroduce; virtual;
1185 procedure Unbind(const aDisableTexCoordsGen: Boolean = true; const aDisableTextureUnit: Boolean = true); reintroduce; virtual;
1188 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1189 TglBitmapNormalMap = class(TglBitmapCubeMap)
1191 procedure AfterConstruction; override;
1192 procedure GenerateNormalMap(const aSize: Integer = 32; const aTestTextureSize: Boolean = true);
1196 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1198 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1199 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1200 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1201 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1202 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1203 procedure glBitmapSetDefaultWrap(
1204 const S: Cardinal = GL_CLAMP_TO_EDGE;
1205 const T: Cardinal = GL_CLAMP_TO_EDGE;
1206 const R: Cardinal = GL_CLAMP_TO_EDGE);
1208 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1209 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1210 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1211 function glBitmapGetDefaultFormat: TglBitmapFormat;
1212 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1213 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1215 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1216 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1217 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1220 glBitmapDefaultDeleteTextureOnFree: Boolean;
1221 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1222 glBitmapDefaultFormat: TglBitmapFormat;
1223 glBitmapDefaultMipmap: TglBitmapMipMap;
1224 glBitmapDefaultFilterMin: Cardinal;
1225 glBitmapDefaultFilterMag: Cardinal;
1226 glBitmapDefaultWrapS: Cardinal;
1227 glBitmapDefaultWrapT: Cardinal;
1228 glBitmapDefaultWrapR: Cardinal;
1229 glDefaultSwizzle: array[0..3] of GLenum;
1232 function CreateGrayPalette: HPALETTE;
1238 Math, syncobjs, typinfo
1239 {$IFDEF GLB_DELPHI}, Types{$ENDIF}
1240 {$IF DEFINED(GLB_SUPPORT_JPEG_READ) AND DEFINED(GLB_LAZ_JPEG)}, FPReadJPEG{$IFEND};
1244 QWord = System.UInt64;
1251 ////////////////////////////////////////////////////////////////////////////////////////////////////
1252 TShiftRec = packed record
1254 0: (r, g, b, a: Byte);
1255 1: (arr: array[0..3] of Byte);
1258 TFormatDescriptor = class(TglBitmapFormatDescriptor)
1260 function GetRedMask: QWord;
1261 function GetGreenMask: QWord;
1262 function GetBlueMask: QWord;
1263 function GetAlphaMask: QWord;
1265 fFormat: TglBitmapFormat;
1266 fWithAlpha: TglBitmapFormat;
1267 fWithoutAlpha: TglBitmapFormat;
1268 fRGBInverted: TglBitmapFormat;
1269 fUncompressed: TglBitmapFormat;
1271 fIsCompressed: Boolean;
1273 fRange: TglBitmapColorRec;
1277 fglInternalFormat: GLenum;
1278 fglDataFormat: GLenum;
1280 function GetIsCompressed: Boolean; override;
1281 function GetHasRed: Boolean; override;
1282 function GetHasGreen: Boolean; override;
1283 function GetHasBlue: Boolean; override;
1284 function GetHasAlpha: Boolean; override;
1286 function GetglFormat: GLenum; override;
1287 function GetglInternalFormat: GLenum; override;
1288 function GetglDataFormat: GLenum; override;
1290 function GetComponents: Integer; virtual;
1292 property Format: TglBitmapFormat read fFormat;
1293 property WithAlpha: TglBitmapFormat read fWithAlpha;
1294 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1295 property RGBInverted: TglBitmapFormat read fRGBInverted;
1296 property Components: Integer read GetComponents;
1297 property PixelSize: Single read fPixelSize;
1299 property Range: TglBitmapColorRec read fRange;
1300 property Shift: TShiftRec read fShift;
1302 property RedMask: QWord read GetRedMask;
1303 property GreenMask: QWord read GetGreenMask;
1304 property BlueMask: QWord read GetBlueMask;
1305 property AlphaMask: QWord read GetAlphaMask;
1307 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1308 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1310 function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual;
1311 function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
1313 function CreateMappingData: Pointer; virtual;
1314 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1316 function IsEmpty: Boolean; virtual;
1317 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual;
1319 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1321 constructor Create; virtual;
1323 class procedure Init;
1324 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1325 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1326 class procedure Clear;
1327 class procedure Finalize;
1329 TFormatDescriptorClass = class of TFormatDescriptor;
1331 TfdEmpty = class(TFormatDescriptor);
1333 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1334 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1335 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1336 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1337 constructor Create; override;
1340 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1341 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1342 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1343 constructor Create; override;
1346 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1347 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1348 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1349 constructor Create; override;
1352 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1353 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1354 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1355 constructor Create; override;
1358 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1359 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1360 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1361 constructor Create; override;
1364 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1365 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1366 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1367 constructor Create; override;
1370 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
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 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
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 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1383 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1384 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1385 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1386 constructor Create; override;
1389 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1390 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1391 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1392 constructor Create; override;
1395 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1396 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1397 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1398 constructor Create; override;
1401 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1402 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1403 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1404 constructor Create; override;
1407 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1408 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1409 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1410 constructor Create; override;
1413 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1414 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1415 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1416 constructor Create; override;
1419 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1420 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1421 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1422 constructor Create; override;
1425 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
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 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
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 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1439 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1440 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1441 constructor Create; override;
1444 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1445 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1446 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1447 constructor Create; override;
1450 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1451 TfdAlpha4 = class(TfdAlpha_UB1)
1452 constructor Create; override;
1455 TfdAlpha8 = class(TfdAlpha_UB1)
1456 constructor Create; override;
1459 TfdAlpha12 = class(TfdAlpha_US1)
1460 constructor Create; override;
1463 TfdAlpha16 = class(TfdAlpha_US1)
1464 constructor Create; override;
1467 TfdLuminance4 = class(TfdLuminance_UB1)
1468 constructor Create; override;
1471 TfdLuminance8 = class(TfdLuminance_UB1)
1472 constructor Create; override;
1475 TfdLuminance12 = class(TfdLuminance_US1)
1476 constructor Create; override;
1479 TfdLuminance16 = class(TfdLuminance_US1)
1480 constructor Create; override;
1483 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1484 constructor Create; override;
1487 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1488 constructor Create; override;
1491 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1492 constructor Create; override;
1495 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1496 constructor Create; override;
1499 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1500 constructor Create; override;
1503 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1504 constructor Create; override;
1507 TfdR3G3B2 = class(TfdUniversal_UB1)
1508 constructor Create; override;
1511 TfdRGB4 = class(TfdUniversal_US1)
1512 constructor Create; override;
1515 TfdR5G6B5 = class(TfdUniversal_US1)
1516 constructor Create; override;
1519 TfdRGB5 = class(TfdUniversal_US1)
1520 constructor Create; override;
1523 TfdRGB8 = class(TfdRGB_UB3)
1524 constructor Create; override;
1527 TfdRGB10 = class(TfdUniversal_UI1)
1528 constructor Create; override;
1531 TfdRGB12 = class(TfdRGB_US3)
1532 constructor Create; override;
1535 TfdRGB16 = class(TfdRGB_US3)
1536 constructor Create; override;
1539 TfdRGBA2 = class(TfdRGBA_UB4)
1540 constructor Create; override;
1543 TfdRGBA4 = class(TfdUniversal_US1)
1544 constructor Create; override;
1547 TfdRGB5A1 = class(TfdUniversal_US1)
1548 constructor Create; override;
1551 TfdRGBA8 = class(TfdRGBA_UB4)
1552 constructor Create; override;
1555 TfdRGB10A2 = class(TfdUniversal_UI1)
1556 constructor Create; override;
1559 TfdRGBA12 = class(TfdRGBA_US4)
1560 constructor Create; override;
1563 TfdRGBA16 = class(TfdRGBA_US4)
1564 constructor Create; override;
1567 TfdBGR4 = class(TfdUniversal_US1)
1568 constructor Create; override;
1571 TfdB5G6R5 = class(TfdUniversal_US1)
1572 constructor Create; override;
1575 TfdBGR5 = class(TfdUniversal_US1)
1576 constructor Create; override;
1579 TfdBGR8 = class(TfdBGR_UB3)
1580 constructor Create; override;
1583 TfdBGR10 = class(TfdUniversal_UI1)
1584 constructor Create; override;
1587 TfdBGR12 = class(TfdBGR_US3)
1588 constructor Create; override;
1591 TfdBGR16 = class(TfdBGR_US3)
1592 constructor Create; override;
1595 TfdBGRA2 = class(TfdBGRA_UB4)
1596 constructor Create; override;
1599 TfdBGRA4 = class(TfdUniversal_US1)
1600 constructor Create; override;
1603 TfdBGR5A1 = class(TfdUniversal_US1)
1604 constructor Create; override;
1607 TfdBGRA8 = class(TfdBGRA_UB4)
1608 constructor Create; override;
1611 TfdBGR10A2 = class(TfdUniversal_UI1)
1612 constructor Create; override;
1615 TfdBGRA12 = class(TfdBGRA_US4)
1616 constructor Create; override;
1619 TfdBGRA16 = class(TfdBGRA_US4)
1620 constructor Create; override;
1623 TfdDepth16 = class(TfdDepth_US1)
1624 constructor Create; override;
1627 TfdDepth24 = class(TfdDepth_UI1)
1628 constructor Create; override;
1631 TfdDepth32 = class(TfdDepth_UI1)
1632 constructor Create; override;
1635 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1636 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1637 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1638 constructor Create; override;
1641 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1642 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1643 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1644 constructor Create; override;
1647 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1648 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1649 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1650 constructor Create; override;
1653 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1654 TbmpBitfieldFormat = class(TFormatDescriptor)
1656 procedure SetRedMask (const aValue: QWord);
1657 procedure SetGreenMask(const aValue: QWord);
1658 procedure SetBlueMask (const aValue: QWord);
1659 procedure SetAlphaMask(const aValue: QWord);
1661 procedure Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte);
1663 property RedMask: QWord read GetRedMask write SetRedMask;
1664 property GreenMask: QWord read GetGreenMask write SetGreenMask;
1665 property BlueMask: QWord read GetBlueMask write SetBlueMask;
1666 property AlphaMask: QWord read GetAlphaMask write SetAlphaMask;
1668 property PixelSize: Single read fPixelSize write fPixelSize;
1670 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1671 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1674 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1675 TbmpColorTableEnty = packed record
1678 TbmpColorTable = array of TbmpColorTableEnty;
1679 TbmpColorTableFormat = class(TFormatDescriptor)
1681 fColorTable: TbmpColorTable;
1683 property PixelSize: Single read fPixelSize write fPixelSize;
1684 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1685 property Range: TglBitmapColorRec read fRange write fRange;
1686 property Shift: TShiftRec read fShift write fShift;
1687 property Format: TglBitmapFormat read fFormat write fFormat;
1689 procedure CreateColorTable;
1691 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1692 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1693 destructor Destroy; override;
1697 LUMINANCE_WEIGHT_R = 0.30;
1698 LUMINANCE_WEIGHT_G = 0.59;
1699 LUMINANCE_WEIGHT_B = 0.11;
1701 ALPHA_WEIGHT_R = 0.30;
1702 ALPHA_WEIGHT_G = 0.59;
1703 ALPHA_WEIGHT_B = 0.11;
1705 DEPTH_WEIGHT_R = 0.333333333;
1706 DEPTH_WEIGHT_G = 0.333333333;
1707 DEPTH_WEIGHT_B = 0.333333333;
1709 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1711 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1724 TfdLuminance4Alpha4,
1725 TfdLuminance6Alpha2,
1726 TfdLuminance8Alpha8,
1727 TfdLuminance12Alpha4,
1728 TfdLuminance12Alpha12,
1729 TfdLuminance16Alpha16,
1774 FormatDescriptorCS: TCriticalSection;
1775 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1777 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1778 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1780 inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1783 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1784 constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat);
1786 inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1789 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1790 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1792 result.Fields := [];
1795 result.Fields := result.Fields + [ffX];
1797 result.Fields := result.Fields + [ffY];
1799 result.X := Max(0, X);
1800 result.Y := Max(0, Y);
1803 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1804 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1812 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1813 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1818 for i := 0 to high(r1.arr) do
1819 if (r1.arr[i] <> r2.arr[i]) then
1824 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1825 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1833 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1834 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1843 tfR3G3B2, tfLuminance8,
1846 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1847 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1853 tfRGB10, tfRGB10A2, tfRGBA8,
1854 tfBGR10, tfBGR10A2, tfBGRA8]) then
1855 result := result + [ftBMP];
1859 tfLuminance8, tfAlpha8,
1862 tfLuminance16, tfLuminance8Alpha8,
1863 tfRGB5, tfRGB5A1, tfRGBA4,
1864 tfBGR5, tfBGR5A1, tfBGRA4,
1870 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1871 result := result + [ftTGA];
1875 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1876 tfR3G3B2, tfRGBA2, tfBGRA2,
1879 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1880 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1881 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1887 tfLuminance16Alpha16,
1892 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1893 result := result + [ftDDS];
1895 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1897 tfAlpha8, tfLuminance8, tfLuminance8Alpha8,
1899 tfBGR8, tfBGRA8] then
1900 result := result + [ftPNG];
1903 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1904 if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then
1905 result := result + [ftJPEG];
1909 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1910 function IsPowerOfTwo(aNumber: Integer): Boolean;
1912 while (aNumber and 1) = 0 do
1913 aNumber := aNumber shr 1;
1914 result := aNumber = 1;
1917 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1918 function GetTopMostBit(aBitSet: QWord): Integer;
1921 while aBitSet > 0 do begin
1923 aBitSet := aBitSet shr 1;
1927 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1928 function CountSetBits(aBitSet: QWord): Integer;
1931 while aBitSet > 0 do begin
1932 if (aBitSet and 1) = 1 then
1934 aBitSet := aBitSet shr 1;
1938 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1939 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1942 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1943 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1944 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1947 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1948 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1951 DEPTH_WEIGHT_R * aPixel.Data.r +
1952 DEPTH_WEIGHT_G * aPixel.Data.g +
1953 DEPTH_WEIGHT_B * aPixel.Data.b);
1956 {$IFDEF GLB_NATIVE_OGL}
1957 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1958 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1959 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1961 GL_LibHandle: Pointer = nil;
1963 function glbGetProcAddress(aProcName: PAnsiChar; aLibHandle: Pointer = nil; const aRaiseOnErr: Boolean = true): Pointer;
1965 if not Assigned(aLibHandle) then
1966 aLibHandle := GL_LibHandle;
1968 {$IF DEFINED(GLB_WIN)}
1969 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1970 if Assigned(result) then
1973 if Assigned(wglGetProcAddress) then
1974 result := wglGetProcAddress(aProcName);
1975 {$ELSEIF DEFINED(GLB_LINUX)}
1976 if Assigned(glXGetProcAddress) then begin
1977 result := glXGetProcAddress(aProcName);
1978 if Assigned(result) then
1982 if Assigned(glXGetProcAddressARB) then begin
1983 result := glXGetProcAddressARB(aProcName);
1984 if Assigned(result) then
1988 result := dlsym(aLibHandle, aProcName);
1990 if not Assigned(result) and aRaiseOnErr then
1991 raise EglBitmap.Create('unable to load procedure form library: ' + aProcName);
1994 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1996 GLU_LibHandle: Pointer = nil;
1997 OpenGLInitialized: Boolean;
1998 InitOpenGLCS: TCriticalSection;
2000 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001 procedure glbInitOpenGL;
2003 ////////////////////////////////////////////////////////////////////////////////
2004 function glbLoadLibrary(const aName: PChar): Pointer;
2006 {$IF DEFINED(GLB_WIN)}
2007 result := {%H-}Pointer(LoadLibrary(aName));
2008 {$ELSEIF DEFINED(GLB_LINUX)}
2009 result := dlopen(Name, RTLD_LAZY);
2015 ////////////////////////////////////////////////////////////////////////////////
2016 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
2019 if not Assigned(aLibHandle) then
2022 {$IF DEFINED(GLB_WIN)}
2023 Result := FreeLibrary({%H-}HINST(aLibHandle));
2024 {$ELSEIF DEFINED(GLB_LINUX)}
2025 Result := dlclose(aLibHandle) = 0;
2030 if Assigned(GL_LibHandle) then
2031 glbFreeLibrary(GL_LibHandle);
2033 if Assigned(GLU_LibHandle) then
2034 glbFreeLibrary(GLU_LibHandle);
2036 GL_LibHandle := glbLoadLibrary(libopengl);
2037 if not Assigned(GL_LibHandle) then
2038 raise EglBitmap.Create('unable to load library: ' + libopengl);
2040 GLU_LibHandle := glbLoadLibrary(libglu);
2041 if not Assigned(GLU_LibHandle) then
2042 raise EglBitmap.Create('unable to load library: ' + libglu);
2044 {$IF DEFINED(GLB_WIN)}
2045 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
2046 {$ELSEIF DEFINED(GLB_LINUX)}
2047 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
2048 glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
2051 glEnable := glbGetProcAddress('glEnable');
2052 glDisable := glbGetProcAddress('glDisable');
2053 glGetString := glbGetProcAddress('glGetString');
2054 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
2055 glTexParameteri := glbGetProcAddress('glTexParameteri');
2056 glTexParameteriv := glbGetProcAddress('glTexParameteriv');
2057 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
2058 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
2059 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
2060 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
2061 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
2062 glTexGeni := glbGetProcAddress('glTexGeni');
2063 glGenTextures := glbGetProcAddress('glGenTextures');
2064 glBindTexture := glbGetProcAddress('glBindTexture');
2065 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
2066 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
2067 glReadPixels := glbGetProcAddress('glReadPixels');
2068 glPixelStorei := glbGetProcAddress('glPixelStorei');
2069 glTexImage1D := glbGetProcAddress('glTexImage1D');
2070 glTexImage2D := glbGetProcAddress('glTexImage2D');
2071 glGetTexImage := glbGetProcAddress('glGetTexImage');
2073 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
2074 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
2078 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2079 procedure glbReadOpenGLExtensions;
2082 MajorVersion, MinorVersion: Integer;
2084 ///////////////////////////////////////////////////////////////////////////////////////////
2085 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
2092 Separator := Pos(AnsiString('.'), aBuffer);
2093 if (Separator > 1) and (Separator < Length(aBuffer)) and
2094 (aBuffer[Separator - 1] in ['0'..'9']) and
2095 (aBuffer[Separator + 1] in ['0'..'9']) then begin
2098 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
2101 Delete(aBuffer, 1, Separator);
2102 Separator := Pos(AnsiString('.'), aBuffer) + 1;
2104 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
2107 Delete(aBuffer, Separator, 255);
2108 Separator := Pos(AnsiString('.'), aBuffer);
2110 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
2111 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2115 ///////////////////////////////////////////////////////////////////////////////////////////
2116 function CheckExtension(const Extension: AnsiString): Boolean;
2120 ExtPos := Pos(Extension, Buffer);
2121 result := ExtPos > 0;
2123 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2126 ///////////////////////////////////////////////////////////////////////////////////////////
2127 function CheckVersion(const aMajor, aMinor: Integer): Boolean;
2129 result := (MajorVersion > aMajor) or ((MajorVersion = aMajor) and (MinorVersion >= aMinor));
2133 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2136 if not OpenGLInitialized then begin
2138 OpenGLInitialized := true;
2146 Buffer := glGetString(GL_VERSION);
2147 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2149 GL_VERSION_1_2 := CheckVersion(1, 2);
2150 GL_VERSION_1_3 := CheckVersion(1, 3);
2151 GL_VERSION_1_4 := CheckVersion(1, 4);
2152 GL_VERSION_2_0 := CheckVersion(2, 0);
2153 GL_VERSION_3_3 := CheckVersion(3, 3);
2156 Buffer := glGetString(GL_EXTENSIONS);
2157 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2158 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2159 GL_ARB_texture_swizzle := CheckExtension('GL_ARB_texture_swizzle');
2160 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
2161 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2162 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2163 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2164 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2165 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2166 GL_EXT_texture_swizzle := CheckExtension('GL_EXT_texture_swizzle');
2167 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
2168 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2169 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2170 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2172 if GL_VERSION_1_3 then begin
2173 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2174 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2175 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2177 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB', nil, false);
2178 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB', nil, false);
2179 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB', nil, false);
2184 {$IFDEF GLB_SDL_IMAGE}
2185 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2186 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2187 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2188 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2190 result := TStream(context^.unknown.data1).Seek(offset, whence);
2193 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2195 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2198 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2200 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2203 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2208 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2210 result := SDL_AllocRW;
2212 if result = nil then
2213 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2215 result^.seek := glBitmapRWseek;
2216 result^.read := glBitmapRWread;
2217 result^.write := glBitmapRWwrite;
2218 result^.close := glBitmapRWclose;
2219 result^.unknown.data1 := Stream;
2223 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2224 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2226 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2229 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2230 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2232 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2235 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2236 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2238 glBitmapDefaultMipmap := aValue;
2241 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2242 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2244 glBitmapDefaultFormat := aFormat;
2247 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2248 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2250 glBitmapDefaultFilterMin := aMin;
2251 glBitmapDefaultFilterMag := aMag;
2254 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2255 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2257 glBitmapDefaultWrapS := S;
2258 glBitmapDefaultWrapT := T;
2259 glBitmapDefaultWrapR := R;
2262 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2263 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
2265 glDefaultSwizzle[0] := r;
2266 glDefaultSwizzle[1] := g;
2267 glDefaultSwizzle[2] := b;
2268 glDefaultSwizzle[3] := a;
2271 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2272 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2274 result := glBitmapDefaultDeleteTextureOnFree;
2277 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2278 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2280 result := glBitmapDefaultFreeDataAfterGenTextures;
2283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2284 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2286 result := glBitmapDefaultMipmap;
2289 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2290 function glBitmapGetDefaultFormat: TglBitmapFormat;
2292 result := glBitmapDefaultFormat;
2295 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2296 procedure glBitmapGetDefaultFilter(var aMin, aMag: GLenum);
2298 aMin := glBitmapDefaultFilterMin;
2299 aMag := glBitmapDefaultFilterMag;
2302 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2303 procedure glBitmapGetDefaultTextureWrap(var S, T, R: GLenum);
2305 S := glBitmapDefaultWrapS;
2306 T := glBitmapDefaultWrapT;
2307 R := glBitmapDefaultWrapR;
2310 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2311 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
2313 r := glDefaultSwizzle[0];
2314 g := glDefaultSwizzle[1];
2315 b := glDefaultSwizzle[2];
2316 a := glDefaultSwizzle[3];
2319 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2320 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2321 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2322 function TFormatDescriptor.GetRedMask: QWord;
2324 result := fRange.r shl fShift.r;
2327 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2328 function TFormatDescriptor.GetGreenMask: QWord;
2330 result := fRange.g shl fShift.g;
2333 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2334 function TFormatDescriptor.GetBlueMask: QWord;
2336 result := fRange.b shl fShift.b;
2339 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2340 function TFormatDescriptor.GetAlphaMask: QWord;
2342 result := fRange.a shl fShift.a;
2345 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2346 function TFormatDescriptor.GetIsCompressed: Boolean;
2348 result := fIsCompressed;
2351 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2352 function TFormatDescriptor.GetHasRed: Boolean;
2354 result := (fRange.r > 0);
2357 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2358 function TFormatDescriptor.GetHasGreen: Boolean;
2360 result := (fRange.g > 0);
2363 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2364 function TFormatDescriptor.GetHasBlue: Boolean;
2366 result := (fRange.b > 0);
2369 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2370 function TFormatDescriptor.GetHasAlpha: Boolean;
2372 result := (fRange.a > 0);
2375 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2376 function TFormatDescriptor.GetglFormat: GLenum;
2378 result := fglFormat;
2381 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2382 function TFormatDescriptor.GetglInternalFormat: GLenum;
2384 result := fglInternalFormat;
2387 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2388 function TFormatDescriptor.GetglDataFormat: GLenum;
2390 result := fglDataFormat;
2393 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2394 function TFormatDescriptor.GetComponents: Integer;
2400 if (fRange.arr[i] > 0) then
2404 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2405 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2409 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2410 w := Max(1, aSize.X);
2411 h := Max(1, aSize.Y);
2412 result := GetSize(w, h);
2417 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2418 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2421 if (aWidth <= 0) or (aHeight <= 0) then
2423 result := Ceil(aWidth * aHeight * fPixelSize);
2426 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2427 function TFormatDescriptor.CreateMappingData: Pointer;
2432 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2433 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2438 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2439 function TFormatDescriptor.IsEmpty: Boolean;
2441 result := (fFormat = tfEmpty);
2444 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2445 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2448 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2449 raise EglBitmap.Create('FormatCheckFormat - All Masks are 0');
2450 if (aRedMask <> RedMask) then
2452 if (aGreenMask <> GreenMask) then
2454 if (aBlueMask <> BlueMask) then
2456 if (aAlphaMask <> AlphaMask) then
2461 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2462 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2464 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2465 aPixel.Data := fRange;
2466 aPixel.Range := fRange;
2467 aPixel.Format := fFormat;
2470 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2471 constructor TFormatDescriptor.Create;
2476 fWithAlpha := tfEmpty;
2477 fWithoutAlpha := tfEmpty;
2478 fRGBInverted := tfEmpty;
2479 fUncompressed := tfEmpty;
2481 fIsCompressed := false;
2484 fglInternalFormat := 0;
2487 FillChar(fRange, 0, SizeOf(fRange));
2488 FillChar(fShift, 0, SizeOf(fShift));
2491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2492 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2493 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2494 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2496 aData^ := aPixel.Data.a;
2500 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2505 aPixel.Data.a := aData^;
2509 constructor TfdAlpha_UB1.Create;
2514 fglFormat := GL_ALPHA;
2515 fglDataFormat := GL_UNSIGNED_BYTE;
2518 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2519 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2520 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2521 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2523 aData^ := LuminanceWeight(aPixel);
2527 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2529 aPixel.Data.r := aData^;
2530 aPixel.Data.g := aData^;
2531 aPixel.Data.b := aData^;
2536 constructor TfdLuminance_UB1.Create;
2543 fglFormat := GL_LUMINANCE;
2544 fglDataFormat := GL_UNSIGNED_BYTE;
2547 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2548 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2549 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2550 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2556 if (fRange.arr[i] > 0) then
2557 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2561 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2566 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2570 constructor TfdUniversal_UB1.Create;
2576 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2577 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2578 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2579 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2581 inherited Map(aPixel, aData, aMapData);
2582 aData^ := aPixel.Data.a;
2586 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2588 inherited Unmap(aData, aPixel, aMapData);
2589 aPixel.Data.a := aData^;
2593 constructor TfdLuminanceAlpha_UB2.Create;
2599 fglFormat := GL_LUMINANCE_ALPHA;
2600 fglDataFormat := GL_UNSIGNED_BYTE;
2603 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2604 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2605 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2606 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2608 aData^ := aPixel.Data.r;
2610 aData^ := aPixel.Data.g;
2612 aData^ := aPixel.Data.b;
2616 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2618 aPixel.Data.r := aData^;
2620 aPixel.Data.g := aData^;
2622 aPixel.Data.b := aData^;
2627 constructor TfdRGB_UB3.Create;
2637 fglFormat := GL_RGB;
2638 fglDataFormat := GL_UNSIGNED_BYTE;
2641 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2642 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2643 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2644 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2646 aData^ := aPixel.Data.b;
2648 aData^ := aPixel.Data.g;
2650 aData^ := aPixel.Data.r;
2654 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2656 aPixel.Data.b := aData^;
2658 aPixel.Data.g := aData^;
2660 aPixel.Data.r := aData^;
2665 constructor TfdBGR_UB3.Create;
2674 fglFormat := GL_BGR;
2675 fglDataFormat := GL_UNSIGNED_BYTE;
2678 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2679 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2680 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2681 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2683 inherited Map(aPixel, aData, aMapData);
2684 aData^ := aPixel.Data.a;
2688 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2690 inherited Unmap(aData, aPixel, aMapData);
2691 aPixel.Data.a := aData^;
2695 constructor TfdRGBA_UB4.Create;
2701 fglFormat := GL_RGBA;
2702 fglDataFormat := GL_UNSIGNED_BYTE;
2705 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2706 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2707 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2708 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2710 inherited Map(aPixel, aData, aMapData);
2711 aData^ := aPixel.Data.a;
2715 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2717 inherited Unmap(aData, aPixel, aMapData);
2718 aPixel.Data.a := aData^;
2722 constructor TfdBGRA_UB4.Create;
2728 fglFormat := GL_BGRA;
2729 fglDataFormat := GL_UNSIGNED_BYTE;
2732 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2733 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2734 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2735 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2737 PWord(aData)^ := aPixel.Data.a;
2741 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2746 aPixel.Data.a := PWord(aData)^;
2750 constructor TfdAlpha_US1.Create;
2755 fglFormat := GL_ALPHA;
2756 fglDataFormat := GL_UNSIGNED_SHORT;
2759 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2760 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2761 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2762 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2764 PWord(aData)^ := LuminanceWeight(aPixel);
2768 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2770 aPixel.Data.r := PWord(aData)^;
2771 aPixel.Data.g := PWord(aData)^;
2772 aPixel.Data.b := PWord(aData)^;
2777 constructor TfdLuminance_US1.Create;
2784 fglFormat := GL_LUMINANCE;
2785 fglDataFormat := GL_UNSIGNED_SHORT;
2788 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2789 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2790 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2791 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2797 if (fRange.arr[i] > 0) then
2798 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2802 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2807 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2811 constructor TfdUniversal_US1.Create;
2817 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2818 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2819 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2820 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2822 PWord(aData)^ := DepthWeight(aPixel);
2826 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2828 aPixel.Data.r := PWord(aData)^;
2829 aPixel.Data.g := PWord(aData)^;
2830 aPixel.Data.b := PWord(aData)^;
2835 constructor TfdDepth_US1.Create;
2842 fglFormat := GL_DEPTH_COMPONENT;
2843 fglDataFormat := GL_UNSIGNED_SHORT;
2846 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2847 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2848 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2849 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2851 inherited Map(aPixel, aData, aMapData);
2852 PWord(aData)^ := aPixel.Data.a;
2856 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2858 inherited Unmap(aData, aPixel, aMapData);
2859 aPixel.Data.a := PWord(aData)^;
2863 constructor TfdLuminanceAlpha_US2.Create;
2869 fglFormat := GL_LUMINANCE_ALPHA;
2870 fglDataFormat := GL_UNSIGNED_SHORT;
2873 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2874 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2875 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2876 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2878 PWord(aData)^ := aPixel.Data.r;
2880 PWord(aData)^ := aPixel.Data.g;
2882 PWord(aData)^ := aPixel.Data.b;
2886 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2888 aPixel.Data.r := PWord(aData)^;
2890 aPixel.Data.g := PWord(aData)^;
2892 aPixel.Data.b := PWord(aData)^;
2897 constructor TfdRGB_US3.Create;
2907 fglFormat := GL_RGB;
2908 fglDataFormat := GL_UNSIGNED_SHORT;
2911 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2912 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2913 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2914 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2916 PWord(aData)^ := aPixel.Data.b;
2918 PWord(aData)^ := aPixel.Data.g;
2920 PWord(aData)^ := aPixel.Data.r;
2924 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2926 aPixel.Data.b := PWord(aData)^;
2928 aPixel.Data.g := PWord(aData)^;
2930 aPixel.Data.r := PWord(aData)^;
2935 constructor TfdBGR_US3.Create;
2945 fglFormat := GL_BGR;
2946 fglDataFormat := GL_UNSIGNED_SHORT;
2949 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2950 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2951 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2952 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2954 inherited Map(aPixel, aData, aMapData);
2955 PWord(aData)^ := aPixel.Data.a;
2959 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2961 inherited Unmap(aData, aPixel, aMapData);
2962 aPixel.Data.a := PWord(aData)^;
2966 constructor TfdRGBA_US4.Create;
2972 fglFormat := GL_RGBA;
2973 fglDataFormat := GL_UNSIGNED_SHORT;
2976 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2977 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2978 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2979 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2981 inherited Map(aPixel, aData, aMapData);
2982 PWord(aData)^ := aPixel.Data.a;
2986 procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2988 inherited Unmap(aData, aPixel, aMapData);
2989 aPixel.Data.a := PWord(aData)^;
2993 constructor TfdBGRA_US4.Create;
2999 fglFormat := GL_BGRA;
3000 fglDataFormat := GL_UNSIGNED_SHORT;
3003 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3004 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3005 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3006 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3010 PCardinal(aData)^ := 0;
3012 if (fRange.arr[i] > 0) then
3013 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
3017 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3022 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
3026 constructor TfdUniversal_UI1.Create;
3032 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3033 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3034 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3035 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3037 PCardinal(aData)^ := DepthWeight(aPixel);
3041 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3043 aPixel.Data.r := PCardinal(aData)^;
3044 aPixel.Data.g := PCardinal(aData)^;
3045 aPixel.Data.b := PCardinal(aData)^;
3050 constructor TfdDepth_UI1.Create;
3054 fRange.r := $FFFFFFFF;
3055 fRange.g := $FFFFFFFF;
3056 fRange.b := $FFFFFFFF;
3057 fglFormat := GL_DEPTH_COMPONENT;
3058 fglDataFormat := GL_UNSIGNED_INT;
3061 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3062 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3063 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3064 constructor TfdAlpha4.Create;
3067 fFormat := tfAlpha4;
3068 fWithAlpha := tfAlpha4;
3069 fglInternalFormat := GL_ALPHA4;
3072 constructor TfdAlpha8.Create;
3075 fFormat := tfAlpha8;
3076 fWithAlpha := tfAlpha8;
3077 fglInternalFormat := GL_ALPHA8;
3080 constructor TfdAlpha12.Create;
3083 fFormat := tfAlpha12;
3084 fWithAlpha := tfAlpha12;
3085 fglInternalFormat := GL_ALPHA12;
3088 constructor TfdAlpha16.Create;
3091 fFormat := tfAlpha16;
3092 fWithAlpha := tfAlpha16;
3093 fglInternalFormat := GL_ALPHA16;
3096 constructor TfdLuminance4.Create;
3099 fFormat := tfLuminance4;
3100 fWithAlpha := tfLuminance4Alpha4;
3101 fWithoutAlpha := tfLuminance4;
3102 fglInternalFormat := GL_LUMINANCE4;
3105 constructor TfdLuminance8.Create;
3108 fFormat := tfLuminance8;
3109 fWithAlpha := tfLuminance8Alpha8;
3110 fWithoutAlpha := tfLuminance8;
3111 fglInternalFormat := GL_LUMINANCE8;
3114 constructor TfdLuminance12.Create;
3117 fFormat := tfLuminance12;
3118 fWithAlpha := tfLuminance12Alpha12;
3119 fWithoutAlpha := tfLuminance12;
3120 fglInternalFormat := GL_LUMINANCE12;
3123 constructor TfdLuminance16.Create;
3126 fFormat := tfLuminance16;
3127 fWithAlpha := tfLuminance16Alpha16;
3128 fWithoutAlpha := tfLuminance16;
3129 fglInternalFormat := GL_LUMINANCE16;
3132 constructor TfdLuminance4Alpha4.Create;
3135 fFormat := tfLuminance4Alpha4;
3136 fWithAlpha := tfLuminance4Alpha4;
3137 fWithoutAlpha := tfLuminance4;
3138 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3141 constructor TfdLuminance6Alpha2.Create;
3144 fFormat := tfLuminance6Alpha2;
3145 fWithAlpha := tfLuminance6Alpha2;
3146 fWithoutAlpha := tfLuminance8;
3147 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3150 constructor TfdLuminance8Alpha8.Create;
3153 fFormat := tfLuminance8Alpha8;
3154 fWithAlpha := tfLuminance8Alpha8;
3155 fWithoutAlpha := tfLuminance8;
3156 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3159 constructor TfdLuminance12Alpha4.Create;
3162 fFormat := tfLuminance12Alpha4;
3163 fWithAlpha := tfLuminance12Alpha4;
3164 fWithoutAlpha := tfLuminance12;
3165 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3168 constructor TfdLuminance12Alpha12.Create;
3171 fFormat := tfLuminance12Alpha12;
3172 fWithAlpha := tfLuminance12Alpha12;
3173 fWithoutAlpha := tfLuminance12;
3174 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3177 constructor TfdLuminance16Alpha16.Create;
3180 fFormat := tfLuminance16Alpha16;
3181 fWithAlpha := tfLuminance16Alpha16;
3182 fWithoutAlpha := tfLuminance16;
3183 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3186 constructor TfdR3G3B2.Create;
3189 fFormat := tfR3G3B2;
3190 fWithAlpha := tfRGBA2;
3191 fWithoutAlpha := tfR3G3B2;
3198 fglFormat := GL_RGB;
3199 fglInternalFormat := GL_R3_G3_B2;
3200 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3203 constructor TfdRGB4.Create;
3207 fWithAlpha := tfRGBA4;
3208 fWithoutAlpha := tfRGB4;
3209 fRGBInverted := tfBGR4;
3216 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3217 fglInternalFormat := GL_RGB4;
3218 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3221 constructor TfdR5G6B5.Create;
3224 fFormat := tfR5G6B5;
3225 fWithAlpha := tfRGBA4;
3226 fWithoutAlpha := tfR5G6B5;
3227 fRGBInverted := tfB5G6R5;
3234 fglFormat := GL_RGB;
3235 fglInternalFormat := GL_RGB565;
3236 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3239 constructor TfdRGB5.Create;
3243 fWithAlpha := tfRGB5A1;
3244 fWithoutAlpha := tfRGB5;
3245 fRGBInverted := tfBGR5;
3252 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3253 fglInternalFormat := GL_RGB5;
3254 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3257 constructor TfdRGB8.Create;
3261 fWithAlpha := tfRGBA8;
3262 fWithoutAlpha := tfRGB8;
3263 fRGBInverted := tfBGR8;
3264 fglInternalFormat := GL_RGB8;
3267 constructor TfdRGB10.Create;
3271 fWithAlpha := tfRGB10A2;
3272 fWithoutAlpha := tfRGB10;
3273 fRGBInverted := tfBGR10;
3280 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3281 fglInternalFormat := GL_RGB10;
3282 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3285 constructor TfdRGB12.Create;
3289 fWithAlpha := tfRGBA12;
3290 fWithoutAlpha := tfRGB12;
3291 fRGBInverted := tfBGR12;
3292 fglInternalFormat := GL_RGB12;
3295 constructor TfdRGB16.Create;
3299 fWithAlpha := tfRGBA16;
3300 fWithoutAlpha := tfRGB16;
3301 fRGBInverted := tfBGR16;
3302 fglInternalFormat := GL_RGB16;
3305 constructor TfdRGBA2.Create;
3309 fWithAlpha := tfRGBA2;
3310 fWithoutAlpha := tfR3G3B2;
3311 fRGBInverted := tfBGRA2;
3312 fglInternalFormat := GL_RGBA2;
3315 constructor TfdRGBA4.Create;
3319 fWithAlpha := tfRGBA4;
3320 fWithoutAlpha := tfRGB4;
3321 fRGBInverted := tfBGRA4;
3330 fglFormat := GL_RGBA;
3331 fglInternalFormat := GL_RGBA4;
3332 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3335 constructor TfdRGB5A1.Create;
3338 fFormat := tfRGB5A1;
3339 fWithAlpha := tfRGB5A1;
3340 fWithoutAlpha := tfRGB5;
3341 fRGBInverted := tfBGR5A1;
3350 fglFormat := GL_RGBA;
3351 fglInternalFormat := GL_RGB5_A1;
3352 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3355 constructor TfdRGBA8.Create;
3359 fWithAlpha := tfRGBA8;
3360 fWithoutAlpha := tfRGB8;
3361 fRGBInverted := tfBGRA8;
3362 fglInternalFormat := GL_RGBA8;
3365 constructor TfdRGB10A2.Create;
3368 fFormat := tfRGB10A2;
3369 fWithAlpha := tfRGB10A2;
3370 fWithoutAlpha := tfRGB10;
3371 fRGBInverted := tfBGR10A2;
3380 fglFormat := GL_RGBA;
3381 fglInternalFormat := GL_RGB10_A2;
3382 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3385 constructor TfdRGBA12.Create;
3388 fFormat := tfRGBA12;
3389 fWithAlpha := tfRGBA12;
3390 fWithoutAlpha := tfRGB12;
3391 fRGBInverted := tfBGRA12;
3392 fglInternalFormat := GL_RGBA12;
3395 constructor TfdRGBA16.Create;
3398 fFormat := tfRGBA16;
3399 fWithAlpha := tfRGBA16;
3400 fWithoutAlpha := tfRGB16;
3401 fRGBInverted := tfBGRA16;
3402 fglInternalFormat := GL_RGBA16;
3405 constructor TfdBGR4.Create;
3410 fWithAlpha := tfBGRA4;
3411 fWithoutAlpha := tfBGR4;
3412 fRGBInverted := tfRGB4;
3421 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3422 fglInternalFormat := GL_RGB4;
3423 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3426 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3428 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3429 constructor TfdB5G6R5.Create;
3432 fFormat := tfB5G6R5;
3433 fWithAlpha := tfBGRA4;
3434 fWithoutAlpha := tfB5G6R5;
3435 fRGBInverted := tfR5G6B5;
3442 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3443 fglInternalFormat := GL_RGB8;
3444 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3447 constructor TfdBGR5.Create;
3452 fWithAlpha := tfBGR5A1;
3453 fWithoutAlpha := tfBGR5;
3454 fRGBInverted := tfRGB5;
3463 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3464 fglInternalFormat := GL_RGB5;
3465 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3468 constructor TfdBGR8.Create;
3472 fWithAlpha := tfBGRA8;
3473 fWithoutAlpha := tfBGR8;
3474 fRGBInverted := tfRGB8;
3475 fglInternalFormat := GL_RGB8;
3478 constructor TfdBGR10.Create;
3482 fWithAlpha := tfBGR10A2;
3483 fWithoutAlpha := tfBGR10;
3484 fRGBInverted := tfRGB10;
3493 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3494 fglInternalFormat := GL_RGB10;
3495 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3498 constructor TfdBGR12.Create;
3502 fWithAlpha := tfBGRA12;
3503 fWithoutAlpha := tfBGR12;
3504 fRGBInverted := tfRGB12;
3505 fglInternalFormat := GL_RGB12;
3508 constructor TfdBGR16.Create;
3512 fWithAlpha := tfBGRA16;
3513 fWithoutAlpha := tfBGR16;
3514 fRGBInverted := tfRGB16;
3515 fglInternalFormat := GL_RGB16;
3518 constructor TfdBGRA2.Create;
3522 fWithAlpha := tfBGRA4;
3523 fWithoutAlpha := tfBGR4;
3524 fRGBInverted := tfRGBA2;
3525 fglInternalFormat := GL_RGBA2;
3528 constructor TfdBGRA4.Create;
3532 fWithAlpha := tfBGRA4;
3533 fWithoutAlpha := tfBGR4;
3534 fRGBInverted := tfRGBA4;
3543 fglFormat := GL_BGRA;
3544 fglInternalFormat := GL_RGBA4;
3545 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3548 constructor TfdBGR5A1.Create;
3551 fFormat := tfBGR5A1;
3552 fWithAlpha := tfBGR5A1;
3553 fWithoutAlpha := tfBGR5;
3554 fRGBInverted := tfRGB5A1;
3563 fglFormat := GL_BGRA;
3564 fglInternalFormat := GL_RGB5_A1;
3565 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3568 constructor TfdBGRA8.Create;
3572 fWithAlpha := tfBGRA8;
3573 fWithoutAlpha := tfBGR8;
3574 fRGBInverted := tfRGBA8;
3575 fglInternalFormat := GL_RGBA8;
3578 constructor TfdBGR10A2.Create;
3581 fFormat := tfBGR10A2;
3582 fWithAlpha := tfBGR10A2;
3583 fWithoutAlpha := tfBGR10;
3584 fRGBInverted := tfRGB10A2;
3593 fglFormat := GL_BGRA;
3594 fglInternalFormat := GL_RGB10_A2;
3595 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3598 constructor TfdBGRA12.Create;
3601 fFormat := tfBGRA12;
3602 fWithAlpha := tfBGRA12;
3603 fWithoutAlpha := tfBGR12;
3604 fRGBInverted := tfRGBA12;
3605 fglInternalFormat := GL_RGBA12;
3608 constructor TfdBGRA16.Create;
3611 fFormat := tfBGRA16;
3612 fWithAlpha := tfBGRA16;
3613 fWithoutAlpha := tfBGR16;
3614 fRGBInverted := tfRGBA16;
3615 fglInternalFormat := GL_RGBA16;
3618 constructor TfdDepth16.Create;
3621 fFormat := tfDepth16;
3622 fWithAlpha := tfEmpty;
3623 fWithoutAlpha := tfDepth16;
3624 fglInternalFormat := GL_DEPTH_COMPONENT16;
3627 constructor TfdDepth24.Create;
3630 fFormat := tfDepth24;
3631 fWithAlpha := tfEmpty;
3632 fWithoutAlpha := tfDepth24;
3633 fglInternalFormat := GL_DEPTH_COMPONENT24;
3636 constructor TfdDepth32.Create;
3639 fFormat := tfDepth32;
3640 fWithAlpha := tfEmpty;
3641 fWithoutAlpha := tfDepth32;
3642 fglInternalFormat := GL_DEPTH_COMPONENT32;
3645 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3646 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3647 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3648 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3650 raise EglBitmap.Create('mapping for compressed formats is not supported');
3653 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3655 raise EglBitmap.Create('mapping for compressed formats is not supported');
3658 constructor TfdS3tcDtx1RGBA.Create;
3661 fFormat := tfS3tcDtx1RGBA;
3662 fWithAlpha := tfS3tcDtx1RGBA;
3663 fUncompressed := tfRGB5A1;
3665 fIsCompressed := true;
3666 fglFormat := GL_COMPRESSED_RGBA;
3667 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3668 fglDataFormat := GL_UNSIGNED_BYTE;
3671 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3672 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3673 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3674 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3676 raise EglBitmap.Create('mapping for compressed formats is not supported');
3679 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3681 raise EglBitmap.Create('mapping for compressed formats is not supported');
3684 constructor TfdS3tcDtx3RGBA.Create;
3687 fFormat := tfS3tcDtx3RGBA;
3688 fWithAlpha := tfS3tcDtx3RGBA;
3689 fUncompressed := tfRGBA8;
3691 fIsCompressed := true;
3692 fglFormat := GL_COMPRESSED_RGBA;
3693 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3694 fglDataFormat := GL_UNSIGNED_BYTE;
3697 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3698 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3699 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3700 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3702 raise EglBitmap.Create('mapping for compressed formats is not supported');
3705 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3707 raise EglBitmap.Create('mapping for compressed formats is not supported');
3710 constructor TfdS3tcDtx5RGBA.Create;
3713 fFormat := tfS3tcDtx3RGBA;
3714 fWithAlpha := tfS3tcDtx3RGBA;
3715 fUncompressed := tfRGBA8;
3717 fIsCompressed := true;
3718 fglFormat := GL_COMPRESSED_RGBA;
3719 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3720 fglDataFormat := GL_UNSIGNED_BYTE;
3723 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3724 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3725 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3726 class procedure TFormatDescriptor.Init;
3728 if not Assigned(FormatDescriptorCS) then
3729 FormatDescriptorCS := TCriticalSection.Create;
3732 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3733 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3735 FormatDescriptorCS.Enter;
3737 result := FormatDescriptors[aFormat];
3738 if not Assigned(result) then begin
3739 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3740 FormatDescriptors[aFormat] := result;
3743 FormatDescriptorCS.Leave;
3747 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3748 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3750 result := Get(Get(aFormat).WithAlpha);
3753 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3754 class procedure TFormatDescriptor.Clear;
3758 FormatDescriptorCS.Enter;
3760 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3761 FreeAndNil(FormatDescriptors[f]);
3763 FormatDescriptorCS.Leave;
3767 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3768 class procedure TFormatDescriptor.Finalize;
3771 FreeAndNil(FormatDescriptorCS);
3774 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3775 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3776 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3777 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3779 Update(aValue, fRange.r, fShift.r);
3782 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3783 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3785 Update(aValue, fRange.g, fShift.g);
3788 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3789 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3791 Update(aValue, fRange.b, fShift.b);
3794 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3795 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3797 Update(aValue, fRange.a, fShift.a);
3800 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3801 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3808 while (aMask > 0) and ((aMask and 1) = 0) do begin
3810 aMask := aMask shr 1;
3813 while (aMask > 0) do begin
3814 aRange := aRange shl 1;
3815 aMask := aMask shr 1;
3819 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3822 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3823 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3829 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3830 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3831 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3832 ((aPixel.Data.a and fRange.a) shl fShift.a);
3833 s := Round(fPixelSize);
3836 2: PWord(aData)^ := data;
3837 4: PCardinal(aData)^ := data;
3838 8: PQWord(aData)^ := data;
3840 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3845 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3846 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3851 s := Round(fPixelSize);
3854 2: data := PWord(aData)^;
3855 4: data := PCardinal(aData)^;
3856 8: data := PQWord(aData)^;
3858 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3861 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3865 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3866 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3867 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3868 procedure TbmpColorTableFormat.CreateColorTable;
3872 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3873 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3875 if (Format = tfLuminance4) then
3876 SetLength(fColorTable, 16)
3878 SetLength(fColorTable, 256);
3882 for i := 0 to High(fColorTable) do begin
3883 fColorTable[i].r := 16 * i;
3884 fColorTable[i].g := 16 * i;
3885 fColorTable[i].b := 16 * i;
3886 fColorTable[i].a := 0;
3891 for i := 0 to High(fColorTable) do begin
3892 fColorTable[i].r := i;
3893 fColorTable[i].g := i;
3894 fColorTable[i].b := i;
3895 fColorTable[i].a := 0;
3900 for i := 0 to High(fColorTable) do begin
3901 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3902 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3903 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3904 fColorTable[i].a := 0;
3910 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3911 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3915 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3916 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3920 if (aMapData = nil) then
3922 d := LuminanceWeight(aPixel) and Range.r;
3923 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3924 inc(PByte(aMapData), 4);
3925 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3932 aData^ := LuminanceWeight(aPixel) and Range.r;
3938 ((aPixel.Data.r and Range.r) shl Shift.r) or
3939 ((aPixel.Data.g and Range.g) shl Shift.g) or
3940 ((aPixel.Data.b and Range.b) shl Shift.b));
3946 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3947 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3954 s := Trunc(fPixelSize);
3955 f := fPixelSize - s;
3956 bits := Round(8 * f);
3958 0: idx := (aData^ shr (8 - bits - {%H-}PtrInt(aMapData))) and ((1 shl bits) - 1);
3960 2: idx := PWord(aData)^;
3961 4: idx := PCardinal(aData)^;
3962 8: idx := PQWord(aData)^;
3964 raise EglBitmap.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3966 if (idx >= Length(fColorTable)) then
3967 raise EglBitmap.CreateFmt('invalid color index: %d', [idx]);
3968 with fColorTable[idx] do begin
3974 inc(PByte(aMapData), bits);
3975 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3977 dec(PByte(aMapData), 8);
3982 destructor TbmpColorTableFormat.Destroy;
3984 SetLength(fColorTable, 0);
3988 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3989 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3990 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3991 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
3995 for i := 0 to 3 do begin
3996 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
3997 if (aSourceFD.Range.arr[i] > 0) then
3998 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
4000 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
4005 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4006 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
4008 with aFuncRec do begin
4009 if (Source.Range.r > 0) then
4010 Dest.Data.r := Source.Data.r;
4011 if (Source.Range.g > 0) then
4012 Dest.Data.g := Source.Data.g;
4013 if (Source.Range.b > 0) then
4014 Dest.Data.b := Source.Data.b;
4015 if (Source.Range.a > 0) then
4016 Dest.Data.a := Source.Data.a;
4020 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4021 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4025 with aFuncRec do begin
4027 if (Source.Range.arr[i] > 0) then
4028 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4033 TShiftData = packed record
4035 0: (r, g, b, a: SmallInt);
4036 1: (arr: array[0..3] of SmallInt);
4038 PShiftData = ^TShiftData;
4040 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4041 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4047 if (Source.Range.arr[i] > 0) then
4048 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4051 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4052 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4054 with aFuncRec do begin
4055 Dest.Data := Source.Data;
4056 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4057 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4058 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4059 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4061 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4062 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4067 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4068 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4072 with aFuncRec do begin
4074 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4078 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4079 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4083 with FuncRec do begin
4084 if (FuncRec.Args = nil) then begin //source has no alpha
4086 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4087 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4088 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4089 Dest.Data.a := Round(Dest.Range.a * Temp);
4091 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4095 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4096 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4098 PglBitmapPixelData = ^TglBitmapPixelData;
4100 with FuncRec do begin
4101 Dest.Data.r := Source.Data.r;
4102 Dest.Data.g := Source.Data.g;
4103 Dest.Data.b := Source.Data.b;
4105 with PglBitmapPixelData(Args)^ do
4106 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4107 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4108 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4111 Dest.Data.a := Dest.Range.a;
4115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4116 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4118 with FuncRec do begin
4119 Dest.Data.r := Source.Data.r;
4120 Dest.Data.g := Source.Data.g;
4121 Dest.Data.b := Source.Data.b;
4122 Dest.Data.a := PCardinal(Args)^;
4126 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4127 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4130 TRGBPix = array [0..2] of byte;
4134 while aWidth > 0 do begin
4135 Temp := PRGBPix(aData)^[0];
4136 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4137 PRGBPix(aData)^[2] := Temp;
4147 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4148 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4149 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4150 function TglBitmap.GetFormatDesc: TglBitmapFormatDescriptor;
4152 result := TFormatDescriptor.Get(Format);
4155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4156 function TglBitmap.GetWidth: Integer;
4158 if (ffX in fDimension.Fields) then
4159 result := fDimension.X
4164 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4165 function TglBitmap.GetHeight: Integer;
4167 if (ffY in fDimension.Fields) then
4168 result := fDimension.Y
4173 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4174 function TglBitmap.GetFileWidth: Integer;
4176 result := Max(1, Width);
4179 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4180 function TglBitmap.GetFileHeight: Integer;
4182 result := Max(1, Height);
4185 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4186 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4188 if fCustomData = aValue then
4190 fCustomData := aValue;
4193 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4194 procedure TglBitmap.SetCustomName(const aValue: String);
4196 if fCustomName = aValue then
4198 fCustomName := aValue;
4201 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4202 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4204 if fCustomNameW = aValue then
4206 fCustomNameW := aValue;
4209 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4210 procedure TglBitmap.SetFreeDataOnDestroy(const aValue: Boolean);
4212 if fFreeDataOnDestroy = aValue then
4214 fFreeDataOnDestroy := aValue;
4217 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4218 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4220 if fDeleteTextureOnFree = aValue then
4222 fDeleteTextureOnFree := aValue;
4225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4226 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4228 if fFormat = aValue then
4230 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4231 raise EglBitmapUnsupportedFormat.Create(Format);
4232 SetDataPointer(fData, aValue, Width, Height); //be careful, Data could be freed by this method
4235 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4236 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4238 if fFreeDataAfterGenTexture = aValue then
4240 fFreeDataAfterGenTexture := aValue;
4243 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4244 procedure TglBitmap.SetID(const aValue: Cardinal);
4246 if fID = aValue then
4251 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4252 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4254 if fMipMap = aValue then
4259 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4260 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4262 if fTarget = aValue then
4267 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4268 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4270 MaxAnisotropic: Integer;
4272 fAnisotropic := aValue;
4273 if (ID > 0) then begin
4274 if GL_EXT_texture_filter_anisotropic then begin
4275 if fAnisotropic > 0 then begin
4277 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4278 if aValue > MaxAnisotropic then
4279 fAnisotropic := MaxAnisotropic;
4280 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4288 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4289 procedure TglBitmap.CreateID;
4292 glDeleteTextures(1, @fID);
4293 glGenTextures(1, @fID);
4297 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4298 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4300 // Set Up Parameters
4301 SetWrap(fWrapS, fWrapT, fWrapR);
4302 SetFilter(fFilterMin, fFilterMag);
4303 SetAnisotropic(fAnisotropic);
4304 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4306 if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
4307 SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4309 // Mip Maps Generation Mode
4310 aBuildWithGlu := false;
4311 if (MipMap = mmMipmap) then begin
4312 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4313 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4315 aBuildWithGlu := true;
4316 end else if (MipMap = mmMipmapGlu) then
4317 aBuildWithGlu := true;
4320 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4321 procedure TglBitmap.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
4322 const aWidth: Integer; const aHeight: Integer);
4326 if (Data <> aData) then begin
4327 if (Assigned(Data)) then
4332 if not Assigned(fData) then begin
4336 FillChar(fDimension, SizeOf(fDimension), 0);
4337 if aWidth <> -1 then begin
4338 fDimension.Fields := fDimension.Fields + [ffX];
4339 fDimension.X := aWidth;
4342 if aHeight <> -1 then begin
4343 fDimension.Fields := fDimension.Fields + [ffY];
4344 fDimension.Y := aHeight;
4347 s := TFormatDescriptor.Get(aFormat).PixelSize;
4349 fPixelSize := Ceil(s);
4350 fRowSize := Ceil(s * aWidth);
4354 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4355 function TglBitmap.FlipHorz: Boolean;
4360 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4361 function TglBitmap.FlipVert: Boolean;
4366 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4367 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4368 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4369 procedure TglBitmap.AfterConstruction;
4371 inherited AfterConstruction;
4375 fIsResident := false;
4377 fMipMap := glBitmapDefaultMipmap;
4378 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4379 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4381 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4382 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4383 glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4386 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4387 procedure TglBitmap.BeforeDestruction;
4391 if fFreeDataOnDestroy then begin
4393 SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
4395 if (fID > 0) and fDeleteTextureOnFree then
4396 glDeleteTextures(1, @fID);
4397 inherited BeforeDestruction;
4400 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4401 procedure TglBitmap.PrepareResType(var aResource: String; var aResType: PChar);
4405 if not Assigned(aResType) then begin
4406 TempPos := Pos('.', aResource);
4407 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4408 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4412 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4413 procedure TglBitmap.LoadFromFile(const aFilename: String);
4417 if not FileExists(aFilename) then
4418 raise EglBitmap.Create('file does not exist: ' + aFilename);
4419 fFilename := aFilename;
4420 fs := TFileStream.Create(fFilename, fmOpenRead);
4429 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4430 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4432 {$IFDEF GLB_SUPPORT_PNG_READ}
4433 if not LoadPNG(aStream) then
4435 {$IFDEF GLB_SUPPORT_JPEG_READ}
4436 if not LoadJPEG(aStream) then
4438 if not LoadDDS(aStream) then
4439 if not LoadTGA(aStream) then
4440 if not LoadBMP(aStream) then
4441 raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4444 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4445 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4446 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4451 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4452 GetMem(tmpData, size);
4454 FillChar(tmpData^, size, #$FF);
4455 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
4457 if Assigned(tmpData) then
4461 AddFunc(Self, aFunc, false, aFormat, aArgs);
4464 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4465 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
4467 rs: TResourceStream;
4469 PrepareResType(aResource, aResType);
4470 rs := TResourceStream.Create(aInstance, aResource, aResType);
4478 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4479 procedure TglBitmap.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4481 rs: TResourceStream;
4483 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
4491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4492 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4496 fs := TFileStream.Create(aFileName, fmCreate);
4499 SaveToStream(fs, aFileType);
4505 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4506 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4509 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4510 ftPNG: SavePNG(aStream);
4512 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4513 ftJPEG: SaveJPEG(aStream);
4515 ftDDS: SaveDDS(aStream);
4516 ftTGA: SaveTGA(aStream);
4517 ftBMP: SaveBMP(aStream);
4521 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4522 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4524 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4527 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4528 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4529 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4531 DestData, TmpData, SourceData: pByte;
4532 TempHeight, TempWidth: Integer;
4533 SourceFD, DestFD: TFormatDescriptor;
4534 SourceMD, DestMD: Pointer;
4536 FuncRec: TglBitmapFunctionRec;
4538 Assert(Assigned(Data));
4539 Assert(Assigned(aSource));
4540 Assert(Assigned(aSource.Data));
4543 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4544 SourceFD := TFormatDescriptor.Get(aSource.Format);
4545 DestFD := TFormatDescriptor.Get(aFormat);
4547 if (SourceFD.IsCompressed) then
4548 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
4549 if (DestFD.IsCompressed) then
4550 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
4552 // inkompatible Formats so CreateTemp
4553 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4554 aCreateTemp := true;
4557 TempHeight := Max(1, aSource.Height);
4558 TempWidth := Max(1, aSource.Width);
4560 FuncRec.Sender := Self;
4561 FuncRec.Args := aArgs;
4564 if aCreateTemp then begin
4565 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
4566 DestData := TmpData;
4571 SourceFD.PreparePixel(FuncRec.Source);
4572 DestFD.PreparePixel (FuncRec.Dest);
4574 SourceMD := SourceFD.CreateMappingData;
4575 DestMD := DestFD.CreateMappingData;
4577 FuncRec.Size := aSource.Dimension;
4578 FuncRec.Position.Fields := FuncRec.Size.Fields;
4581 SourceData := aSource.Data;
4582 FuncRec.Position.Y := 0;
4583 while FuncRec.Position.Y < TempHeight do begin
4584 FuncRec.Position.X := 0;
4585 while FuncRec.Position.X < TempWidth do begin
4586 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4588 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4589 inc(FuncRec.Position.X);
4591 inc(FuncRec.Position.Y);
4594 // Updating Image or InternalFormat
4596 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) //be careful, Data could be freed by this method
4597 else if (aFormat <> fFormat) then
4602 SourceFD.FreeMappingData(SourceMD);
4603 DestFD.FreeMappingData(DestMD);
4606 if aCreateTemp and Assigned(TmpData) then
4614 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4615 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4617 Row, RowSize: Integer;
4618 SourceData, TmpData: PByte;
4620 FormatDesc: TFormatDescriptor;
4622 function GetRowPointer(Row: Integer): pByte;
4624 result := aSurface.pixels;
4625 Inc(result, Row * RowSize);
4631 FormatDesc := TFormatDescriptor.Get(Format);
4632 if FormatDesc.IsCompressed then
4633 raise EglBitmapUnsupportedFormat.Create(Format);
4635 if Assigned(Data) then begin
4636 case Trunc(FormatDesc.PixelSize) of
4642 raise EglBitmapUnsupportedFormat.Create(Format);
4645 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4646 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4648 RowSize := FormatDesc.GetSize(FileWidth, 1);
4650 for Row := 0 to FileHeight-1 do begin
4651 TmpData := GetRowPointer(Row);
4652 if Assigned(TmpData) then begin
4653 Move(SourceData^, TmpData^, RowSize);
4654 inc(SourceData, RowSize);
4661 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4662 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4664 pSource, pData, pTempData: PByte;
4665 Row, RowSize, TempWidth, TempHeight: Integer;
4666 IntFormat: TglBitmapFormat;
4667 FormatDesc: TFormatDescriptor;
4669 function GetRowPointer(Row: Integer): pByte;
4671 result := aSurface^.pixels;
4672 Inc(result, Row * RowSize);
4677 if (Assigned(aSurface)) then begin
4678 with aSurface^.format^ do begin
4679 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4680 FormatDesc := TFormatDescriptor.Get(IntFormat);
4681 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4684 if (IntFormat = tfEmpty) then
4685 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4688 TempWidth := aSurface^.w;
4689 TempHeight := aSurface^.h;
4690 RowSize := FormatDesc.GetSize(TempWidth, 1);
4691 GetMem(pData, TempHeight * RowSize);
4694 for Row := 0 to TempHeight -1 do begin
4695 pSource := GetRowPointer(Row);
4696 if (Assigned(pSource)) then begin
4697 Move(pSource^, pTempData^, RowSize);
4698 Inc(pTempData, RowSize);
4701 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4704 if Assigned(pData) then
4711 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4712 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4714 Row, Col, AlphaInterleave: Integer;
4715 pSource, pDest: PByte;
4717 function GetRowPointer(Row: Integer): pByte;
4719 result := aSurface.pixels;
4720 Inc(result, Row * Width);
4725 if Assigned(Data) then begin
4726 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4727 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4729 AlphaInterleave := 0;
4732 AlphaInterleave := 1;
4734 AlphaInterleave := 3;
4738 for Row := 0 to Height -1 do begin
4739 pDest := GetRowPointer(Row);
4740 if Assigned(pDest) then begin
4741 for Col := 0 to Width -1 do begin
4742 Inc(pSource, AlphaInterleave);
4754 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4755 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4759 bmp := TglBitmap2D.Create;
4761 bmp.AssignFromSurface(aSurface);
4762 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4770 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4771 function CreateGrayPalette: HPALETTE;
4776 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
4778 Pal.palVersion := $300;
4779 Pal.palNumEntries := 256;
4781 for Idx := 0 to Pal.palNumEntries - 1 do begin
4782 Pal.palPalEntry[Idx].peRed := Idx;
4783 Pal.palPalEntry[Idx].peGreen := Idx;
4784 Pal.palPalEntry[Idx].peBlue := Idx;
4785 Pal.palPalEntry[Idx].peFlags := 0;
4787 Result := CreatePalette(Pal^);
4791 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4792 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4795 pSource, pData: PByte;
4798 if Assigned(Data) then begin
4799 if Assigned(aBitmap) then begin
4800 aBitmap.Width := Width;
4801 aBitmap.Height := Height;
4804 tfAlpha8, tfLuminance8: begin
4805 aBitmap.PixelFormat := pf8bit;
4806 aBitmap.Palette := CreateGrayPalette;
4809 aBitmap.PixelFormat := pf15bit;
4811 aBitmap.PixelFormat := pf16bit;
4813 aBitmap.PixelFormat := pf24bit;
4815 aBitmap.PixelFormat := pf32bit;
4817 raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.');
4821 for Row := 0 to FileHeight -1 do begin
4822 pData := aBitmap.Scanline[Row];
4823 Move(pSource^, pData^, fRowSize);
4824 Inc(pSource, fRowSize);
4825 if (Format in [tfRGB8, tfRGBA8]) then // swap RGB(A) to BGR(A)
4826 SwapRGB(pData, FileWidth, Format = tfRGBA8);
4833 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4834 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4836 pSource, pData, pTempData: PByte;
4837 Row, RowSize, TempWidth, TempHeight: Integer;
4838 IntFormat: TglBitmapFormat;
4842 if (Assigned(aBitmap)) then begin
4843 case aBitmap.PixelFormat of
4845 IntFormat := tfLuminance8;
4847 IntFormat := tfRGB5A1;
4849 IntFormat := tfR5G6B5;
4851 IntFormat := tfBGR8;
4853 IntFormat := tfBGRA8;
4855 raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.');
4858 TempWidth := aBitmap.Width;
4859 TempHeight := aBitmap.Height;
4860 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
4861 GetMem(pData, TempHeight * RowSize);
4864 for Row := 0 to TempHeight -1 do begin
4865 pSource := aBitmap.Scanline[Row];
4866 if (Assigned(pSource)) then begin
4867 Move(pSource^, pTempData^, RowSize);
4868 Inc(pTempData, RowSize);
4871 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4874 if Assigned(pData) then
4881 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4882 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4884 Row, Col, AlphaInterleave: Integer;
4885 pSource, pDest: PByte;
4889 if Assigned(Data) then begin
4890 if (Format in [tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8]) then begin
4891 if Assigned(aBitmap) then begin
4892 aBitmap.PixelFormat := pf8bit;
4893 aBitmap.Palette := CreateGrayPalette;
4894 aBitmap.Width := Width;
4895 aBitmap.Height := Height;
4899 AlphaInterleave := 1;
4901 AlphaInterleave := 3;
4903 AlphaInterleave := 0;
4909 for Row := 0 to Height -1 do begin
4910 pDest := aBitmap.Scanline[Row];
4911 if Assigned(pDest) then begin
4912 for Col := 0 to Width -1 do begin
4913 Inc(pSource, AlphaInterleave);
4926 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4927 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4931 tex := TglBitmap2D.Create;
4933 tex.AssignFromBitmap(ABitmap);
4934 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4941 {$IFDEF GLB_LAZARUS}
4942 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4943 function TglBitmap.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4945 rid: TRawImageDescription;
4946 FormatDesc: TFormatDescriptor;
4949 if not Assigned(aImage) or (Format = tfEmpty) then
4951 FormatDesc := TFormatDescriptor.Get(Format);
4952 if FormatDesc.IsCompressed then
4955 FillChar(rid{%H-}, SizeOf(rid), 0);
4957 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
4958 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
4959 tfLuminance4Alpha4, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16]) then
4960 rid.Format := ricfGray
4962 rid.Format := ricfRGBA;
4965 rid.Height := Height;
4966 rid.Depth := CountSetBits(FormatDesc.RedMask or FormatDesc.GreenMask or FormatDesc.BlueMask or FormatDesc.AlphaMask);
4967 rid.BitOrder := riboBitsInOrder;
4968 rid.ByteOrder := riboLSBFirst;
4969 rid.LineOrder := riloTopToBottom;
4970 rid.LineEnd := rileTight;
4971 rid.BitsPerPixel := Round(8 * FormatDesc.PixelSize);
4972 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
4973 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
4974 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
4975 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
4976 rid.RedShift := FormatDesc.Shift.r;
4977 rid.GreenShift := FormatDesc.Shift.g;
4978 rid.BlueShift := FormatDesc.Shift.b;
4979 rid.AlphaShift := FormatDesc.Shift.a;
4981 rid.MaskBitsPerPixel := 0;
4982 rid.PaletteColorCount := 0;
4984 aImage.DataDescription := rid;
4987 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
4992 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4993 function TglBitmap.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
4996 FormatDesc: TFormatDescriptor;
5001 procedure CopyConvert;
5003 bfFormat: TbmpBitfieldFormat;
5004 pSourceLine, pDestLine: PByte;
5005 pSourceMD, pDestMD: Pointer;
5007 pixel: TglBitmapPixelData;
5009 bfFormat := TbmpBitfieldFormat.Create;
5010 with aImage.DataDescription do begin
5011 bfFormat.RedMask := ((1 shl RedPrec) - 1) shl RedShift;
5012 bfFormat.GreenMask := ((1 shl GreenPrec) - 1) shl GreenShift;
5013 bfFormat.BlueMask := ((1 shl BluePrec) - 1) shl BlueShift;
5014 bfFormat.AlphaMask := ((1 shl AlphaPrec) - 1) shl AlphaShift;
5015 bfFormat.PixelSize := BitsPerPixel / 8;
5017 pSourceMD := bfFormat.CreateMappingData;
5018 pDestMD := FormatDesc.CreateMappingData;
5020 for y := 0 to aImage.Height-1 do begin
5021 pSourceLine := aImage.PixelData + y * aImage.DataDescription.BytesPerLine;
5022 pDestLine := ImageData + y * Round(FormatDesc.PixelSize * aImage.Width);
5023 for x := 0 to aImage.Width-1 do begin
5024 bfFormat.Unmap(pSourceLine, pixel, pSourceMD);
5025 FormatDesc.Map(pixel, pDestLine, pDestMD);
5029 FormatDesc.FreeMappingData(pDestMD);
5030 bfFormat.FreeMappingData(pSourceMD);
5037 if not Assigned(aImage) then
5039 for f := High(f) downto Low(f) do begin
5040 FormatDesc := TFormatDescriptor.Get(f);
5041 with aImage.DataDescription do
5042 if FormatDesc.MaskMatch(
5043 (QWord(1 shl RedPrec )-1) shl RedShift,
5044 (QWord(1 shl GreenPrec)-1) shl GreenShift,
5045 (QWord(1 shl BluePrec )-1) shl BlueShift,
5046 (QWord(1 shl AlphaPrec)-1) shl AlphaShift) then
5050 if (f = tfEmpty) then
5054 (Round(FormatDesc.PixelSize * 8) = aImage.DataDescription.Depth) and
5055 (aImage.DataDescription.BitsPerPixel = aImage.DataDescription.Depth);
5057 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
5058 ImageData := GetMem(ImageSize);
5061 Move(aImage.PixelData^, ImageData^, ImageSize)
5064 SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method
5066 if Assigned(ImageData) then
5074 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5075 function TglBitmap.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
5077 rid: TRawImageDescription;
5078 FormatDesc: TFormatDescriptor;
5079 Pixel: TglBitmapPixelData;
5085 if not Assigned(aImage) or (Format = tfEmpty) then
5087 FormatDesc := TFormatDescriptor.Get(Format);
5088 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5091 FillChar(rid{%H-}, SizeOf(rid), 0);
5092 rid.Format := ricfGray;
5094 rid.Height := Height;
5095 rid.Depth := CountSetBits(FormatDesc.Range.a);
5096 rid.BitOrder := riboBitsInOrder;
5097 rid.ByteOrder := riboLSBFirst;
5098 rid.LineOrder := riloTopToBottom;
5099 rid.LineEnd := rileTight;
5100 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
5101 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
5106 rid.GreenShift := 0;
5108 rid.AlphaShift := 0;
5110 rid.MaskBitsPerPixel := 0;
5111 rid.PaletteColorCount := 0;
5113 aImage.DataDescription := rid;
5116 srcMD := FormatDesc.CreateMappingData;
5118 FormatDesc.PreparePixel(Pixel);
5120 dst := aImage.PixelData;
5121 for y := 0 to Height-1 do
5122 for x := 0 to Width-1 do begin
5123 FormatDesc.Unmap(src, Pixel, srcMD);
5124 case rid.BitsPerPixel of
5126 dst^ := Pixel.Data.a;
5130 PWord(dst)^ := Pixel.Data.a;
5134 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
5135 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
5136 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
5140 PCardinal(dst)^ := Pixel.Data.a;
5144 raise EglBitmapUnsupportedFormat.Create(Format);
5148 FormatDesc.FreeMappingData(srcMD);
5153 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5154 function TglBitmap.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5158 tex := TglBitmap2D.Create;
5160 tex.AssignFromLazIntfImage(aImage);
5161 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5168 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5169 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
5170 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5172 rs: TResourceStream;
5174 PrepareResType(aResource, aResType);
5175 rs := TResourceStream.Create(aInstance, aResource, aResType);
5177 result := AddAlphaFromStream(rs, aFunc, aArgs);
5183 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5184 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
5185 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5187 rs: TResourceStream;
5189 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
5191 result := AddAlphaFromStream(rs, aFunc, aArgs);
5197 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5198 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5200 if TFormatDescriptor.Get(Format).IsCompressed then
5201 raise EglBitmapUnsupportedFormat.Create(Format);
5202 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
5205 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5206 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5210 FS := TFileStream.Create(aFileName, fmOpenRead);
5212 result := AddAlphaFromStream(FS, aFunc, aArgs);
5218 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5219 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5223 tex := TglBitmap2D.Create(aStream);
5225 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5231 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5232 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5234 DestData, DestData2, SourceData: pByte;
5235 TempHeight, TempWidth: Integer;
5236 SourceFD, DestFD: TFormatDescriptor;
5237 SourceMD, DestMD, DestMD2: Pointer;
5239 FuncRec: TglBitmapFunctionRec;
5243 Assert(Assigned(Data));
5244 Assert(Assigned(aBitmap));
5245 Assert(Assigned(aBitmap.Data));
5247 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
5248 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
5250 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
5251 DestFD := TFormatDescriptor.Get(Format);
5253 if not Assigned(aFunc) then begin
5254 aFunc := glBitmapAlphaFunc;
5255 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5257 FuncRec.Args := aArgs;
5260 TempHeight := aBitmap.FileHeight;
5261 TempWidth := aBitmap.FileWidth;
5263 FuncRec.Sender := Self;
5264 FuncRec.Size := Dimension;
5265 FuncRec.Position.Fields := FuncRec.Size.Fields;
5269 SourceData := aBitmap.Data;
5272 SourceFD.PreparePixel(FuncRec.Source);
5273 DestFD.PreparePixel (FuncRec.Dest);
5275 SourceMD := SourceFD.CreateMappingData;
5276 DestMD := DestFD.CreateMappingData;
5277 DestMD2 := DestFD.CreateMappingData;
5279 FuncRec.Position.Y := 0;
5280 while FuncRec.Position.Y < TempHeight do begin
5281 FuncRec.Position.X := 0;
5282 while FuncRec.Position.X < TempWidth do begin
5283 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5284 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5286 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5287 inc(FuncRec.Position.X);
5289 inc(FuncRec.Position.Y);
5292 SourceFD.FreeMappingData(SourceMD);
5293 DestFD.FreeMappingData(DestMD);
5294 DestFD.FreeMappingData(DestMD2);
5299 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5300 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5302 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5305 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5306 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5308 PixelData: TglBitmapPixelData;
5310 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5311 result := AddAlphaFromColorKeyFloat(
5312 aRed / PixelData.Range.r,
5313 aGreen / PixelData.Range.g,
5314 aBlue / PixelData.Range.b,
5315 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5318 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5319 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5321 values: array[0..2] of Single;
5324 PixelData: TglBitmapPixelData;
5326 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5327 with PixelData do begin
5329 values[1] := aGreen;
5332 for i := 0 to 2 do begin
5333 tmp := Trunc(Range.arr[i] * aDeviation);
5334 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5335 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5340 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5343 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5344 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5346 result := AddAlphaFromValueFloat(aAlpha / $FF);
5349 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5350 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5352 PixelData: TglBitmapPixelData;
5354 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5355 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5358 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5359 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5361 PixelData: TglBitmapPixelData;
5363 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5365 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5366 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5369 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5370 function TglBitmap.RemoveAlpha: Boolean;
5372 FormatDesc: TFormatDescriptor;
5375 FormatDesc := TFormatDescriptor.Get(Format);
5376 if Assigned(Data) then begin
5377 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5378 raise EglBitmapUnsupportedFormat.Create(Format);
5379 result := ConvertTo(FormatDesc.WithoutAlpha);
5383 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5384 function TglBitmap.Clone: TglBitmap;
5391 Temp := (ClassType.Create as TglBitmap);
5393 // copy texture data if assigned
5394 if Assigned(Data) then begin
5395 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5396 GetMem(TempPtr, Size);
5398 Move(Data^, TempPtr^, Size);
5399 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5401 if Assigned(TempPtr) then
5407 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5412 Temp.fTarget := Target;
5413 Temp.fFormat := Format;
5414 Temp.fMipMap := MipMap;
5415 Temp.fAnisotropic := Anisotropic;
5416 Temp.fBorderColor := fBorderColor;
5417 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5418 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5419 Temp.fFilterMin := fFilterMin;
5420 Temp.fFilterMag := fFilterMag;
5421 Temp.fWrapS := fWrapS;
5422 Temp.fWrapT := fWrapT;
5423 Temp.fWrapR := fWrapR;
5424 Temp.fFilename := fFilename;
5425 Temp.fCustomName := fCustomName;
5426 Temp.fCustomNameW := fCustomNameW;
5427 Temp.fCustomData := fCustomData;
5436 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5437 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5439 SourceFD, DestFD: TFormatDescriptor;
5440 SourcePD, DestPD: TglBitmapPixelData;
5441 ShiftData: TShiftData;
5443 function CanCopyDirect: Boolean;
5446 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5447 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5448 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5449 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5452 function CanShift: Boolean;
5455 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5456 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5457 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5458 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5461 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5464 while (aSource > aDest) and (aSource > 0) do begin
5466 aSource := aSource shr 1;
5471 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5472 SourceFD := TFormatDescriptor.Get(Format);
5473 DestFD := TFormatDescriptor.Get(aFormat);
5475 SourceFD.PreparePixel(SourcePD);
5476 DestFD.PreparePixel (DestPD);
5478 if CanCopyDirect then
5479 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5480 else if CanShift then begin
5481 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5482 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5483 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5484 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5485 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5487 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5492 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5493 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5495 if aUseRGB or aUseAlpha then
5496 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5497 ((Byte(aUseAlpha) and 1) shl 1) or
5498 (Byte(aUseRGB) and 1) ));
5501 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5502 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5504 fBorderColor[0] := aRed;
5505 fBorderColor[1] := aGreen;
5506 fBorderColor[2] := aBlue;
5507 fBorderColor[3] := aAlpha;
5508 if (ID > 0) then begin
5510 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5514 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5515 procedure TglBitmap.FreeData;
5520 SetDataPointer(TempPtr, tfEmpty); //be careful, Data could be freed by this method
5523 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5524 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5525 const aAlpha: Byte);
5527 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5530 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5531 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5533 PixelData: TglBitmapPixelData;
5535 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5537 aRed / PixelData.Range.r,
5538 aGreen / PixelData.Range.g,
5539 aBlue / PixelData.Range.b,
5540 aAlpha / PixelData.Range.a);
5543 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5544 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5546 PixelData: TglBitmapPixelData;
5548 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5549 with PixelData do begin
5550 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5551 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5552 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5553 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5555 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5558 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5559 procedure TglBitmap.SetFilter(const aMin, aMag: GLenum);
5564 fFilterMin := GL_NEAREST;
5566 fFilterMin := GL_LINEAR;
5567 GL_NEAREST_MIPMAP_NEAREST:
5568 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5569 GL_LINEAR_MIPMAP_NEAREST:
5570 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5571 GL_NEAREST_MIPMAP_LINEAR:
5572 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5573 GL_LINEAR_MIPMAP_LINEAR:
5574 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5576 raise EglBitmap.Create('SetFilter - Unknow MIN filter.');
5582 fFilterMag := GL_NEAREST;
5584 fFilterMag := GL_LINEAR;
5586 raise EglBitmap.Create('SetFilter - Unknow MAG filter.');
5590 if (ID > 0) then begin
5592 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5594 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5596 GL_NEAREST, GL_LINEAR:
5597 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5598 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5599 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5600 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5601 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5604 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5608 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5609 procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum);
5611 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5615 aTarget := GL_CLAMP;
5618 aTarget := GL_REPEAT;
5620 GL_CLAMP_TO_EDGE: begin
5621 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5622 aTarget := GL_CLAMP_TO_EDGE
5624 aTarget := GL_CLAMP;
5627 GL_CLAMP_TO_BORDER: begin
5628 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5629 aTarget := GL_CLAMP_TO_BORDER
5631 aTarget := GL_CLAMP;
5634 GL_MIRRORED_REPEAT: begin
5635 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5636 aTarget := GL_MIRRORED_REPEAT
5638 raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5641 raise EglBitmap.Create('SetWrap - Unknow Texturewrap');
5646 CheckAndSetWrap(S, fWrapS);
5647 CheckAndSetWrap(T, fWrapT);
5648 CheckAndSetWrap(R, fWrapR);
5650 if (ID > 0) then begin
5652 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5653 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5654 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5658 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5659 procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum);
5661 procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer);
5663 if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or
5664 (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then
5665 fSwizzle[aIndex] := aValue
5667 raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value');
5671 if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
5672 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
5673 CheckAndSetValue(r, 0);
5674 CheckAndSetValue(g, 1);
5675 CheckAndSetValue(b, 2);
5676 CheckAndSetValue(a, 3);
5678 if (ID > 0) then begin
5680 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, PGLint(@fSwizzle[0]));
5684 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5685 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5687 if aEnableTextureUnit then
5690 glBindTexture(Target, ID);
5693 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5694 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5696 if aDisableTextureUnit then
5698 glBindTexture(Target, 0);
5701 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5702 constructor TglBitmap.Create;
5704 if (ClassType = TglBitmap) then
5705 raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5706 {$IFDEF GLB_NATIVE_OGL}
5707 glbReadOpenGLExtensions;
5710 fFormat := glBitmapGetDefaultFormat;
5711 fFreeDataOnDestroy := true;
5714 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5715 constructor TglBitmap.Create(const aFileName: String);
5718 LoadFromFile(aFileName);
5721 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5722 constructor TglBitmap.Create(const aStream: TStream);
5725 LoadFromStream(aStream);
5728 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5729 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte);
5734 if not Assigned(aData) then begin
5735 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5736 GetMem(aData, ImageSize);
5738 FillChar(aData^, ImageSize, #$FF);
5739 SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5741 if Assigned(aData) then
5746 SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5747 fFreeDataOnDestroy := false;
5751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5752 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer);
5755 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5758 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5759 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5762 LoadFromResource(aInstance, aResource, aResType);
5765 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5766 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5769 LoadFromResourceID(aInstance, aResourceID, aResType);
5772 {$IFDEF GLB_SUPPORT_PNG_READ}
5773 {$IF DEFINED(GLB_LAZ_PNG)}
5774 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5775 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5776 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5777 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5780 PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A;
5782 reader: TLazReaderPNG;
5783 intf: TLazIntfImage;
5785 magic: String[MAGIC_LEN];
5788 StreamPos := aStream.Position;
5790 SetLength(magic, MAGIC_LEN);
5791 aStream.Read(magic[1], MAGIC_LEN);
5792 aStream.Position := StreamPos;
5793 if (magic <> PNG_MAGIC) then begin
5798 intf := TLazIntfImage.Create(0, 0);
5799 reader := TLazReaderPNG.Create;
5801 reader.UpdateDescription := true;
5802 reader.ImageRead(aStream, intf);
5803 AssignFromLazIntfImage(intf);
5806 aStream.Position := StreamPos;
5815 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
5816 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5817 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5819 Surface: PSDL_Surface;
5823 RWops := glBitmapCreateRWops(aStream);
5825 if IMG_isPNG(RWops) > 0 then begin
5826 Surface := IMG_LoadPNG_RW(RWops);
5828 AssignFromSurface(Surface);
5831 SDL_FreeSurface(Surface);
5839 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5840 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5841 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5843 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5846 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5847 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5850 signature: array [0..7] of byte;
5852 png_info: png_infop;
5854 TempHeight, TempWidth: Integer;
5855 Format: TglBitmapFormat;
5858 png_rows: array of pByte;
5859 Row, LineSize: Integer;
5863 if not init_libPNG then
5864 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5868 StreamPos := aStream.Position;
5869 aStream.Read(signature{%H-}, 8);
5870 aStream.Position := StreamPos;
5872 if png_check_sig(@signature, 8) <> 0 then begin
5874 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5876 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5879 png_info := png_create_info_struct(png);
5880 if png_info = nil then begin
5881 png_destroy_read_struct(@png, nil, nil);
5882 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5885 // set read callback
5886 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5888 // read informations
5889 png_read_info(png, png_info);
5892 TempHeight := png_get_image_height(png, png_info);
5893 TempWidth := png_get_image_width(png, png_info);
5896 case png_get_color_type(png, png_info) of
5897 PNG_COLOR_TYPE_GRAY:
5898 Format := tfLuminance8;
5899 PNG_COLOR_TYPE_GRAY_ALPHA:
5900 Format := tfLuminance8Alpha8;
5903 PNG_COLOR_TYPE_RGB_ALPHA:
5906 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5909 // cut upper 8 bit from 16 bit formats
5910 if png_get_bit_depth(png, png_info) > 8 then
5911 png_set_strip_16(png);
5913 // expand bitdepth smaller than 8
5914 if png_get_bit_depth(png, png_info) < 8 then
5915 png_set_expand(png);
5917 // allocating mem for scanlines
5918 LineSize := png_get_rowbytes(png, png_info);
5919 GetMem(png_data, TempHeight * LineSize);
5921 SetLength(png_rows, TempHeight);
5922 for Row := Low(png_rows) to High(png_rows) do begin
5923 png_rows[Row] := png_data;
5924 Inc(png_rows[Row], Row * LineSize);
5927 // read complete image into scanlines
5928 png_read_image(png, @png_rows[0]);
5931 png_read_end(png, png_info);
5933 // destroy read struct
5934 png_destroy_read_struct(@png, @png_info, nil);
5936 SetLength(png_rows, 0);
5939 SetDataPointer(png_data, Format, TempWidth, TempHeight); //be careful, Data could be freed by this method
5943 if Assigned(png_data) then
5953 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5954 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5955 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5960 Row, Col, PixSize, LineSize: Integer;
5961 NewImage, pSource, pDest, pAlpha: pByte;
5962 PngFormat: TglBitmapFormat;
5963 FormatDesc: TFormatDescriptor;
5966 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
5971 StreamPos := aStream.Position;
5972 aStream.Read(Header[0], SizeOf(Header));
5973 aStream.Position := StreamPos;
5975 {Test if the header matches}
5976 if Header = PngHeader then begin
5977 Png := TPNGObject.Create;
5979 Png.LoadFromStream(aStream);
5981 case Png.Header.ColorType of
5983 PngFormat := tfLuminance8;
5984 COLOR_GRAYSCALEALPHA:
5985 PngFormat := tfLuminance8Alpha8;
5987 PngFormat := tfBGR8;
5989 PngFormat := tfBGRA8;
5991 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5994 FormatDesc := TFormatDescriptor.Get(PngFormat);
5995 PixSize := Round(FormatDesc.PixelSize);
5996 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
5998 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
6002 case Png.Header.ColorType of
6003 COLOR_RGB, COLOR_GRAYSCALE:
6005 for Row := 0 to Png.Height -1 do begin
6006 Move (Png.Scanline[Row]^, pDest^, LineSize);
6007 Inc(pDest, LineSize);
6010 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
6012 PixSize := PixSize -1;
6014 for Row := 0 to Png.Height -1 do begin
6015 pSource := Png.Scanline[Row];
6016 pAlpha := pByte(Png.AlphaScanline[Row]);
6018 for Col := 0 to Png.Width -1 do begin
6019 Move (pSource^, pDest^, PixSize);
6020 Inc(pSource, PixSize);
6021 Inc(pDest, PixSize);
6030 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
6033 SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); //be careful, Data could be freed by this method
6037 if Assigned(NewImage) then
6049 {$IFDEF GLB_SUPPORT_PNG_WRITE}
6050 {$IFDEF GLB_LIB_PNG}
6051 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6052 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
6054 TStream(png_get_io_ptr(png)).Write(buffer^, size);
6058 {$IF DEFINED(GLB_LAZ_PNG)}
6059 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6060 procedure TglBitmap.SavePNG(const aStream: TStream);
6062 png: TPortableNetworkGraphic;
6063 intf: TLazIntfImage;
6066 png := TPortableNetworkGraphic.Create;
6067 intf := TLazIntfImage.Create(0, 0);
6069 if not AssignToLazIntfImage(intf) then
6070 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6071 intf.GetRawImage(raw);
6072 png.LoadFromRawImage(raw, false);
6073 png.SaveToStream(aStream);
6080 {$ELSEIF DEFINED(GLB_LIB_PNG)}
6081 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6082 procedure TglBitmap.SavePNG(const aStream: TStream);
6085 png_info: png_infop;
6086 png_rows: array of pByte;
6090 FormatDesc: TFormatDescriptor;
6092 if not (ftPNG in FormatGetSupportedFiles(Format)) then
6093 raise EglBitmapUnsupportedFormat.Create(Format);
6095 if not init_libPNG then
6096 raise Exception.Create('unable to initialize libPNG.');
6100 tfAlpha8, tfLuminance8:
6101 ColorType := PNG_COLOR_TYPE_GRAY;
6103 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
6105 ColorType := PNG_COLOR_TYPE_RGB;
6107 ColorType := PNG_COLOR_TYPE_RGBA;
6109 raise EglBitmapUnsupportedFormat.Create(Format);
6112 FormatDesc := TFormatDescriptor.Get(Format);
6113 LineSize := FormatDesc.GetSize(Width, 1);
6115 // creating array for scanline
6116 SetLength(png_rows, Height);
6118 for Row := 0 to Height - 1 do begin
6119 png_rows[Row] := Data;
6120 Inc(png_rows[Row], Row * LineSize)
6124 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
6126 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
6129 png_info := png_create_info_struct(png);
6130 if png_info = nil then begin
6131 png_destroy_write_struct(@png, nil);
6132 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
6135 // set read callback
6136 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
6139 png_set_compression_level(png, 6);
6141 if Format in [tfBGR8, tfBGRA8] then
6144 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
6145 png_write_info(png, png_info);
6146 png_write_image(png, @png_rows[0]);
6147 png_write_end(png, png_info);
6148 png_destroy_write_struct(@png, @png_info);
6150 SetLength(png_rows, 0);
6157 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
6158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6159 procedure TglBitmap.SavePNG(const aStream: TStream);
6163 pSource, pDest: pByte;
6164 X, Y, PixSize: Integer;
6165 ColorType: Cardinal;
6171 if not (ftPNG in FormatGetSupportedFiles (Format)) then
6172 raise EglBitmapUnsupportedFormat.Create(Format);
6175 tfAlpha8, tfLuminance8: begin
6176 ColorType := COLOR_GRAYSCALE;
6180 tfLuminance8Alpha8: begin
6181 ColorType := COLOR_GRAYSCALEALPHA;
6185 tfBGR8, tfRGB8: begin
6186 ColorType := COLOR_RGB;
6190 tfBGRA8, tfRGBA8: begin
6191 ColorType := COLOR_RGBALPHA;
6196 raise EglBitmapUnsupportedFormat.Create(Format);
6199 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
6203 for Y := 0 to Height -1 do begin
6204 pDest := png.ScanLine[Y];
6205 for X := 0 to Width -1 do begin
6206 Move(pSource^, pDest^, PixSize);
6207 Inc(pDest, PixSize);
6208 Inc(pSource, PixSize);
6210 png.AlphaScanline[Y]^[X] := pSource^;
6215 // convert RGB line to BGR
6216 if Format in [tfRGB8, tfRGBA8] then begin
6217 pTemp := png.ScanLine[Y];
6218 for X := 0 to Width -1 do begin
6219 Temp := pByteArray(pTemp)^[0];
6220 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
6221 pByteArray(pTemp)^[2] := Temp;
6228 Png.CompressionLevel := 6;
6229 Png.SaveToStream(aStream);
6237 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6238 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6239 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6240 {$IFDEF GLB_LIB_JPEG}
6242 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
6243 glBitmap_libJPEG_source_mgr = record
6244 pub: jpeg_source_mgr;
6247 SrcBuffer: array [1..4096] of byte;
6250 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
6251 glBitmap_libJPEG_dest_mgr = record
6252 pub: jpeg_destination_mgr;
6254 DestStream: TStream;
6255 DestBuffer: array [1..4096] of byte;
6258 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
6264 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
6270 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
6275 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
6281 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
6287 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6288 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
6290 src: glBitmap_libJPEG_source_mgr_ptr;
6293 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6295 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
6296 if (bytes <= 0) then begin
6297 src^.SrcBuffer[1] := $FF;
6298 src^.SrcBuffer[2] := JPEG_EOI;
6302 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
6303 src^.pub.bytes_in_buffer := bytes;
6308 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6309 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
6311 src: glBitmap_libJPEG_source_mgr_ptr;
6313 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6315 if num_bytes > 0 then begin
6316 // wanted byte isn't in buffer so set stream position and read buffer
6317 if num_bytes > src^.pub.bytes_in_buffer then begin
6318 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
6319 src^.pub.fill_input_buffer(cinfo);
6321 // wanted byte is in buffer so only skip
6322 inc(src^.pub.next_input_byte, num_bytes);
6323 dec(src^.pub.bytes_in_buffer, num_bytes);
6328 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6329 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
6331 dest: glBitmap_libJPEG_dest_mgr_ptr;
6333 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6335 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
6336 // write complete buffer
6337 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
6340 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
6341 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
6347 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6348 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
6351 dest: glBitmap_libJPEG_dest_mgr_ptr;
6353 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6355 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6356 // check for endblock
6357 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6359 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6364 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6369 {$IFDEF GLB_SUPPORT_JPEG_READ}
6370 {$IF DEFINED(GLB_LAZ_JPEG)}
6371 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6372 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6375 JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
6377 intf: TLazIntfImage;
6378 reader: TFPReaderJPEG;
6380 magic: String[MAGIC_LEN];
6383 StreamPos := aStream.Position;
6385 SetLength(magic, MAGIC_LEN);
6386 aStream.Read(magic[1], MAGIC_LEN);
6387 aStream.Position := StreamPos;
6388 if (magic <> JPEG_MAGIC) then begin
6393 reader := TFPReaderJPEG.Create;
6394 intf := TLazIntfImage.Create(0, 0);
6396 intf.DataDescription := GetDescriptionFromDevice(0, 0, 0);
6397 reader.ImageRead(aStream, intf);
6398 AssignFromLazIntfImage(intf);
6401 aStream.Position := StreamPos;
6410 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
6411 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6412 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6414 Surface: PSDL_Surface;
6419 RWops := glBitmapCreateRWops(aStream);
6421 if IMG_isJPG(RWops) > 0 then begin
6422 Surface := IMG_LoadJPG_RW(RWops);
6424 AssignFromSurface(Surface);
6427 SDL_FreeSurface(Surface);
6435 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6436 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6437 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6440 Temp: array[0..1]of Byte;
6442 jpeg: jpeg_decompress_struct;
6443 jpeg_err: jpeg_error_mgr;
6445 IntFormat: TglBitmapFormat;
6447 TempHeight, TempWidth: Integer;
6452 FormatDesc: TFormatDescriptor;
6456 if not init_libJPEG then
6457 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6460 // reading first two bytes to test file and set cursor back to begin
6461 StreamPos := aStream.Position;
6462 aStream.Read({%H-}Temp[0], 2);
6463 aStream.Position := StreamPos;
6465 // if Bitmap then read file.
6466 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6467 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6468 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6471 jpeg.err := jpeg_std_error(@jpeg_err);
6472 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6473 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6475 // decompression struct
6476 jpeg_create_decompress(@jpeg);
6478 // allocation space for streaming methods
6479 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6481 // seeting up custom functions
6482 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6483 pub.init_source := glBitmap_libJPEG_init_source;
6484 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6485 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6486 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6487 pub.term_source := glBitmap_libJPEG_term_source;
6489 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6490 pub.next_input_byte := nil; // until buffer loaded
6492 SrcStream := aStream;
6495 // set global decoding state
6496 jpeg.global_state := DSTATE_START;
6498 // read header of jpeg
6499 jpeg_read_header(@jpeg, false);
6501 // setting output parameter
6502 case jpeg.jpeg_color_space of
6505 jpeg.out_color_space := JCS_GRAYSCALE;
6506 IntFormat := tfLuminance8;
6509 jpeg.out_color_space := JCS_RGB;
6510 IntFormat := tfRGB8;
6514 jpeg_start_decompress(@jpeg);
6516 TempHeight := jpeg.output_height;
6517 TempWidth := jpeg.output_width;
6519 FormatDesc := TFormatDescriptor.Get(IntFormat);
6521 // creating new image
6522 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6526 for Row := 0 to TempHeight -1 do begin
6527 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6528 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6531 // finish decompression
6532 jpeg_finish_decompress(@jpeg);
6534 // destroy decompression
6535 jpeg_destroy_decompress(@jpeg);
6537 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
6541 if Assigned(pImage) then
6551 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6552 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6553 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6558 Temp: array[0..1]of Byte;
6562 // reading first two bytes to test file and set cursor back to begin
6563 StreamPos := aStream.Position;
6564 aStream.Read(Temp[0], 2);
6565 aStream.Position := StreamPos;
6567 // if Bitmap then read file.
6568 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6569 bmp := TBitmap.Create;
6571 jpg := TJPEGImage.Create;
6573 jpg.LoadFromStream(aStream);
6575 result := AssignFromBitmap(bmp);
6587 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6588 {$IF DEFINED(GLB_LAZ_JPEG)}
6589 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6590 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6593 intf: TLazIntfImage;
6596 jpeg := TJPEGImage.Create;
6597 intf := TLazIntfImage.Create(0, 0);
6599 if not AssignToLazIntfImage(intf) then
6600 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6601 intf.GetRawImage(raw);
6602 jpeg.LoadFromRawImage(raw, false);
6603 jpeg.SaveToStream(aStream);
6610 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6611 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6612 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6614 jpeg: jpeg_compress_struct;
6615 jpeg_err: jpeg_error_mgr;
6617 pTemp, pTemp2: pByte;
6619 procedure CopyRow(pDest, pSource: pByte);
6623 for X := 0 to Width - 1 do begin
6624 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6625 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6626 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6633 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6634 raise EglBitmapUnsupportedFormat.Create(Format);
6636 if not init_libJPEG then
6637 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6640 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6641 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6644 jpeg.err := jpeg_std_error(@jpeg_err);
6645 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6646 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6648 // compression struct
6649 jpeg_create_compress(@jpeg);
6651 // allocation space for streaming methods
6652 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6654 // seeting up custom functions
6655 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6656 pub.init_destination := glBitmap_libJPEG_init_destination;
6657 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6658 pub.term_destination := glBitmap_libJPEG_term_destination;
6660 pub.next_output_byte := @DestBuffer[1];
6661 pub.free_in_buffer := Length(DestBuffer);
6663 DestStream := aStream;
6666 // very important state
6667 jpeg.global_state := CSTATE_START;
6668 jpeg.image_width := Width;
6669 jpeg.image_height := Height;
6671 tfAlpha8, tfLuminance8: begin
6672 jpeg.input_components := 1;
6673 jpeg.in_color_space := JCS_GRAYSCALE;
6675 tfRGB8, tfBGR8: begin
6676 jpeg.input_components := 3;
6677 jpeg.in_color_space := JCS_RGB;
6681 jpeg_set_defaults(@jpeg);
6682 jpeg_set_quality(@jpeg, 95, true);
6683 jpeg_start_compress(@jpeg, true);
6686 if Format = tfBGR8 then
6687 GetMem(pTemp2, fRowSize)
6692 for Row := 0 to jpeg.image_height -1 do begin
6694 if Format = tfBGR8 then
6695 CopyRow(pTemp2, pTemp)
6700 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6701 inc(pTemp, fRowSize);
6705 if Format = tfBGR8 then
6708 jpeg_finish_compress(@jpeg);
6709 jpeg_destroy_compress(@jpeg);
6715 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6716 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6717 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6722 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6723 raise EglBitmapUnsupportedFormat.Create(Format);
6725 Bmp := TBitmap.Create;
6727 Jpg := TJPEGImage.Create;
6729 AssignToBitmap(Bmp);
6730 if (Format in [tfAlpha8, tfLuminance8]) then begin
6731 Jpg.Grayscale := true;
6732 Jpg.PixelFormat := jf8Bit;
6735 Jpg.SaveToStream(aStream);
6746 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6747 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6748 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6755 BMP_COMP_BITFIELDS = 3;
6758 TBMPHeader = packed record
6763 bfOffBits: Cardinal;
6766 TBMPInfo = packed record
6772 biCompression: Cardinal;
6773 biSizeImage: Cardinal;
6774 biXPelsPerMeter: Longint;
6775 biYPelsPerMeter: Longint;
6776 biClrUsed: Cardinal;
6777 biClrImportant: Cardinal;
6780 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6781 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6783 //////////////////////////////////////////////////////////////////////////////////////////////////
6784 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6787 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6788 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6791 case aInfo.biCompression of
6793 BMP_COMP_RLE8: begin
6794 raise EglBitmap.Create('RLE compression is not supported');
6796 BMP_COMP_BITFIELDS: begin
6797 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6798 aStream.Read(aMask.r, SizeOf(aMask.r));
6799 aStream.Read(aMask.g, SizeOf(aMask.g));
6800 aStream.Read(aMask.b, SizeOf(aMask.b));
6801 aStream.Read(aMask.a, SizeOf(aMask.a));
6803 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
6807 //get suitable format
6808 case aInfo.biBitCount of
6809 8: result := tfLuminance8;
6810 16: result := tfBGR5;
6811 24: result := tfBGR8;
6812 32: result := tfBGRA8;
6816 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6819 ColorTable: TbmpColorTable;
6822 if (aInfo.biBitCount >= 16) then
6824 aFormat := tfLuminance8;
6825 c := aInfo.biClrUsed;
6827 c := 1 shl aInfo.biBitCount;
6828 SetLength(ColorTable, c);
6829 for i := 0 to c-1 do begin
6830 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6831 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6835 result := TbmpColorTableFormat.Create;
6836 result.PixelSize := aInfo.biBitCount / 8;
6837 result.ColorTable := ColorTable;
6838 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6841 //////////////////////////////////////////////////////////////////////////////////////////////////
6842 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6843 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6845 TmpFormat: TglBitmapFormat;
6846 FormatDesc: TFormatDescriptor;
6849 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6850 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6851 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6852 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6853 aFormat := FormatDesc.Format;
6858 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6859 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6860 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6861 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6863 result := TbmpBitfieldFormat.Create;
6864 result.PixelSize := aInfo.biBitCount / 8;
6865 result.RedMask := aMask.r;
6866 result.GreenMask := aMask.g;
6867 result.BlueMask := aMask.b;
6868 result.AlphaMask := aMask.a;
6875 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6876 PaddingBuff: Cardinal;
6877 LineBuf, ImageData, TmpData: PByte;
6878 SourceMD, DestMD: Pointer;
6879 BmpFormat: TglBitmapFormat;
6882 Mask: TglBitmapColorRec;
6887 SpecialFormat: TFormatDescriptor;
6888 FormatDesc: TFormatDescriptor;
6890 //////////////////////////////////////////////////////////////////////////////////////////////////
6891 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6894 Pixel: TglBitmapPixelData;
6896 aStream.Read(aLineBuf^, rbLineSize);
6897 SpecialFormat.PreparePixel(Pixel);
6898 for i := 0 to Info.biWidth-1 do begin
6899 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6900 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6901 FormatDesc.Map(Pixel, aData, DestMD);
6907 BmpFormat := tfEmpty;
6908 SpecialFormat := nil;
6914 StartPos := aStream.Position;
6915 aStream.Read(Header{%H-}, SizeOf(Header));
6917 if Header.bfType = BMP_MAGIC then begin
6919 BmpFormat := ReadInfo(Info, Mask);
6920 SpecialFormat := ReadColorTable(BmpFormat, Info);
6921 if not Assigned(SpecialFormat) then
6922 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6923 aStream.Position := StartPos + Header.bfOffBits;
6925 if (BmpFormat <> tfEmpty) then begin
6926 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6927 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6928 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6929 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6932 DestMD := FormatDesc.CreateMappingData;
6933 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6934 GetMem(ImageData, ImageSize);
6935 if Assigned(SpecialFormat) then begin
6936 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6937 SourceMD := SpecialFormat.CreateMappingData;
6942 FillChar(ImageData^, ImageSize, $FF);
6943 TmpData := ImageData;
6944 if (Info.biHeight > 0) then
6945 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6946 for i := 0 to Abs(Info.biHeight)-1 do begin
6947 if Assigned(SpecialFormat) then
6948 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6950 aStream.Read(TmpData^, wbLineSize); //else only read data
6951 if (Info.biHeight > 0) then
6952 dec(TmpData, wbLineSize)
6954 inc(TmpData, wbLineSize);
6955 aStream.Read(PaddingBuff{%H-}, Padding);
6957 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method
6960 if Assigned(LineBuf) then
6962 if Assigned(SourceMD) then
6963 SpecialFormat.FreeMappingData(SourceMD);
6964 FormatDesc.FreeMappingData(DestMD);
6967 if Assigned(ImageData) then
6972 raise EglBitmap.Create('LoadBMP - No suitable format found');
6974 aStream.Position := StartPos;
6978 FreeAndNil(SpecialFormat);
6981 else aStream.Position := StartPos;
6984 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6985 procedure TglBitmap.SaveBMP(const aStream: TStream);
6989 Converter: TFormatDescriptor;
6990 FormatDesc: TFormatDescriptor;
6991 SourceFD, DestFD: Pointer;
6992 pData, srcData, dstData, ConvertBuffer: pByte;
6994 Pixel: TglBitmapPixelData;
6995 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6996 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6998 PaddingBuff: Cardinal;
7000 function GetLineWidth : Integer;
7002 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
7006 if not (ftBMP in FormatGetSupportedFiles(Format)) then
7007 raise EglBitmapUnsupportedFormat.Create(Format);
7010 FormatDesc := TFormatDescriptor.Get(Format);
7011 ImageSize := FormatDesc.GetSize(Dimension);
7013 FillChar(Header{%H-}, SizeOf(Header), 0);
7014 Header.bfType := BMP_MAGIC;
7015 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
7016 Header.bfReserved1 := 0;
7017 Header.bfReserved2 := 0;
7018 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
7020 FillChar(Info{%H-}, SizeOf(Info), 0);
7021 Info.biSize := SizeOf(Info);
7022 Info.biWidth := Width;
7023 Info.biHeight := Height;
7025 Info.biCompression := BMP_COMP_RGB;
7026 Info.biSizeImage := ImageSize;
7031 Info.biBitCount := 4;
7032 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
7033 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
7034 Converter := TbmpColorTableFormat.Create;
7035 with (Converter as TbmpColorTableFormat) do begin
7038 Range := glBitmapColorRec($F, $F, $F, $0);
7043 tfR3G3B2, tfLuminance8: begin
7044 Info.biBitCount := 8;
7045 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
7046 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
7047 Converter := TbmpColorTableFormat.Create;
7048 with (Converter as TbmpColorTableFormat) do begin
7051 if (Format = tfR3G3B2) then begin
7052 Range := glBitmapColorRec($7, $7, $3, $0);
7053 Shift := glBitmapShiftRec(0, 3, 6, 0);
7055 Range := glBitmapColorRec($FF, $FF, $FF, $0);
7060 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
7061 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
7062 Info.biBitCount := 16;
7063 Info.biCompression := BMP_COMP_BITFIELDS;
7066 tfBGR8, tfRGB8: begin
7067 Info.biBitCount := 24;
7068 if (Format = tfRGB8) then
7069 Converter := TfdBGR8.Create; //use BGR8 Format Descriptor to Swap RGB Values
7072 tfRGB10, tfRGB10A2, tfRGBA8,
7073 tfBGR10, tfBGR10A2, tfBGRA8: begin
7074 Info.biBitCount := 32;
7075 Info.biCompression := BMP_COMP_BITFIELDS;
7078 raise EglBitmapUnsupportedFormat.Create(Format);
7080 Info.biXPelsPerMeter := 2835;
7081 Info.biYPelsPerMeter := 2835;
7084 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7085 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
7086 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
7088 RedMask := FormatDesc.RedMask;
7089 GreenMask := FormatDesc.GreenMask;
7090 BlueMask := FormatDesc.BlueMask;
7091 AlphaMask := FormatDesc.AlphaMask;
7095 aStream.Write(Header, SizeOf(Header));
7096 aStream.Write(Info, SizeOf(Info));
7099 if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
7100 with (Converter as TbmpColorTableFormat) do
7101 aStream.Write(ColorTable[0].b,
7102 SizeOf(TbmpColorTableEnty) * Length(ColorTable));
7105 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7106 aStream.Write(RedMask, SizeOf(Cardinal));
7107 aStream.Write(GreenMask, SizeOf(Cardinal));
7108 aStream.Write(BlueMask, SizeOf(Cardinal));
7109 aStream.Write(AlphaMask, SizeOf(Cardinal));
7113 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
7114 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
7115 Padding := GetLineWidth - wbLineSize;
7119 inc(pData, (Height-1) * rbLineSize);
7121 // prepare row buffer. But only for RGB because RGBA supports color masks
7122 // so it's possible to change color within the image.
7123 if Assigned(Converter) then begin
7124 FormatDesc.PreparePixel(Pixel);
7125 GetMem(ConvertBuffer, wbLineSize);
7126 SourceFD := FormatDesc.CreateMappingData;
7127 DestFD := Converter.CreateMappingData;
7129 ConvertBuffer := nil;
7132 for LineIdx := 0 to Height - 1 do begin
7134 if Assigned(Converter) then begin
7136 dstData := ConvertBuffer;
7137 for PixelIdx := 0 to Info.biWidth-1 do begin
7138 FormatDesc.Unmap(srcData, Pixel, SourceFD);
7139 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
7140 Converter.Map(Pixel, dstData, DestFD);
7142 aStream.Write(ConvertBuffer^, wbLineSize);
7144 aStream.Write(pData^, rbLineSize);
7146 dec(pData, rbLineSize);
7147 if (Padding > 0) then
7148 aStream.Write(PaddingBuff, Padding);
7151 // destroy row buffer
7152 if Assigned(ConvertBuffer) then begin
7153 FormatDesc.FreeMappingData(SourceFD);
7154 Converter.FreeMappingData(DestFD);
7155 FreeMem(ConvertBuffer);
7159 if Assigned(Converter) then
7164 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7165 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7166 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7168 TTGAHeader = packed record
7172 //ColorMapSpec: Array[0..4] of Byte;
7173 ColorMapStart: Word;
7174 ColorMapLength: Word;
7175 ColorMapEntrySize: Byte;
7185 TGA_UNCOMPRESSED_RGB = 2;
7186 TGA_UNCOMPRESSED_GRAY = 3;
7187 TGA_COMPRESSED_RGB = 10;
7188 TGA_COMPRESSED_GRAY = 11;
7190 TGA_NONE_COLOR_TABLE = 0;
7192 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7193 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
7196 ImageData: System.PByte;
7197 StartPosition: Int64;
7198 PixelSize, LineSize: Integer;
7199 tgaFormat: TglBitmapFormat;
7200 FormatDesc: TFormatDescriptor;
7201 Counter: packed record
7203 low, high, dir: Integer;
7210 ////////////////////////////////////////////////////////////////////////////////////////
7211 procedure ReadUncompressed;
7214 buf, tmp1, tmp2: System.PByte;
7217 if (Counter.X.dir < 0) then
7218 GetMem(buf, LineSize);
7220 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
7222 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
7223 if (Counter.X.dir < 0) then begin //flip X
7224 aStream.Read(buf^, LineSize);
7226 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
7227 for i := 0 to Header.Width-1 do begin //for all pixels in line
7228 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
7233 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
7236 aStream.Read(tmp1^, LineSize);
7237 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
7240 if Assigned(buf) then
7245 ////////////////////////////////////////////////////////////////////////////////////////
7246 procedure ReadCompressed;
7248 /////////////////////////////////////////////////////////////////
7250 TmpData: System.PByte;
7251 LinePixelsRead: Integer;
7252 procedure CheckLine;
7254 if (LinePixelsRead >= Header.Width) then begin
7255 LinePixelsRead := 0;
7256 inc(Counter.Y.low, Counter.Y.dir); //next line index
7257 TmpData := ImageData;
7258 inc(TmpData, Counter.Y.low * LineSize); //set line
7259 if (Counter.X.dir < 0) then //if x flipped then
7260 inc(TmpData, LineSize - PixelSize); //set last pixel
7264 /////////////////////////////////////////////////////////////////
7267 CacheSize, CachePos: Integer;
7268 procedure CachedRead(out Buffer; Count: Integer);
7272 if (CachePos + Count > CacheSize) then begin
7273 //if buffer overflow save non read bytes
7275 if (CacheSize - CachePos > 0) then begin
7276 BytesRead := CacheSize - CachePos;
7277 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
7278 inc(CachePos, BytesRead);
7281 //load cache from file
7282 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
7283 aStream.Read(Cache^, CacheSize);
7286 //read rest of requested bytes
7287 if (Count - BytesRead > 0) then begin
7288 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
7289 inc(CachePos, Count - BytesRead);
7292 //if no buffer overflow just read the data
7293 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
7294 inc(CachePos, Count);
7298 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
7303 inc(aBuffer, Counter.X.dir);
7306 PWord(aBuffer)^ := PWord(aData)^;
7307 inc(aBuffer, 2 * Counter.X.dir);
7310 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
7311 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
7312 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
7313 inc(aBuffer, 3 * Counter.X.dir);
7316 PCardinal(aBuffer)^ := PCardinal(aData)^;
7317 inc(aBuffer, 4 * Counter.X.dir);
7323 TotalPixelsToRead, TotalPixelsRead: Integer;
7325 buf: array [0..3] of Byte; //1 pixel is max 32bit long
7326 PixelRepeat: Boolean;
7327 PixelsToRead, PixelCount: Integer;
7332 TotalPixelsToRead := Header.Width * Header.Height;
7333 TotalPixelsRead := 0;
7334 LinePixelsRead := 0;
7336 GetMem(Cache, CACHE_SIZE);
7338 TmpData := ImageData;
7339 inc(TmpData, Counter.Y.low * LineSize); //set line
7340 if (Counter.X.dir < 0) then //if x flipped then
7341 inc(TmpData, LineSize - PixelSize); //set last pixel
7345 CachedRead(Temp, 1);
7346 PixelRepeat := (Temp and $80) > 0;
7347 PixelsToRead := (Temp and $7F) + 1;
7348 inc(TotalPixelsRead, PixelsToRead);
7351 CachedRead(buf[0], PixelSize);
7352 while (PixelsToRead > 0) do begin
7354 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
7355 while (PixelCount > 0) do begin
7356 if not PixelRepeat then
7357 CachedRead(buf[0], PixelSize);
7358 PixelToBuffer(@buf[0], TmpData);
7359 inc(LinePixelsRead);
7364 until (TotalPixelsRead >= TotalPixelsToRead);
7370 function IsGrayFormat: Boolean;
7372 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
7378 // reading header to test file and set cursor back to begin
7379 StartPosition := aStream.Position;
7380 aStream.Read(Header{%H-}, SizeOf(Header));
7382 // no colormapped files
7383 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
7384 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
7387 if Header.ImageID <> 0 then // skip image ID
7388 aStream.Position := aStream.Position + Header.ImageID;
7390 tgaFormat := tfEmpty;
7392 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
7393 0: tgaFormat := tfLuminance8;
7394 8: tgaFormat := tfAlpha8;
7397 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
7398 0: tgaFormat := tfLuminance16;
7399 8: tgaFormat := tfLuminance8Alpha8;
7400 end else case (Header.ImageDesc and $F) of
7401 0: tgaFormat := tfBGR5;
7402 1: tgaFormat := tfBGR5A1;
7403 4: tgaFormat := tfBGRA4;
7406 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7407 0: tgaFormat := tfBGR8;
7410 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7411 2: tgaFormat := tfBGR10A2;
7412 8: tgaFormat := tfBGRA8;
7416 if (tgaFormat = tfEmpty) then
7417 raise EglBitmap.Create('LoadTga - unsupported format');
7419 FormatDesc := TFormatDescriptor.Get(tgaFormat);
7420 PixelSize := FormatDesc.GetSize(1, 1);
7421 LineSize := FormatDesc.GetSize(Header.Width, 1);
7423 GetMem(ImageData, LineSize * Header.Height);
7426 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7427 Counter.X.low := Header.Height-1;;
7428 Counter.X.high := 0;
7429 Counter.X.dir := -1;
7432 Counter.X.high := Header.Height-1;
7437 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7439 Counter.Y.high := Header.Height-1;
7442 Counter.Y.low := Header.Height-1;;
7443 Counter.Y.high := 0;
7444 Counter.Y.dir := -1;
7448 case Header.ImageType of
7449 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7451 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7455 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method
7458 if Assigned(ImageData) then
7463 aStream.Position := StartPosition;
7466 else aStream.Position := StartPosition;
7469 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7470 procedure TglBitmap.SaveTGA(const aStream: TStream);
7473 LineSize, Size, x, y: Integer;
7474 Pixel: TglBitmapPixelData;
7475 LineBuf, SourceData, DestData: PByte;
7476 SourceMD, DestMD: Pointer;
7477 FormatDesc: TFormatDescriptor;
7478 Converter: TFormatDescriptor;
7480 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7481 raise EglBitmapUnsupportedFormat.Create(Format);
7484 FillChar(Header{%H-}, SizeOf(Header), 0);
7487 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7488 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7489 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7491 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7494 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7496 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7497 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7499 else if (Format in [tfBGR8, tfRGB8]) then
7507 Header.ImageDesc := 1 and $F;
7508 tfRGB10A2, tfBGR10A2:
7509 Header.ImageDesc := 2 and $F;
7511 Header.ImageDesc := 4 and $F;
7512 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7513 Header.ImageDesc := 8 and $F;
7516 Header.Width := Width;
7517 Header.Height := Height;
7518 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7519 aStream.Write(Header, SizeOf(Header));
7521 // convert RGB(A) to BGR(A)
7523 FormatDesc := TFormatDescriptor.Get(Format);
7524 Size := FormatDesc.GetSize(Dimension);
7525 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7526 if (FormatDesc.RGBInverted = tfEmpty) then
7527 raise EglBitmap.Create('inverted RGB format is empty');
7528 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7529 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7530 (Converter.PixelSize <> FormatDesc.PixelSize) then
7531 raise EglBitmap.Create('invalid inverted RGB format');
7534 if Assigned(Converter) then begin
7535 LineSize := FormatDesc.GetSize(Width, 1);
7536 GetMem(LineBuf, LineSize);
7537 SourceMD := FormatDesc.CreateMappingData;
7538 DestMD := Converter.CreateMappingData;
7541 for y := 0 to Height-1 do begin
7542 DestData := LineBuf;
7543 for x := 0 to Width-1 do begin
7544 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7545 Converter.Map(Pixel, DestData, DestMD);
7547 aStream.Write(LineBuf^, LineSize);
7551 FormatDesc.FreeMappingData(SourceMD);
7552 FormatDesc.FreeMappingData(DestMD);
7555 aStream.Write(Data^, Size);
7558 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7559 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7560 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7562 DDS_MAGIC: Cardinal = $20534444;
7564 // DDS_header.dwFlags
7565 DDSD_CAPS = $00000001;
7566 DDSD_HEIGHT = $00000002;
7567 DDSD_WIDTH = $00000004;
7568 DDSD_PIXELFORMAT = $00001000;
7570 // DDS_header.sPixelFormat.dwFlags
7571 DDPF_ALPHAPIXELS = $00000001;
7572 DDPF_ALPHA = $00000002;
7573 DDPF_FOURCC = $00000004;
7574 DDPF_RGB = $00000040;
7575 DDPF_LUMINANCE = $00020000;
7577 // DDS_header.sCaps.dwCaps1
7578 DDSCAPS_TEXTURE = $00001000;
7580 // DDS_header.sCaps.dwCaps2
7581 DDSCAPS2_CUBEMAP = $00000200;
7583 D3DFMT_DXT1 = $31545844;
7584 D3DFMT_DXT3 = $33545844;
7585 D3DFMT_DXT5 = $35545844;
7588 TDDSPixelFormat = packed record
7592 dwRGBBitCount: Cardinal;
7593 dwRBitMask: Cardinal;
7594 dwGBitMask: Cardinal;
7595 dwBBitMask: Cardinal;
7596 dwABitMask: Cardinal;
7599 TDDSCaps = packed record
7603 dwReserved: Cardinal;
7606 TDDSHeader = packed record
7611 dwPitchOrLinearSize: Cardinal;
7613 dwMipMapCount: Cardinal;
7614 dwReserved: array[0..10] of Cardinal;
7615 PixelFormat: TDDSPixelFormat;
7617 dwReserved2: Cardinal;
7620 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7621 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7624 Converter: TbmpBitfieldFormat;
7626 function GetDDSFormat: TglBitmapFormat;
7628 fd: TFormatDescriptor;
7630 Range: TglBitmapColorRec;
7634 with Header.PixelFormat do begin
7636 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7637 case Header.PixelFormat.dwFourCC of
7638 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7639 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7640 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7642 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7644 //find matching format
7645 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7646 fd := TFormatDescriptor.Get(result);
7647 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7648 (8 * fd.PixelSize = dwRGBBitCount) then
7652 //find format with same Range
7653 Range.r := dwRBitMask;
7654 Range.g := dwGBitMask;
7655 Range.b := dwBBitMask;
7656 Range.a := dwABitMask;
7657 for i := 0 to 3 do begin
7658 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7659 Range.arr[i] := Range.arr[i] shr 1;
7661 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7662 fd := TFormatDescriptor.Get(result);
7665 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7673 //no format with same range found -> use default
7674 if (result = tfEmpty) then begin
7675 if (dwABitMask > 0) then
7681 Converter := TbmpBitfieldFormat.Create;
7682 Converter.RedMask := dwRBitMask;
7683 Converter.GreenMask := dwGBitMask;
7684 Converter.BlueMask := dwBBitMask;
7685 Converter.AlphaMask := dwABitMask;
7686 Converter.PixelSize := dwRGBBitCount / 8;
7693 x, y, LineSize, RowSize, Magic: Cardinal;
7694 NewImage, TmpData, RowData, SrcData: System.PByte;
7695 SourceMD, DestMD: Pointer;
7696 Pixel: TglBitmapPixelData;
7697 ddsFormat: TglBitmapFormat;
7698 FormatDesc: TFormatDescriptor;
7703 StreamPos := aStream.Position;
7706 aStream.Read(Magic{%H-}, sizeof(Magic));
7707 if (Magic <> DDS_MAGIC) then begin
7708 aStream.Position := StreamPos;
7713 aStream.Read(Header{%H-}, sizeof(Header));
7714 if (Header.dwSize <> SizeOf(Header)) or
7715 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7716 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7718 aStream.Position := StreamPos;
7722 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7723 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
7725 ddsFormat := GetDDSFormat;
7727 if (ddsFormat = tfEmpty) then
7728 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7730 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7731 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7732 GetMem(NewImage, Header.dwHeight * LineSize);
7734 TmpData := NewImage;
7737 if Assigned(Converter) then begin
7738 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7739 GetMem(RowData, RowSize);
7740 SourceMD := Converter.CreateMappingData;
7741 DestMD := FormatDesc.CreateMappingData;
7743 for y := 0 to Header.dwHeight-1 do begin
7744 TmpData := NewImage;
7745 inc(TmpData, y * LineSize);
7747 aStream.Read(SrcData^, RowSize);
7748 for x := 0 to Header.dwWidth-1 do begin
7749 Converter.Unmap(SrcData, Pixel, SourceMD);
7750 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7751 FormatDesc.Map(Pixel, TmpData, DestMD);
7755 Converter.FreeMappingData(SourceMD);
7756 FormatDesc.FreeMappingData(DestMD);
7762 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7763 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7764 for Y := 0 to Header.dwHeight-1 do begin
7765 aStream.Read(TmpData^, RowSize);
7766 Inc(TmpData, LineSize);
7771 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7772 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7773 for Y := 0 to Header.dwHeight-1 do begin
7774 aStream.Read(TmpData^, RowSize);
7775 Inc(TmpData, LineSize);
7778 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7780 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method
7783 if Assigned(NewImage) then
7788 FreeAndNil(Converter);
7792 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7793 procedure TglBitmap.SaveDDS(const aStream: TStream);
7796 FormatDesc: TFormatDescriptor;
7798 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7799 raise EglBitmapUnsupportedFormat.Create(Format);
7801 FormatDesc := TFormatDescriptor.Get(Format);
7804 FillChar(Header{%H-}, SizeOf(Header), 0);
7805 Header.dwSize := SizeOf(Header);
7806 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7808 Header.dwWidth := Max(1, Width);
7809 Header.dwHeight := Max(1, Height);
7812 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7815 Header.PixelFormat.dwSize := sizeof(Header);
7816 if (FormatDesc.IsCompressed) then begin
7817 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7819 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7820 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7821 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7823 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7824 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7825 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7826 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7827 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7828 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7829 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7830 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7831 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7833 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7834 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7835 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7836 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7837 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7838 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7841 if (FormatDesc.HasAlpha) then
7842 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7844 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7845 aStream.Write(Header, SizeOf(Header));
7846 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7849 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7850 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7851 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7852 procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7853 const aWidth: Integer; const aHeight: Integer);
7858 if (aHeight > 1) then begin
7859 Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1);
7860 GetMem(pTemp, Size);
7862 Move(aData^, pTemp^, Size);
7871 inherited SetDataPointer(pTemp, aFormat, aWidth);
7874 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7875 function TglBitmap1D.FlipHorz: Boolean;
7878 pTempDest, pDest, pSource: PByte;
7880 result := inherited FlipHorz;
7881 if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin
7883 GetMem(pDest, fRowSize);
7886 Inc(pTempDest, fRowSize);
7887 for Col := 0 to Width-1 do begin
7888 dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data
7889 Move(pSource^, pTempDest^, fPixelSize);
7890 Inc(pSource, fPixelSize);
7892 SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method
7895 if Assigned(pDest) then
7902 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7903 procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean);
7905 FormatDesc: TFormatDescriptor;
7908 FormatDesc := TFormatDescriptor.Get(Format);
7909 if FormatDesc.IsCompressed then begin
7910 if not Assigned(glCompressedTexImage1D) then
7911 raise EglBitmap.Create('compressed formats not supported by video adapter');
7912 glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
7913 end else if aBuildWithGlu then
7914 gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7916 glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7919 if (FreeDataAfterGenTexture) then
7923 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7924 procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean);
7926 BuildWithGlu, TexRec: Boolean;
7929 if Assigned(Data) then begin
7930 // Check Texture Size
7931 if (aTestTextureSize) then begin
7932 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7934 if (Width > TexSize) then
7935 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7937 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7938 (Target = GL_TEXTURE_RECTANGLE);
7939 if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7940 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7944 SetupParameters(BuildWithGlu);
7945 UploadData(BuildWithGlu);
7946 glAreTexturesResident(1, @fID, @fIsResident);
7950 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7951 procedure TglBitmap1D.AfterConstruction;
7954 Target := GL_TEXTURE_1D;
7957 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7958 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7959 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7960 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7962 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7963 result := fLines[aIndex]
7968 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7969 procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7970 const aWidth: Integer; const aHeight: Integer);
7972 Idx, LineWidth: Integer;
7974 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7976 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7978 if Assigned(Data) then begin
7979 SetLength(fLines, GetHeight);
7980 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7982 for Idx := 0 to GetHeight-1 do begin
7983 fLines[Idx] := Data;
7984 Inc(fLines[Idx], Idx * LineWidth);
7987 else SetLength(fLines, 0);
7989 SetLength(fLines, 0);
7993 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7994 procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
7996 FormatDesc: TFormatDescriptor;
7998 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
8000 FormatDesc := TFormatDescriptor.Get(Format);
8001 if FormatDesc.IsCompressed then begin
8002 if not Assigned(glCompressedTexImage2D) then
8003 raise EglBitmap.Create('compressed formats not supported by video adapter');
8004 glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
8005 end else if aBuildWithGlu then begin
8006 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
8007 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
8009 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
8010 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
8014 if (FreeDataAfterGenTexture) then
8018 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8019 procedure TglBitmap2D.AfterConstruction;
8022 Target := GL_TEXTURE_2D;
8025 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8026 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
8029 Size, w, h: Integer;
8030 FormatDesc: TFormatDescriptor;
8032 FormatDesc := TFormatDescriptor.Get(aFormat);
8033 if FormatDesc.IsCompressed then
8034 raise EglBitmapUnsupportedFormat.Create(aFormat);
8036 w := aRight - aLeft;
8037 h := aBottom - aTop;
8038 Size := FormatDesc.GetSize(w, h);
8041 glPixelStorei(GL_PACK_ALIGNMENT, 1);
8042 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8043 SetDataPointer(Temp, aFormat, w, h); //be careful, Data could be freed by this method
8046 if Assigned(Temp) then
8052 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8053 procedure TglBitmap2D.GetDataFromTexture;
8056 TempWidth, TempHeight: Integer;
8057 TempIntFormat: GLint;
8058 IntFormat, f: TglBitmapFormat;
8059 FormatDesc: TFormatDescriptor;
8064 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
8065 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
8066 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
8068 IntFormat := tfEmpty;
8069 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
8070 FormatDesc := TFormatDescriptor.Get(f);
8071 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
8072 IntFormat := FormatDesc.Format;
8077 // Getting data from OpenGL
8078 FormatDesc := TFormatDescriptor.Get(IntFormat);
8079 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
8081 if FormatDesc.IsCompressed then begin
8082 if not Assigned(glGetCompressedTexImage) then
8083 raise EglBitmap.Create('compressed formats not supported by video adapter');
8084 glGetCompressedTexImage(Target, 0, Temp)
8086 glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8087 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
8089 if Assigned(Temp) then
8095 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8096 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
8098 BuildWithGlu, PotTex, TexRec: Boolean;
8101 if Assigned(Data) then begin
8102 // Check Texture Size
8103 if (aTestTextureSize) then begin
8104 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8106 if ((Height > TexSize) or (Width > TexSize)) then
8107 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8109 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
8110 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
8111 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8112 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8116 SetupParameters(BuildWithGlu);
8117 UploadData(Target, BuildWithGlu);
8118 glAreTexturesResident(1, @fID, @fIsResident);
8122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8123 function TglBitmap2D.FlipHorz: Boolean;
8126 TempDestData, DestData, SourceData: PByte;
8129 result := inherited FlipHorz;
8130 if Assigned(Data) then begin
8132 ImgSize := Height * fRowSize;
8133 GetMem(DestData, ImgSize);
8135 TempDestData := DestData;
8136 Dec(TempDestData, fRowSize + fPixelSize);
8137 for Row := 0 to Height -1 do begin
8138 Inc(TempDestData, fRowSize * 2);
8139 for Col := 0 to Width -1 do begin
8140 Move(SourceData^, TempDestData^, fPixelSize);
8141 Inc(SourceData, fPixelSize);
8142 Dec(TempDestData, fPixelSize);
8145 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8148 if Assigned(DestData) then
8155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8156 function TglBitmap2D.FlipVert: Boolean;
8159 TempDestData, DestData, SourceData: PByte;
8161 result := inherited FlipVert;
8162 if Assigned(Data) then begin
8164 GetMem(DestData, Height * fRowSize);
8166 TempDestData := DestData;
8167 Inc(TempDestData, Width * (Height -1) * fPixelSize);
8168 for Row := 0 to Height -1 do begin
8169 Move(SourceData^, TempDestData^, fRowSize);
8170 Dec(TempDestData, fRowSize);
8171 Inc(SourceData, fRowSize);
8173 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8176 if Assigned(DestData) then
8183 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8184 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8185 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8187 TMatrixItem = record
8192 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
8193 TglBitmapToNormalMapRec = Record
8195 Heights: array of Single;
8196 MatrixU : array of TMatrixItem;
8197 MatrixV : array of TMatrixItem;
8201 ONE_OVER_255 = 1 / 255;
8203 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8204 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
8208 with FuncRec do begin
8210 Source.Data.r * LUMINANCE_WEIGHT_R +
8211 Source.Data.g * LUMINANCE_WEIGHT_G +
8212 Source.Data.b * LUMINANCE_WEIGHT_B;
8213 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
8217 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8218 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
8221 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
8224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8225 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
8227 TVec = Array[0..2] of Single;
8234 function GetHeight(X, Y: Integer): Single;
8236 with FuncRec do begin
8237 X := Max(0, Min(Size.X -1, X));
8238 Y := Max(0, Min(Size.Y -1, Y));
8239 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
8244 with FuncRec do begin
8245 with PglBitmapToNormalMapRec(Args)^ do begin
8247 for Idx := Low(MatrixU) to High(MatrixU) do
8248 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
8251 for Idx := Low(MatrixU) to High(MatrixU) do
8252 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
8254 Vec[0] := -du * Scale;
8255 Vec[1] := -dv * Scale;
8260 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8261 if Len <> 0 then begin
8262 Vec[0] := Vec[0] * Len;
8263 Vec[1] := Vec[1] * Len;
8264 Vec[2] := Vec[2] * Len;
8268 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
8269 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
8270 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
8274 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8275 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
8277 Rec: TglBitmapToNormalMapRec;
8279 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
8281 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
8282 Matrix[Index].X := X;
8283 Matrix[Index].Y := Y;
8284 Matrix[Index].W := W;
8289 if TFormatDescriptor.Get(Format).IsCompressed then
8290 raise EglBitmapUnsupportedFormat.Create(Format);
8292 if aScale > 100 then
8294 else if aScale < -100 then
8297 Rec.Scale := aScale;
8299 SetLength(Rec.Heights, Width * Height);
8303 SetLength(Rec.MatrixU, 2);
8304 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
8305 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
8307 SetLength(Rec.MatrixV, 2);
8308 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
8309 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
8313 SetLength(Rec.MatrixU, 6);
8314 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
8315 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
8316 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
8317 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
8318 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
8319 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
8321 SetLength(Rec.MatrixV, 6);
8322 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
8323 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
8324 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
8325 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
8326 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
8327 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
8331 SetLength(Rec.MatrixU, 6);
8332 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
8333 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
8334 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
8335 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
8336 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
8337 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
8339 SetLength(Rec.MatrixV, 6);
8340 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
8341 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
8342 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
8343 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
8344 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
8345 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
8349 SetLength(Rec.MatrixU, 20);
8350 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
8351 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
8352 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
8353 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
8354 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
8355 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
8356 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
8357 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
8358 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
8359 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
8360 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
8361 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
8362 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
8363 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
8364 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
8365 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
8366 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
8367 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
8368 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
8369 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
8371 SetLength(Rec.MatrixV, 20);
8372 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
8373 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
8374 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
8375 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
8376 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
8377 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
8378 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
8379 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
8380 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
8381 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
8382 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
8383 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
8384 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
8385 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
8386 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
8387 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
8388 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
8389 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
8390 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
8391 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
8396 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
8397 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
8399 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
8400 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
8402 SetLength(Rec.Heights, 0);
8406 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8407 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8408 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8409 procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean);
8411 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8414 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8415 procedure TglBitmapCubeMap.AfterConstruction;
8419 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8420 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8423 Target := GL_TEXTURE_CUBE_MAP;
8424 fGenMode := GL_REFLECTION_MAP;
8427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8428 procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean);
8430 BuildWithGlu: Boolean;
8433 if (aTestTextureSize) then begin
8434 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8436 if (Height > TexSize) or (Width > TexSize) then
8437 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8439 if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8440 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8445 SetupParameters(BuildWithGlu);
8446 UploadData(aCubeTarget, BuildWithGlu);
8449 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8450 procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean);
8452 inherited Bind (aEnableTextureUnit);
8453 if aEnableTexCoordsGen then begin
8454 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8455 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8456 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8457 glEnable(GL_TEXTURE_GEN_S);
8458 glEnable(GL_TEXTURE_GEN_T);
8459 glEnable(GL_TEXTURE_GEN_R);
8463 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8464 procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean);
8466 inherited Unbind(aDisableTextureUnit);
8467 if aDisableTexCoordsGen then begin
8468 glDisable(GL_TEXTURE_GEN_S);
8469 glDisable(GL_TEXTURE_GEN_T);
8470 glDisable(GL_TEXTURE_GEN_R);
8474 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8475 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8476 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8478 TVec = Array[0..2] of Single;
8479 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8481 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8482 TglBitmapNormalMapRec = record
8484 Func: TglBitmapNormalMapGetVectorFunc;
8487 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8488 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8490 aVec[0] := aHalfSize;
8491 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8492 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8495 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8496 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8498 aVec[0] := - aHalfSize;
8499 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8500 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8503 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8504 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8506 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8507 aVec[1] := aHalfSize;
8508 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8511 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8512 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8514 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8515 aVec[1] := - aHalfSize;
8516 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8519 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8520 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8522 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8523 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8524 aVec[2] := aHalfSize;
8527 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8528 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8530 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8531 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8532 aVec[2] := - aHalfSize;
8535 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8536 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8542 with FuncRec do begin
8543 with PglBitmapNormalMapRec(Args)^ do begin
8544 Func(Vec, Position, HalfSize);
8547 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8548 if Len <> 0 then begin
8549 Vec[0] := Vec[0] * Len;
8550 Vec[1] := Vec[1] * Len;
8551 Vec[2] := Vec[2] * Len;
8554 // Scale Vector and AddVectro
8555 Vec[0] := Vec[0] * 0.5 + 0.5;
8556 Vec[1] := Vec[1] * 0.5 + 0.5;
8557 Vec[2] := Vec[2] * 0.5 + 0.5;
8562 Dest.Data.arr[i] := Round(Vec[i] * 255);
8566 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8567 procedure TglBitmapNormalMap.AfterConstruction;
8570 fGenMode := GL_NORMAL_MAP;
8573 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8574 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean);
8576 Rec: TglBitmapNormalMapRec;
8577 SizeRec: TglBitmapPixelPosition;
8579 Rec.HalfSize := aSize div 2;
8580 FreeDataAfterGenTexture := false;
8582 SizeRec.Fields := [ffX, ffY];
8587 Rec.Func := glBitmapNormalMapPosX;
8588 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8589 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize);
8592 Rec.Func := glBitmapNormalMapNegX;
8593 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8594 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize);
8597 Rec.Func := glBitmapNormalMapPosY;
8598 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8599 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize);
8602 Rec.Func := glBitmapNormalMapNegY;
8603 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8604 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize);
8607 Rec.Func := glBitmapNormalMapPosZ;
8608 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8609 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize);
8612 Rec.Func := glBitmapNormalMapNegZ;
8613 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8614 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize);
8619 glBitmapSetDefaultFormat (tfEmpty);
8620 glBitmapSetDefaultMipmap (mmMipmap);
8621 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8622 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8623 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8625 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8626 glBitmapSetDefaultDeleteTextureOnFree (true);
8628 TFormatDescriptor.Init;
8630 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8631 OpenGLInitialized := false;
8632 InitOpenGLCS := TCriticalSection.Create;
8636 TFormatDescriptor.Finalize;
8638 {$IFDEF GLB_NATIVE_OGL}
8639 if Assigned(GL_LibHandle) then
8640 glbFreeLibrary(GL_LibHandle);
8642 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8643 if Assigned(GLU_LibHandle) then
8644 glbFreeLibrary(GLU_LibHandle);
8645 FreeAndNil(InitOpenGLCS);