1 {***********************************************************
2 glBitmap by Steffen Xonna aka Lossy eX (2003-2008)
3 http://www.opengl24.de/index.php?cat=header&file=glbitmap
5 modified by Delphi OpenGL Community (http://delphigl.com/) (2013)
7 ------------------------------------------------------------
8 The contents of this file are used with permission, subject to
9 the Mozilla Public License Version 1.1 (the "License"); you may
10 not use this file except in compliance with the License. You may
11 obtain a copy of the License at
12 http://www.mozilla.org/MPL/MPL-1.1.html
13 ------------------------------------------------------------
14 Version 3.0.0 unstable
15 ------------------------------------------------------------
18 - refactoring of the complete library
20 - The define GLB_DELPHI dosn't check versions anymore. If you say you are using delphi
21 then it's your problem if that isn't true. This prevents the unit for incompatibility
22 with newer versions of Delphi.
23 - Problems with D2009+ resolved (Thanks noeska and all i forgot)
24 - GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson)
26 - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson)
27 - Additional Datapointer for functioninterface now has the name CustomData
29 - AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson)
30 - If you load an texture from an file the property Filename will be set to the name of the file
31 - Three new properties to attach custom data to the Texture objects
32 - CustomName (free for use string)
33 - CustomNameW (free for use widestring)
34 - CustomDataPointer (free for use pointer to attach other objects or complex structures)
36 - RLE TGAs loaded much faster
38 - fixed some problem with reading RLE TGAs.
40 - function clone now only copys data if it's assigned and now it also copies the ID
41 - it seems that lazarus dont like comments in comments.
43 - It's possible to set the id of the texture
44 - define GLB_NO_NATIVE_GL deactivated by default
46 - Now supports the following libraries
50 - Linux compatibillity via free pascal compatibility (delphi sources optional)
51 - BMPs now loaded manuel
53 - Property DataPtr now has the name Data
54 - Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR
55 - Unused Depth removed
56 - Function FreeData to freeing image data added
58 - ImageID flag of TGAs was ignored. (Thanks Zwoetzen)
60 - Function SetBorderColor implemented (only used by opengl if wrap is set to GL_CLAMP_TO_BORDER)
61 - Function AddAlphaFromValue implemented to use an fixed Value as Alphachannel
62 - Function ReadOpenGLExtension is now only intern
64 - pngimage now disabled by default like all other versions.
66 - Setting up an anisotropic filter of 0 isnt allowed by nvidia (Thanks Ogridi)
68 - Fixed some Problem with Delphi 5
69 - Now uses the newest version of pngimage. Makes saving pngs much easier.
71 - Property IsCompressed and Size removed. Not really supported by Spec (Thanks Ogridi)
73 - Internal Format ifDepth8 added
74 - function GrabScreen now supports all uncompressed formats
76 - AddAlphaFromglBitmap implemented
78 - LoadFromResource and LoadFromResourceId now needs an Instance and an ResourceType (for ID)
80 - Width, Height and Depth internal changed to TglBitmapPixelPosition.
81 property Width, Height, Depth are still existing and new property Dimension are avail
83 - Added native OpenGL Support. Breaking the dglOpenGL "barrier".
85 - Added function GrabScreen to class TglBitmap2D
87 - Added support to Save images
88 - Added function Clone to Clone Instance
90 - Functions now works with Cardinals for each channel. Up to 32 Bits per channel.
92 - Several speed optimizations
94 - Internal structure change. Loading of TGA, PNG and DDS improved.
95 Data, format and size will now set directly with SetDataPtr.
96 - AddFunc now works with all Types of Images and Formats
97 - Some Funtions moved to Baseclass TglBitmap
99 - Added Support to decompress DXT3 and DXT5 compressed Images.
100 - Added Mapping to convert data from one format into an other.
102 - Added method ConvertTo in Class TglBitmap2D. Method allows to convert every
103 supported Input format (supported by GetPixel) into any uncompresed Format
104 - Added Support to decompress DXT1 compressed Images.
105 - SwapColors replaced by ConvertTo
107 - Added Support for compressed DDSs
108 - Added new internal formats (DXT1, DXT3, DXT5)
110 - Parameter Components renamed to InternalFormat
112 - Some AllocMem replaced with GetMem (little speed change)
113 - better exception handling. Better protection from memory leaks.
115 - Added support for Direct Draw Surfaces (.DDS) (uncompressed images only)
116 - Added new internal formats (RGB8, RGBA8, RGBA4, RGB5A1, RGB10A2, R5G6B5)
118 - Added support for Grayscale textures
119 - Added internal formats (Alpha, Luminance, LuminanceAlpha, BGR8, BGRA8)
121 - Added support for GL_VERSION_2_0
122 - Added support for GL_EXT_texture_filter_anisotropic
124 - Function FillWithColor fills the Image with one Color
125 - Function LoadNormalMap added
127 - ToNormalMap allows to Create an NormalMap from the Alphachannel
128 - ToNormalMap now supports Sobel (nmSobel) function.
130 - support for RLE Compressed RGB TGAs added
132 - Class TglBitmapNormalMap added to support Normalmap generation
133 - Added function ToNormalMap in class TglBitmap2D to genereate normal maps from textures.
134 3 Filters are supported. (4 Samples, 3x3 and 5x5)
136 - Method LoadCubeMapClass removed
137 - LoadCubeMap returnvalue is now the Texture paramter. Such as LoadTextures
138 - virtual abstract method GenTexture in class TglBitmap now is protected
140 - now support DescriptionFlag in LoadTga. Allows vertical flipped images to be loaded as normal
142 - little enhancement for IsPowerOfTwo
143 - TglBitmap1D.GenTexture now tests NPOT Textures
145 - some little name changes. All properties or function with Texture in name are
146 now without texture in name. We have allways texture so we dosn't name it.
148 - GenTexture now tests if texture is NPOT and NPOT-Texture are supported or
149 TextureTarget is GL_TEXTURE_RECTANGLE. Else it raised an exception.
151 - added support for GL_ARB_texture_rectangle, GL_EXT_texture_rectangle and GL_NV_texture_rectangle
153 - Function Unbind added
154 - call of SetFilter or SetTextureWrap if TextureID exists results in setting properties to opengl texture.
156 - class TglBitmapCubeMap added (allows to Create Cubemaps)
158 - Added Support for PNG Images. (http://pngdelphi.sourceforge.net/)
159 To Enable png's use the define pngimage
161 - New Functioninterface added
162 - Function GetPixel added
164 - Property BuildMipMaps renamed to MipMap
166 - property Name removed.
167 - BuildMipMaps is now a set of 3 values. None, GluBuildMipmaps and SGIS_generate_mipmap
169 - property name added. Only used in glForms!
171 - property FreeDataAfterGenTexture is now available as default (default = true)
172 - BuildMipmaps now implemented in TglBitmap1D (i've forgotten it)
173 - function MoveMemory replaced with function Move (little speed change)
174 - several calculations stored in variables (little speed change)
176 - property BuildMipsMaps added (default = true)
177 if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps
178 - property FreeDataAfterGenTexture added (default = true)
179 if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated.
180 - parameter DisableOtherTextureUnits of Bind removed
181 - parameter FreeDataAfterGeneration of GenTextures removed
183 - TglBitmap dosn't delete data if class was destroyed (fixed)
185 - Bind now enables TextureUnits (by params)
186 - GenTextures can leave data (by param)
187 - LoadTextures now optimal
189 - Performance optimization in AddFunc
190 - procedure Bind moved to subclasses
191 - Added new Class TglBitmap1D to support real OpenGL 1D Textures
193 - Texturefilter and texturewrap now also as defaults
194 Minfilter = GL_LINEAR_MIPMAP_LINEAR
195 Magfilter = GL_LINEAR
196 Wrap(str) = GL_CLAMP_TO_EDGE
197 - Added new format tfCompressed to create a compressed texture.
198 - propertys IsCompressed, TextureSize and IsResident added
199 IsCompressed and TextureSize only contains data from level 0
201 - Added function AddFunc to add PerPixelEffects to Image
202 - LoadFromFunc now based on AddFunc
203 - Invert now based on AddFunc
204 - SwapColors now based on AddFunc
206 - Added function FlipHorz
208 - Added function LaodFromFunc to create images with function
209 - Added function FlipVert
210 - Added internal format RGB(A) if GL_EXT_bgra or OpenGL 1.2 isn't supported
212 - Added Alphafunctions to calculate alpha per function
213 - Added Alpha from ColorKey using alphafunctions
215 - First full functionally Version of glBitmap
216 - Support for 24Bit and 32Bit TGA Pictures added
218 - begin of programming
219 ***********************************************************}
222 // Please uncomment the defines below to configure the glBitmap to your preferences.
223 // If you have configured the unit you can uncomment the warning above.
224 {$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
227 // Preferences ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
229 // activate to enable build-in OpenGL support with statically linked methods
230 // use dglOpenGL.pas if not enabled
231 {.$DEFINE GLB_NATIVE_OGL_STATIC}
233 // activate to enable build-in OpenGL support with dynamically linked methods
234 // use dglOpenGL.pas if not enabled
235 {.$DEFINE GLB_NATIVE_OGL_DYNAMIC}
238 // activate to enable the support for SDL_surfaces
241 // activate to enable the support for TBitmap from Delphi (not lazarus)
242 {.$DEFINE GLB_DELPHI}
244 // activate to enable the support for TLazIntfImage from Lazarus
245 {.$DEFINE GLB_LAZARUS}
249 // activate to enable the support of SDL_image to load files. (READ ONLY)
250 // If you enable SDL_image all other libraries will be ignored!
251 {.$DEFINE GLB_SDL_IMAGE}
255 // activate to enable Lazarus TPortableNetworkGraphic support
256 // if you enable this pngImage and libPNG will be ignored
257 {.$DEFINE GLB_LAZ_PNG}
259 // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/
260 // if you enable pngimage the libPNG will be ignored
261 {.$DEFINE GLB_PNGIMAGE}
263 // activate to use the libPNG -> http://www.libpng.org/
264 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libpng
265 {.$DEFINE GLB_LIB_PNG}
269 // activate to enable Lazarus TJPEGImage support
270 // if you enable this delphi jpegs and libJPEG will be ignored
271 {.$DEFINE GLB_LAZ_JPEG}
273 // if you enable delphi jpegs the libJPEG will be ignored
274 {.$DEFINE GLB_DELPHI_JPEG}
276 // activate to use the libJPEG -> http://www.ijg.org/
277 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libjpeg
278 {.$DEFINE GLB_LIB_JPEG}
281 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
282 // PRIVATE: do not change anything! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299 {$IF DEFINED(WIN32) or DEFINED(WIN64) or DEFINED(WINDOWS)}
301 {$ELSEIF DEFINED(LINUX)}
305 // native OpenGL Support
306 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) OR DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
307 {$DEFINE GLB_NATIVE_OGL}
310 // checking define combinations
312 {$IFDEF GLB_SDL_IMAGE}
314 {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
319 {$MESSAGE warn 'The Lazarus TPortableNetworkGraphics will be ignored because you are using SDL_image.'}
323 {$IFDEF GLB_PNGIMAGE}
324 {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
325 {$undef GLB_PNGIMAGE}
328 {$IFDEF GLB_LAZ_JPEG}
329 {$MESSAGE warn 'The Lazarus TJPEGImage will be ignored because you are using SDL_image.'}
330 {$undef GLB_LAZ_JPEG}
333 {$IFDEF GLB_DELPHI_JPEG}
334 {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
335 {$undef GLB_DELPHI_JPEG}
339 {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
343 {$IFDEF GLB_LIB_JPEG}
344 {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
345 {$undef GLB_LIB_JPEG}
348 {$DEFINE GLB_SUPPORT_PNG_READ}
349 {$DEFINE GLB_SUPPORT_JPEG_READ}
352 // Lazarus TPortableNetworkGraphic
354 {$IFNDEF GLB_LAZARUS}
355 {$MESSAGE warn 'Lazarus TPortableNetworkGraphic won''t work without Lazarus. Lazarus will be activated.'}
356 {$DEFINE GLB_LAZARUS}
359 {$IFDEF GLB_PNGIMAGE}
360 {$MESSAGE warn 'The pngimage will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
361 {$undef GLB_PNGIMAGE}
365 {$MESSAGE warn 'The library libPNG will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
369 {$DEFINE GLB_SUPPORT_PNG_READ}
370 {$DEFINE GLB_SUPPORT_PNG_WRITE}
374 {$IFDEF GLB_PNGIMAGE}
376 {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'}
380 {$DEFINE GLB_SUPPORT_PNG_READ}
381 {$DEFINE GLB_SUPPORT_PNG_WRITE}
386 {$DEFINE GLB_SUPPORT_PNG_READ}
387 {$DEFINE GLB_SUPPORT_PNG_WRITE}
390 // Lazarus TJPEGImage
391 {$IFDEF GLB_LAZ_JPEG}
392 {$IFNDEF GLB_LAZARUS}
393 {$MESSAGE warn 'Lazarus TJPEGImage won''t work without Lazarus. Lazarus will be activated.'}
394 {$DEFINE GLB_LAZARUS}
397 {$IFDEF GLB_DELPHI_JPEG}
398 {$MESSAGE warn 'The Delphi JPEGImage will be ignored if you are using the Lazarus TJPEGImage.'}
399 {$undef GLB_DELPHI_JPEG}
402 {$IFDEF GLB_LIB_JPEG}
403 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the Lazarus TJPEGImage.'}
404 {$undef GLB_LIB_JPEG}
407 {$DEFINE GLB_SUPPORT_JPEG_READ}
408 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
412 {$IFDEF GLB_DELPHI_JPEG}
413 {$IFDEF GLB_LIB_JPEG}
414 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
415 {$undef GLB_LIB_JPEG}
418 {$DEFINE GLB_SUPPORT_JPEG_READ}
419 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
423 {$IFDEF GLB_LIB_JPEG}
424 {$DEFINE GLB_SUPPORT_JPEG_READ}
425 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
429 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) AND DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
430 {$MESSAGE warn 'GLB_NATIVE_OGL_STATIC will be ignored because you enabled GLB_NATIVE_OGL_DYNAMIC'}
444 {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF}
445 {$IF DEFINED(GLB_WIN) AND
446 (DEFINED(GLB_NATIVE_OGL) OR
447 DEFINED(GLB_DELPHI))} windows, {$IFEND}
449 {$IFDEF GLB_SDL} SDL, {$ENDIF}
450 {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, Graphics, {$ENDIF}
451 {$IFDEF GLB_DELPHI} Dialogs, Graphics, Types, {$ENDIF}
453 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
454 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
455 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
456 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
457 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
461 {$IFDEF GLB_NATIVE_OGL}
470 GL_EXTENSIONS = $1F03;
472 GL_TEXTURE_1D = $0DE0;
473 GL_TEXTURE_2D = $0DE1;
474 GL_TEXTURE_RECTANGLE = $84F5;
476 GL_NORMAL_MAP = $8511;
477 GL_TEXTURE_CUBE_MAP = $8513;
478 GL_REFLECTION_MAP = $8512;
479 GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515;
480 GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516;
481 GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517;
482 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518;
483 GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519;
484 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A;
486 GL_TEXTURE_WIDTH = $1000;
487 GL_TEXTURE_HEIGHT = $1001;
488 GL_TEXTURE_INTERNAL_FORMAT = $1003;
489 GL_TEXTURE_SWIZZLE_RGBA = $8E46;
496 GL_TEXTURE_GEN_S = $0C60;
497 GL_TEXTURE_GEN_T = $0C61;
498 GL_TEXTURE_GEN_R = $0C62;
499 GL_TEXTURE_GEN_Q = $0C63;
511 GL_LUMINANCE = $1909;
512 GL_LUMINANCE4 = $803F;
513 GL_LUMINANCE8 = $8040;
514 GL_LUMINANCE12 = $8041;
515 GL_LUMINANCE16 = $8042;
517 GL_LUMINANCE_ALPHA = $190A;
518 GL_LUMINANCE4_ALPHA4 = $8043;
519 GL_LUMINANCE6_ALPHA2 = $8044;
520 GL_LUMINANCE8_ALPHA8 = $8045;
521 GL_LUMINANCE12_ALPHA4 = $8046;
522 GL_LUMINANCE12_ALPHA12 = $8047;
523 GL_LUMINANCE16_ALPHA16 = $8048;
546 GL_DEPTH_COMPONENT = $1902;
547 GL_DEPTH_COMPONENT16 = $81A5;
548 GL_DEPTH_COMPONENT24 = $81A6;
549 GL_DEPTH_COMPONENT32 = $81A7;
551 GL_COMPRESSED_RGB = $84ED;
552 GL_COMPRESSED_RGBA = $84EE;
553 GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
554 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
555 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
556 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
558 GL_UNSIGNED_BYTE = $1401;
559 GL_UNSIGNED_BYTE_3_3_2 = $8032;
560 GL_UNSIGNED_BYTE_2_3_3_REV = $8362;
562 GL_UNSIGNED_SHORT = $1403;
563 GL_UNSIGNED_SHORT_5_6_5 = $8363;
564 GL_UNSIGNED_SHORT_4_4_4_4 = $8033;
565 GL_UNSIGNED_SHORT_5_5_5_1 = $8034;
566 GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
567 GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
568 GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
570 GL_UNSIGNED_INT = $1405;
571 GL_UNSIGNED_INT_8_8_8_8 = $8035;
572 GL_UNSIGNED_INT_10_10_10_2 = $8036;
573 GL_UNSIGNED_INT_8_8_8_8_REV = $8367;
574 GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
577 GL_TEXTURE_MAG_FILTER = $2800;
578 GL_TEXTURE_MIN_FILTER = $2801;
580 GL_NEAREST_MIPMAP_NEAREST = $2700;
581 GL_NEAREST_MIPMAP_LINEAR = $2702;
583 GL_LINEAR_MIPMAP_NEAREST = $2701;
584 GL_LINEAR_MIPMAP_LINEAR = $2703;
587 GL_TEXTURE_WRAP_S = $2802;
588 GL_TEXTURE_WRAP_T = $2803;
589 GL_TEXTURE_WRAP_R = $8072;
592 GL_CLAMP_TO_EDGE = $812F;
593 GL_CLAMP_TO_BORDER = $812D;
594 GL_MIRRORED_REPEAT = $8370;
597 GL_GENERATE_MIPMAP = $8191;
598 GL_TEXTURE_BORDER_COLOR = $1004;
599 GL_MAX_TEXTURE_SIZE = $0D33;
600 GL_PACK_ALIGNMENT = $0D05;
601 GL_UNPACK_ALIGNMENT = $0CF5;
603 GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
604 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
605 GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C;
606 GL_TEXTURE_GEN_MODE = $2500;
608 {$IF DEFINED(GLB_WIN)}
609 libglu = 'glu32.dll';
610 libopengl = 'opengl32.dll';
611 {$ELSEIF DEFINED(GLB_LINUX)}
612 libglu = 'libGLU.so.1';
613 libopengl = 'libGL.so.1';
617 GLboolean = BYTEBOOL;
625 PGLboolean = ^GLboolean;
630 TglCompressedTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
631 TglCompressedTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
632 TglGetCompressedTexImage = procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
634 {$IF DEFINED(GLB_WIN)}
635 TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall;
636 {$ELSEIF DEFINED(GLB_LINUX)}
637 TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl;
638 TglXGetProcAddressARB = function(const name: PAnsiChar): pointer; cdecl;
641 {$IF DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
642 TglEnable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
643 TglDisable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
645 TglGetString = function(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
646 TglGetIntegerv = procedure(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
648 TglTexParameteri = procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
649 TglTexParameteriv = procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
650 TglTexParameterfv = procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
651 TglGetTexParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
652 TglGetTexParameterfv = procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
653 TglGetTexLevelParameteriv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
654 TglGetTexLevelParameterfv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
656 TglTexGeni = procedure(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
657 TglGenTextures = procedure(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
658 TglBindTexture = procedure(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
659 TglDeleteTextures = procedure(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
661 TglAreTexturesResident = function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
662 TglReadPixels = procedure(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
663 TglPixelStorei = procedure(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
665 TglTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
666 TglTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
667 TglGetTexImage = procedure(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
669 TgluBuild1DMipmaps = function(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
670 TgluBuild2DMipmaps = function(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
672 {$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)}
673 procedure glEnable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
674 procedure glDisable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
676 function glGetString(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
677 procedure glGetIntegerv(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
679 procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
680 procedure glTexParameteriv(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
681 procedure glTexParameterfv(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
682 procedure glGetTexParameteriv(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
683 procedure glGetTexParameterfv(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
684 procedure glGetTexLevelParameteriv(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
685 procedure glGetTexLevelParameterfv(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
687 procedure glTexGeni(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
688 procedure glGenTextures(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
689 procedure glBindTexture(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
690 procedure glDeleteTextures(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
692 function glAreTexturesResident(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
693 procedure glReadPixels(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
694 procedure glPixelStorei(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
696 procedure glTexImage1D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
697 procedure glTexImage2D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
698 procedure glGetTexImage(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
700 function gluBuild1DMipmaps(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
701 function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
711 GL_SGIS_generate_mipmap,
713 GL_ARB_texture_border_clamp,
714 GL_ARB_texture_mirrored_repeat,
715 GL_ARB_texture_rectangle,
716 GL_ARB_texture_non_power_of_two,
717 GL_ARB_texture_swizzle,
718 GL_ARB_texture_cube_map,
720 GL_IBM_texture_mirrored_repeat,
722 GL_NV_texture_rectangle,
724 GL_EXT_texture_edge_clamp,
725 GL_EXT_texture_rectangle,
726 GL_EXT_texture_swizzle,
727 GL_EXT_texture_cube_map,
728 GL_EXT_texture_filter_anisotropic: Boolean;
730 glCompressedTexImage1D: TglCompressedTexImage1D;
731 glCompressedTexImage2D: TglCompressedTexImage2D;
732 glGetCompressedTexImage: TglGetCompressedTexImage;
734 {$IF DEFINED(GLB_WIN)}
735 wglGetProcAddress: TwglGetProcAddress;
736 {$ELSEIF DEFINED(GLB_LINUX)}
737 glXGetProcAddress: TglXGetProcAddress;
738 glXGetProcAddressARB: TglXGetProcAddress;
741 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
743 glDisable: TglDisable;
745 glGetString: TglGetString;
746 glGetIntegerv: TglGetIntegerv;
748 glTexParameteri: TglTexParameteri;
749 glTexParameteriv: TglTexParameteriv;
750 glTexParameterfv: TglTexParameterfv;
751 glGetTexParameteriv: TglGetTexParameteriv;
752 glGetTexParameterfv: TglGetTexParameterfv;
753 glGetTexLevelParameteriv: TglGetTexLevelParameteriv;
754 glGetTexLevelParameterfv: TglGetTexLevelParameterfv;
756 glTexGeni: TglTexGeni;
757 glGenTextures: TglGenTextures;
758 glBindTexture: TglBindTexture;
759 glDeleteTextures: TglDeleteTextures;
761 glAreTexturesResident: TglAreTexturesResident;
762 glReadPixels: TglReadPixels;
763 glPixelStorei: TglPixelStorei;
765 glTexImage1D: TglTexImage1D;
766 glTexImage2D: TglTexImage2D;
767 glGetTexImage: TglGetTexImage;
769 gluBuild1DMipmaps: TgluBuild1DMipmaps;
770 gluBuild2DMipmaps: TgluBuild2DMipmaps;
775 ////////////////////////////////////////////////////////////////////////////////////////////////////
777 tfEmpty = 0, //must be smallest value!
793 tfLuminance12Alpha12,
794 tfLuminance16Alpha16,
838 TglBitmapFileType = (
839 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
840 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
844 TglBitmapFileTypes = set of TglBitmapFileType;
851 TglBitmapNormalMapFunc = (
857 ////////////////////////////////////////////////////////////////////////////////////////////////////
858 EglBitmap = class(Exception);
859 EglBitmapNotSupported = class(Exception);
860 EglBitmapSizeToLarge = class(EglBitmap);
861 EglBitmapNonPowerOfTwo = class(EglBitmap);
862 EglBitmapUnsupportedFormat = class(EglBitmap)
864 constructor Create(const aFormat: TglBitmapFormat); overload;
865 constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload;
868 ////////////////////////////////////////////////////////////////////////////////////////////////////
869 TglBitmapColorRec = packed record
871 0: (r, g, b, a: Cardinal);
872 1: (arr: array[0..3] of Cardinal);
875 TglBitmapPixelData = packed record
876 Data, Range: TglBitmapColorRec;
877 Format: TglBitmapFormat;
879 PglBitmapPixelData = ^TglBitmapPixelData;
881 ////////////////////////////////////////////////////////////////////////////////////////////////////
882 TglBitmapPixelPositionFields = set of (ffX, ffY);
883 TglBitmapPixelPosition = record
884 Fields : TglBitmapPixelPositionFields;
889 TglBitmapFormatDescriptor = class(TObject)
891 function GetIsCompressed: Boolean; virtual; abstract;
892 function GetHasAlpha: Boolean; virtual; abstract;
894 function GetglDataFormat: GLenum; virtual; abstract;
895 function GetglFormat: GLenum; virtual; abstract;
896 function GetglInternalFormat: GLenum; virtual; abstract;
898 property IsCompressed: Boolean read GetIsCompressed;
899 property HasAlpha: Boolean read GetHasAlpha;
901 property glFormat: GLenum read GetglFormat;
902 property glInternalFormat: GLenum read GetglInternalFormat;
903 property glDataFormat: GLenum read GetglDataFormat;
906 ////////////////////////////////////////////////////////////////////////////////////////////////////
908 TglBitmapFunctionRec = record
910 Size: TglBitmapPixelPosition;
911 Position: TglBitmapPixelPosition;
912 Source: TglBitmapPixelData;
913 Dest: TglBitmapPixelData;
916 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
918 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
921 function GetFormatDesc: TglBitmapFormatDescriptor;
925 fAnisotropic: Integer;
926 fDeleteTextureOnFree: Boolean;
927 fFreeDataOnDestroy: Boolean;
928 fFreeDataAfterGenTexture: Boolean;
930 fIsResident: Boolean;
931 fBorderColor: array[0..3] of Single;
933 fDimension: TglBitmapPixelPosition;
934 fMipMap: TglBitmapMipMap;
935 fFormat: TglBitmapFormat;
951 fSwizzle: array[0..3] of GLenum;
956 fCustomNameW: WideString;
957 fCustomData: Pointer;
960 function GetWidth: Integer; virtual;
961 function GetHeight: Integer; virtual;
963 function GetFileWidth: Integer; virtual;
964 function GetFileHeight: Integer; virtual;
967 procedure SetCustomData(const aValue: Pointer);
968 procedure SetCustomName(const aValue: String);
969 procedure SetCustomNameW(const aValue: WideString);
970 procedure SetFreeDataOnDestroy(const aValue: Boolean);
971 procedure SetDeleteTextureOnFree(const aValue: Boolean);
972 procedure SetFormat(const aValue: TglBitmapFormat);
973 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
974 procedure SetID(const aValue: Cardinal);
975 procedure SetMipMap(const aValue: TglBitmapMipMap);
976 procedure SetTarget(const aValue: Cardinal);
977 procedure SetAnisotropic(const aValue: Integer);
980 procedure SetupParameters(out aBuildWithGlu: Boolean);
981 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
982 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; //be careful, aData could be freed by this method
983 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
985 function FlipHorz: Boolean; virtual;
986 function FlipVert: Boolean; virtual;
988 property Width: Integer read GetWidth;
989 property Height: Integer read GetHeight;
991 property FileWidth: Integer read GetFileWidth;
992 property FileHeight: Integer read GetFileHeight;
995 property ID: Cardinal read fID write SetID;
996 property Target: Cardinal read fTarget write SetTarget;
997 property Format: TglBitmapFormat read fFormat write SetFormat;
998 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
999 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
1001 property FormatDesc: TglBitmapFormatDescriptor read GetFormatDesc;
1003 property Filename: String read fFilename;
1004 property CustomName: String read fCustomName write SetCustomName;
1005 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
1006 property CustomData: Pointer read fCustomData write SetCustomData;
1008 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
1009 property FreeDataOnDestroy: Boolean read fFreeDataOnDestroy write SetFreeDataOnDestroy;
1010 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
1012 property Dimension: TglBitmapPixelPosition read fDimension;
1013 property Data: PByte read fData;
1014 property IsResident: Boolean read fIsResident;
1016 procedure AfterConstruction; override;
1017 procedure BeforeDestruction; override;
1019 procedure PrepareResType(var aResource: String; var aResType: PChar);
1022 procedure LoadFromFile(const aFilename: String);
1023 procedure LoadFromStream(const aStream: TStream); virtual;
1024 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
1025 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil);
1026 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil);
1027 procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
1030 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
1031 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
1034 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
1035 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
1036 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
1040 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
1041 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
1042 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
1043 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
1044 const aArgs: Pointer = nil): Boolean;
1048 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
1049 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
1050 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
1051 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
1052 const aArgs: Pointer = nil): Boolean;
1055 {$IFDEF GLB_LAZARUS}
1056 function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1057 function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
1058 function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1059 function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil;
1060 const aArgs: Pointer = nil): Boolean;
1063 function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil;
1064 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1065 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
1066 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1068 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
1069 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1070 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1071 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1073 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
1074 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
1075 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
1077 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
1078 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
1079 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
1081 function RemoveAlpha: Boolean; virtual;
1084 function Clone: TglBitmap;
1085 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
1086 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
1087 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
1091 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
1092 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
1093 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
1096 procedure SetFilter(const aMin, aMag: GLenum);
1098 const S: GLenum = GL_CLAMP_TO_EDGE;
1099 const T: GLenum = GL_CLAMP_TO_EDGE;
1100 const R: GLenum = GL_CLAMP_TO_EDGE);
1101 procedure SetSwizzle(const r, g, b, a: GLenum);
1103 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
1104 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
1107 constructor Create; overload;
1108 constructor Create(const aFileName: String); overload;
1109 constructor Create(const aStream: TStream); overload;
1110 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte = nil); overload;
1111 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
1112 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
1113 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
1115 {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1116 {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF}
1118 {$IFDEF GLB_SUPPORT_JPEG_READ} function LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1119 {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF}
1121 function LoadBMP(const aStream: TStream): Boolean; virtual;
1122 procedure SaveBMP(const aStream: TStream); virtual;
1124 function LoadTGA(const aStream: TStream): Boolean; virtual;
1125 procedure SaveTGA(const aStream: TStream); virtual;
1127 function LoadDDS(const aStream: TStream): Boolean; virtual;
1128 procedure SaveDDS(const aStream: TStream); virtual;
1131 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1132 TglBitmap1D = class(TglBitmap)
1134 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1135 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1136 procedure UploadData(const aBuildWithGlu: Boolean);
1139 procedure AfterConstruction; override;
1140 function FlipHorz: Boolean; override;
1141 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1144 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1145 TglBitmap2D = class(TglBitmap)
1147 fLines: array of PByte;
1148 function GetScanline(const aIndex: Integer): Pointer;
1149 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1150 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1151 procedure UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
1155 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
1157 procedure AfterConstruction; override;
1159 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
1160 procedure GetDataFromTexture;
1161 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1163 function FlipHorz: Boolean; override;
1164 function FlipVert: Boolean; override;
1166 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
1167 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1170 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1171 TglBitmapCubeMap = class(TglBitmap2D)
1174 procedure GenTexture(const aTestTextureSize: Boolean = true); reintroduce;
1176 procedure AfterConstruction; override;
1177 procedure GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean = true);
1178 procedure Bind(const aEnableTexCoordsGen: Boolean = true; const aEnableTextureUnit: Boolean = true); reintroduce; virtual;
1179 procedure Unbind(const aDisableTexCoordsGen: Boolean = true; const aDisableTextureUnit: Boolean = true); reintroduce; virtual;
1182 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1183 TglBitmapNormalMap = class(TglBitmapCubeMap)
1185 procedure AfterConstruction; override;
1186 procedure GenerateNormalMap(const aSize: Integer = 32; const aTestTextureSize: Boolean = true);
1190 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1192 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1193 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1194 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1195 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1196 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1197 procedure glBitmapSetDefaultWrap(
1198 const S: Cardinal = GL_CLAMP_TO_EDGE;
1199 const T: Cardinal = GL_CLAMP_TO_EDGE;
1200 const R: Cardinal = GL_CLAMP_TO_EDGE);
1202 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1203 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1204 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1205 function glBitmapGetDefaultFormat: TglBitmapFormat;
1206 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1207 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1209 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1210 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1211 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1214 glBitmapDefaultDeleteTextureOnFree: Boolean;
1215 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1216 glBitmapDefaultFormat: TglBitmapFormat;
1217 glBitmapDefaultMipmap: TglBitmapMipMap;
1218 glBitmapDefaultFilterMin: Cardinal;
1219 glBitmapDefaultFilterMag: Cardinal;
1220 glBitmapDefaultWrapS: Cardinal;
1221 glBitmapDefaultWrapT: Cardinal;
1222 glBitmapDefaultWrapR: Cardinal;
1223 glDefaultSwizzle: array[0..3] of GLenum;
1226 function CreateGrayPalette: HPALETTE;
1232 Math, syncobjs, typinfo
1233 {$IFDEF GLB_DELPHI}, Types{$ENDIF}
1234 {$IF DEFINED(GLB_SUPPORT_JPEG_READ) AND DEFINED(GLB_LAZ_JPEG)}, FPReadJPEG{$IFEND};
1238 QWord = System.UInt64;
1245 ////////////////////////////////////////////////////////////////////////////////////////////////////
1246 TShiftRec = packed record
1248 0: (r, g, b, a: Byte);
1249 1: (arr: array[0..3] of Byte);
1252 TFormatDescriptor = class(TglBitmapFormatDescriptor)
1254 function GetRedMask: QWord;
1255 function GetGreenMask: QWord;
1256 function GetBlueMask: QWord;
1257 function GetAlphaMask: QWord;
1259 fFormat: TglBitmapFormat;
1260 fWithAlpha: TglBitmapFormat;
1261 fWithoutAlpha: TglBitmapFormat;
1262 fRGBInverted: TglBitmapFormat;
1263 fUncompressed: TglBitmapFormat;
1265 fIsCompressed: Boolean;
1267 fRange: TglBitmapColorRec;
1271 fglInternalFormat: GLenum;
1272 fglDataFormat: GLenum;
1274 function GetIsCompressed: Boolean; override;
1275 function GetHasAlpha: Boolean; override;
1277 function GetglFormat: GLenum; override;
1278 function GetglInternalFormat: GLenum; override;
1279 function GetglDataFormat: GLenum; override;
1281 function GetComponents: Integer; virtual;
1283 property Format: TglBitmapFormat read fFormat;
1284 property WithAlpha: TglBitmapFormat read fWithAlpha;
1285 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1286 property RGBInverted: TglBitmapFormat read fRGBInverted;
1287 property Components: Integer read GetComponents;
1288 property PixelSize: Single read fPixelSize;
1290 property Range: TglBitmapColorRec read fRange;
1291 property Shift: TShiftRec read fShift;
1293 property RedMask: QWord read GetRedMask;
1294 property GreenMask: QWord read GetGreenMask;
1295 property BlueMask: QWord read GetBlueMask;
1296 property AlphaMask: QWord read GetAlphaMask;
1298 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1299 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1301 function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual;
1302 function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
1304 function CreateMappingData: Pointer; virtual;
1305 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1307 function IsEmpty: Boolean; virtual;
1308 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual;
1310 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1312 constructor Create; virtual;
1314 class procedure Init;
1315 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1316 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1317 class procedure Clear;
1318 class procedure Finalize;
1320 TFormatDescriptorClass = class of TFormatDescriptor;
1322 TfdEmpty = class(TFormatDescriptor);
1324 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1325 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1326 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1327 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1328 constructor Create; override;
1331 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1332 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1333 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1334 constructor Create; override;
1337 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1338 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1339 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1340 constructor Create; override;
1343 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1344 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1345 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1346 constructor Create; override;
1349 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1350 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1351 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1352 constructor Create; override;
1355 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1356 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1357 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1358 constructor Create; override;
1361 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1362 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1363 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1364 constructor Create; override;
1367 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1368 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1369 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1370 constructor Create; override;
1373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1374 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1375 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1376 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1377 constructor Create; override;
1380 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1381 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1382 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1383 constructor Create; override;
1386 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1387 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1388 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1389 constructor Create; override;
1392 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1393 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1394 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1395 constructor Create; override;
1398 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1399 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1400 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1401 constructor Create; override;
1404 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1405 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1406 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1407 constructor Create; override;
1410 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1411 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1412 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1413 constructor Create; override;
1416 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1417 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1418 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1419 constructor Create; override;
1422 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1423 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1424 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1425 constructor Create; override;
1428 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1429 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1430 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1431 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1432 constructor Create; override;
1435 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1436 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1437 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1438 constructor Create; override;
1441 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1442 TfdAlpha4 = class(TfdAlpha_UB1)
1443 constructor Create; override;
1446 TfdAlpha8 = class(TfdAlpha_UB1)
1447 constructor Create; override;
1450 TfdAlpha12 = class(TfdAlpha_US1)
1451 constructor Create; override;
1454 TfdAlpha16 = class(TfdAlpha_US1)
1455 constructor Create; override;
1458 TfdLuminance4 = class(TfdLuminance_UB1)
1459 constructor Create; override;
1462 TfdLuminance8 = class(TfdLuminance_UB1)
1463 constructor Create; override;
1466 TfdLuminance12 = class(TfdLuminance_US1)
1467 constructor Create; override;
1470 TfdLuminance16 = class(TfdLuminance_US1)
1471 constructor Create; override;
1474 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1475 constructor Create; override;
1478 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1479 constructor Create; override;
1482 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1483 constructor Create; override;
1486 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1487 constructor Create; override;
1490 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1491 constructor Create; override;
1494 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1495 constructor Create; override;
1498 TfdR3G3B2 = class(TfdUniversal_UB1)
1499 constructor Create; override;
1502 TfdRGB4 = class(TfdUniversal_US1)
1503 constructor Create; override;
1506 TfdR5G6B5 = class(TfdUniversal_US1)
1507 constructor Create; override;
1510 TfdRGB5 = class(TfdUniversal_US1)
1511 constructor Create; override;
1514 TfdRGB8 = class(TfdRGB_UB3)
1515 constructor Create; override;
1518 TfdRGB10 = class(TfdUniversal_UI1)
1519 constructor Create; override;
1522 TfdRGB12 = class(TfdRGB_US3)
1523 constructor Create; override;
1526 TfdRGB16 = class(TfdRGB_US3)
1527 constructor Create; override;
1530 TfdRGBA2 = class(TfdRGBA_UB4)
1531 constructor Create; override;
1534 TfdRGBA4 = class(TfdUniversal_US1)
1535 constructor Create; override;
1538 TfdRGB5A1 = class(TfdUniversal_US1)
1539 constructor Create; override;
1542 TfdRGBA8 = class(TfdRGBA_UB4)
1543 constructor Create; override;
1546 TfdRGB10A2 = class(TfdUniversal_UI1)
1547 constructor Create; override;
1550 TfdRGBA12 = class(TfdRGBA_US4)
1551 constructor Create; override;
1554 TfdRGBA16 = class(TfdRGBA_US4)
1555 constructor Create; override;
1558 TfdBGR4 = class(TfdUniversal_US1)
1559 constructor Create; override;
1562 TfdB5G6R5 = class(TfdUniversal_US1)
1563 constructor Create; override;
1566 TfdBGR5 = class(TfdUniversal_US1)
1567 constructor Create; override;
1570 TfdBGR8 = class(TfdBGR_UB3)
1571 constructor Create; override;
1574 TfdBGR10 = class(TfdUniversal_UI1)
1575 constructor Create; override;
1578 TfdBGR12 = class(TfdBGR_US3)
1579 constructor Create; override;
1582 TfdBGR16 = class(TfdBGR_US3)
1583 constructor Create; override;
1586 TfdBGRA2 = class(TfdBGRA_UB4)
1587 constructor Create; override;
1590 TfdBGRA4 = class(TfdUniversal_US1)
1591 constructor Create; override;
1594 TfdBGR5A1 = class(TfdUniversal_US1)
1595 constructor Create; override;
1598 TfdBGRA8 = class(TfdBGRA_UB4)
1599 constructor Create; override;
1602 TfdBGR10A2 = class(TfdUniversal_UI1)
1603 constructor Create; override;
1606 TfdBGRA12 = class(TfdBGRA_US4)
1607 constructor Create; override;
1610 TfdBGRA16 = class(TfdBGRA_US4)
1611 constructor Create; override;
1614 TfdDepth16 = class(TfdDepth_US1)
1615 constructor Create; override;
1618 TfdDepth24 = class(TfdDepth_UI1)
1619 constructor Create; override;
1622 TfdDepth32 = class(TfdDepth_UI1)
1623 constructor Create; override;
1626 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1627 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1628 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1629 constructor Create; override;
1632 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1633 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1634 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1635 constructor Create; override;
1638 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1639 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1640 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1641 constructor Create; override;
1644 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1645 TbmpBitfieldFormat = class(TFormatDescriptor)
1647 procedure SetRedMask (const aValue: QWord);
1648 procedure SetGreenMask(const aValue: QWord);
1649 procedure SetBlueMask (const aValue: QWord);
1650 procedure SetAlphaMask(const aValue: QWord);
1652 procedure Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte);
1654 property RedMask: QWord read GetRedMask write SetRedMask;
1655 property GreenMask: QWord read GetGreenMask write SetGreenMask;
1656 property BlueMask: QWord read GetBlueMask write SetBlueMask;
1657 property AlphaMask: QWord read GetAlphaMask write SetAlphaMask;
1659 property PixelSize: Single read fPixelSize write fPixelSize;
1661 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1662 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1665 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1666 TbmpColorTableEnty = packed record
1669 TbmpColorTable = array of TbmpColorTableEnty;
1670 TbmpColorTableFormat = class(TFormatDescriptor)
1672 fColorTable: TbmpColorTable;
1674 property PixelSize: Single read fPixelSize write fPixelSize;
1675 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1676 property Range: TglBitmapColorRec read fRange write fRange;
1677 property Shift: TShiftRec read fShift write fShift;
1678 property Format: TglBitmapFormat read fFormat write fFormat;
1680 procedure CreateColorTable;
1682 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1683 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1684 destructor Destroy; override;
1688 LUMINANCE_WEIGHT_R = 0.30;
1689 LUMINANCE_WEIGHT_G = 0.59;
1690 LUMINANCE_WEIGHT_B = 0.11;
1692 ALPHA_WEIGHT_R = 0.30;
1693 ALPHA_WEIGHT_G = 0.59;
1694 ALPHA_WEIGHT_B = 0.11;
1696 DEPTH_WEIGHT_R = 0.333333333;
1697 DEPTH_WEIGHT_G = 0.333333333;
1698 DEPTH_WEIGHT_B = 0.333333333;
1700 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1702 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1715 TfdLuminance4Alpha4,
1716 TfdLuminance6Alpha2,
1717 TfdLuminance8Alpha8,
1718 TfdLuminance12Alpha4,
1719 TfdLuminance12Alpha12,
1720 TfdLuminance16Alpha16,
1765 FormatDescriptorCS: TCriticalSection;
1766 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1768 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1769 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1771 inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1774 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1775 constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat);
1777 inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1780 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1781 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1783 result.Fields := [];
1786 result.Fields := result.Fields + [ffX];
1788 result.Fields := result.Fields + [ffY];
1790 result.X := Max(0, X);
1791 result.Y := Max(0, Y);
1794 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1795 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1803 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1804 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1809 for i := 0 to high(r1.arr) do
1810 if (r1.arr[i] <> r2.arr[i]) then
1815 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1816 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1824 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1825 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1834 tfR3G3B2, tfLuminance8,
1837 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1838 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1844 tfRGB10, tfRGB10A2, tfRGBA8,
1845 tfBGR10, tfBGR10A2, tfBGRA8]) then
1846 result := result + [ftBMP];
1850 tfLuminance8, tfAlpha8,
1853 tfLuminance16, tfLuminance8Alpha8,
1854 tfRGB5, tfRGB5A1, tfRGBA4,
1855 tfBGR5, tfBGR5A1, tfBGRA4,
1861 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1862 result := result + [ftTGA];
1866 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1867 tfR3G3B2, tfRGBA2, tfBGRA2,
1870 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1871 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1872 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1878 tfLuminance16Alpha16,
1883 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1884 result := result + [ftDDS];
1886 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1888 tfAlpha8, tfLuminance8, tfLuminance8Alpha8,
1890 tfBGR8, tfBGRA8] then
1891 result := result + [ftPNG];
1894 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1895 if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then
1896 result := result + [ftJPEG];
1900 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1901 function IsPowerOfTwo(aNumber: Integer): Boolean;
1903 while (aNumber and 1) = 0 do
1904 aNumber := aNumber shr 1;
1905 result := aNumber = 1;
1908 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1909 function GetTopMostBit(aBitSet: QWord): Integer;
1912 while aBitSet > 0 do begin
1914 aBitSet := aBitSet shr 1;
1918 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1919 function CountSetBits(aBitSet: QWord): Integer;
1922 while aBitSet > 0 do begin
1923 if (aBitSet and 1) = 1 then
1925 aBitSet := aBitSet shr 1;
1929 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1930 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1933 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1934 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1935 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1938 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1939 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1942 DEPTH_WEIGHT_R * aPixel.Data.r +
1943 DEPTH_WEIGHT_G * aPixel.Data.g +
1944 DEPTH_WEIGHT_B * aPixel.Data.b);
1947 {$IFDEF GLB_NATIVE_OGL}
1948 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1949 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1950 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1952 GL_LibHandle: Pointer = nil;
1954 function glbGetProcAddress(aProcName: PAnsiChar; aLibHandle: Pointer = nil; const aRaiseOnErr: Boolean = true): Pointer;
1956 if not Assigned(aLibHandle) then
1957 aLibHandle := GL_LibHandle;
1959 {$IF DEFINED(GLB_WIN)}
1960 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1961 if Assigned(result) then
1964 if Assigned(wglGetProcAddress) then
1965 result := wglGetProcAddress(aProcName);
1966 {$ELSEIF DEFINED(GLB_LINUX)}
1967 if Assigned(glXGetProcAddress) then begin
1968 result := glXGetProcAddress(aProcName);
1969 if Assigned(result) then
1973 if Assigned(glXGetProcAddressARB) then begin
1974 result := glXGetProcAddressARB(aProcName);
1975 if Assigned(result) then
1979 result := dlsym(aLibHandle, aProcName);
1981 if not Assigned(result) and aRaiseOnErr then
1982 raise EglBitmap.Create('unable to load procedure form library: ' + aProcName);
1985 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1987 GLU_LibHandle: Pointer = nil;
1988 OpenGLInitialized: Boolean;
1989 InitOpenGLCS: TCriticalSection;
1991 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1992 procedure glbInitOpenGL;
1994 ////////////////////////////////////////////////////////////////////////////////
1995 function glbLoadLibrary(const aName: PChar): Pointer;
1997 {$IF DEFINED(GLB_WIN)}
1998 result := {%H-}Pointer(LoadLibrary(aName));
1999 {$ELSEIF DEFINED(GLB_LINUX)}
2000 result := dlopen(Name, RTLD_LAZY);
2006 ////////////////////////////////////////////////////////////////////////////////
2007 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
2010 if not Assigned(aLibHandle) then
2013 {$IF DEFINED(GLB_WIN)}
2014 Result := FreeLibrary({%H-}HINST(aLibHandle));
2015 {$ELSEIF DEFINED(GLB_LINUX)}
2016 Result := dlclose(aLibHandle) = 0;
2021 if Assigned(GL_LibHandle) then
2022 glbFreeLibrary(GL_LibHandle);
2024 if Assigned(GLU_LibHandle) then
2025 glbFreeLibrary(GLU_LibHandle);
2027 GL_LibHandle := glbLoadLibrary(libopengl);
2028 if not Assigned(GL_LibHandle) then
2029 raise EglBitmap.Create('unable to load library: ' + libopengl);
2031 GLU_LibHandle := glbLoadLibrary(libglu);
2032 if not Assigned(GLU_LibHandle) then
2033 raise EglBitmap.Create('unable to load library: ' + libglu);
2035 {$IF DEFINED(GLB_WIN)}
2036 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
2037 {$ELSEIF DEFINED(GLB_LINUX)}
2038 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
2039 glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
2042 glEnable := glbGetProcAddress('glEnable');
2043 glDisable := glbGetProcAddress('glDisable');
2044 glGetString := glbGetProcAddress('glGetString');
2045 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
2046 glTexParameteri := glbGetProcAddress('glTexParameteri');
2047 glTexParameteriv := glbGetProcAddress('glTexParameteriv');
2048 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
2049 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
2050 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
2051 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
2052 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
2053 glTexGeni := glbGetProcAddress('glTexGeni');
2054 glGenTextures := glbGetProcAddress('glGenTextures');
2055 glBindTexture := glbGetProcAddress('glBindTexture');
2056 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
2057 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
2058 glReadPixels := glbGetProcAddress('glReadPixels');
2059 glPixelStorei := glbGetProcAddress('glPixelStorei');
2060 glTexImage1D := glbGetProcAddress('glTexImage1D');
2061 glTexImage2D := glbGetProcAddress('glTexImage2D');
2062 glGetTexImage := glbGetProcAddress('glGetTexImage');
2064 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
2065 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
2069 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2070 procedure glbReadOpenGLExtensions;
2073 MajorVersion, MinorVersion: Integer;
2075 ///////////////////////////////////////////////////////////////////////////////////////////
2076 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
2083 Separator := Pos(AnsiString('.'), aBuffer);
2084 if (Separator > 1) and (Separator < Length(aBuffer)) and
2085 (aBuffer[Separator - 1] in ['0'..'9']) and
2086 (aBuffer[Separator + 1] in ['0'..'9']) then begin
2089 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
2092 Delete(aBuffer, 1, Separator);
2093 Separator := Pos(AnsiString('.'), aBuffer) + 1;
2095 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
2098 Delete(aBuffer, Separator, 255);
2099 Separator := Pos(AnsiString('.'), aBuffer);
2101 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
2102 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2106 ///////////////////////////////////////////////////////////////////////////////////////////
2107 function CheckExtension(const Extension: AnsiString): Boolean;
2111 ExtPos := Pos(Extension, Buffer);
2112 result := ExtPos > 0;
2114 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2117 ///////////////////////////////////////////////////////////////////////////////////////////
2118 function CheckVersion(const aMajor, aMinor: Integer): Boolean;
2120 result := (MajorVersion > aMajor) or ((MajorVersion = aMajor) and (MinorVersion >= aMinor));
2124 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2127 if not OpenGLInitialized then begin
2129 OpenGLInitialized := true;
2137 Buffer := glGetString(GL_VERSION);
2138 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2140 GL_VERSION_1_2 := CheckVersion(1, 2);
2141 GL_VERSION_1_3 := CheckVersion(1, 3);
2142 GL_VERSION_1_4 := CheckVersion(1, 4);
2143 GL_VERSION_2_0 := CheckVersion(2, 0);
2144 GL_VERSION_3_3 := CheckVersion(3, 3);
2147 Buffer := glGetString(GL_EXTENSIONS);
2148 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2149 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2150 GL_ARB_texture_swizzle := CheckExtension('GL_ARB_texture_swizzle');
2151 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
2152 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2153 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2154 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2155 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2156 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2157 GL_EXT_texture_swizzle := CheckExtension('GL_EXT_texture_swizzle');
2158 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
2159 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2160 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2161 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2163 if GL_VERSION_1_3 then begin
2164 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2165 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2166 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2168 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB', nil, false);
2169 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB', nil, false);
2170 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB', nil, false);
2175 {$IFDEF GLB_SDL_IMAGE}
2176 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2177 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2178 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2179 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2181 result := TStream(context^.unknown.data1).Seek(offset, whence);
2184 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2186 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2189 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2191 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2194 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2199 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2201 result := SDL_AllocRW;
2203 if result = nil then
2204 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2206 result^.seek := glBitmapRWseek;
2207 result^.read := glBitmapRWread;
2208 result^.write := glBitmapRWwrite;
2209 result^.close := glBitmapRWclose;
2210 result^.unknown.data1 := Stream;
2214 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2215 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2217 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2220 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2221 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2223 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2227 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2229 glBitmapDefaultMipmap := aValue;
2232 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2233 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2235 glBitmapDefaultFormat := aFormat;
2238 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2239 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2241 glBitmapDefaultFilterMin := aMin;
2242 glBitmapDefaultFilterMag := aMag;
2245 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2246 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2248 glBitmapDefaultWrapS := S;
2249 glBitmapDefaultWrapT := T;
2250 glBitmapDefaultWrapR := R;
2253 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2254 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
2256 glDefaultSwizzle[0] := r;
2257 glDefaultSwizzle[1] := g;
2258 glDefaultSwizzle[2] := b;
2259 glDefaultSwizzle[3] := a;
2262 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2263 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2265 result := glBitmapDefaultDeleteTextureOnFree;
2268 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2269 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2271 result := glBitmapDefaultFreeDataAfterGenTextures;
2274 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2275 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2277 result := glBitmapDefaultMipmap;
2280 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2281 function glBitmapGetDefaultFormat: TglBitmapFormat;
2283 result := glBitmapDefaultFormat;
2286 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2287 procedure glBitmapGetDefaultFilter(var aMin, aMag: GLenum);
2289 aMin := glBitmapDefaultFilterMin;
2290 aMag := glBitmapDefaultFilterMag;
2293 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2294 procedure glBitmapGetDefaultTextureWrap(var S, T, R: GLenum);
2296 S := glBitmapDefaultWrapS;
2297 T := glBitmapDefaultWrapT;
2298 R := glBitmapDefaultWrapR;
2301 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2302 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
2304 r := glDefaultSwizzle[0];
2305 g := glDefaultSwizzle[1];
2306 b := glDefaultSwizzle[2];
2307 a := glDefaultSwizzle[3];
2310 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2311 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2312 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2313 function TFormatDescriptor.GetRedMask: QWord;
2315 result := fRange.r shl fShift.r;
2318 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2319 function TFormatDescriptor.GetGreenMask: QWord;
2321 result := fRange.g shl fShift.g;
2324 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2325 function TFormatDescriptor.GetBlueMask: QWord;
2327 result := fRange.b shl fShift.b;
2330 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2331 function TFormatDescriptor.GetAlphaMask: QWord;
2333 result := fRange.a shl fShift.a;
2336 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2337 function TFormatDescriptor.GetIsCompressed: Boolean;
2339 result := fIsCompressed;
2342 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2343 function TFormatDescriptor.GetHasAlpha: Boolean;
2345 result := (fRange.a > 0);
2348 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2349 function TFormatDescriptor.GetglFormat: GLenum;
2351 result := fglFormat;
2354 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2355 function TFormatDescriptor.GetglInternalFormat: GLenum;
2357 result := fglInternalFormat;
2360 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2361 function TFormatDescriptor.GetglDataFormat: GLenum;
2363 result := fglDataFormat;
2366 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2367 function TFormatDescriptor.GetComponents: Integer;
2373 if (fRange.arr[i] > 0) then
2377 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2378 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2382 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2383 w := Max(1, aSize.X);
2384 h := Max(1, aSize.Y);
2385 result := GetSize(w, h);
2390 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2391 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2394 if (aWidth <= 0) or (aHeight <= 0) then
2396 result := Ceil(aWidth * aHeight * fPixelSize);
2399 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2400 function TFormatDescriptor.CreateMappingData: Pointer;
2405 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2406 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2411 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2412 function TFormatDescriptor.IsEmpty: Boolean;
2414 result := (fFormat = tfEmpty);
2417 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2418 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2421 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2422 raise EglBitmap.Create('FormatCheckFormat - All Masks are 0');
2423 if (aRedMask <> RedMask) then
2425 if (aGreenMask <> GreenMask) then
2427 if (aBlueMask <> BlueMask) then
2429 if (aAlphaMask <> AlphaMask) then
2434 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2435 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2437 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2438 aPixel.Data := fRange;
2439 aPixel.Range := fRange;
2440 aPixel.Format := fFormat;
2443 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2444 constructor TFormatDescriptor.Create;
2449 fWithAlpha := tfEmpty;
2450 fWithoutAlpha := tfEmpty;
2451 fRGBInverted := tfEmpty;
2452 fUncompressed := tfEmpty;
2454 fIsCompressed := false;
2457 fglInternalFormat := 0;
2460 FillChar(fRange, 0, SizeOf(fRange));
2461 FillChar(fShift, 0, SizeOf(fShift));
2464 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2465 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2466 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2467 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2469 aData^ := aPixel.Data.a;
2473 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2478 aPixel.Data.a := aData^;
2482 constructor TfdAlpha_UB1.Create;
2487 fglFormat := GL_ALPHA;
2488 fglDataFormat := GL_UNSIGNED_BYTE;
2491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2492 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2493 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2494 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2496 aData^ := LuminanceWeight(aPixel);
2500 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2502 aPixel.Data.r := aData^;
2503 aPixel.Data.g := aData^;
2504 aPixel.Data.b := aData^;
2509 constructor TfdLuminance_UB1.Create;
2516 fglFormat := GL_LUMINANCE;
2517 fglDataFormat := GL_UNSIGNED_BYTE;
2520 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2521 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2522 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2523 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2529 if (fRange.arr[i] > 0) then
2530 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2534 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2539 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2543 constructor TfdUniversal_UB1.Create;
2549 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2550 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2551 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2552 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2554 inherited Map(aPixel, aData, aMapData);
2555 aData^ := aPixel.Data.a;
2559 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2561 inherited Unmap(aData, aPixel, aMapData);
2562 aPixel.Data.a := aData^;
2566 constructor TfdLuminanceAlpha_UB2.Create;
2572 fglFormat := GL_LUMINANCE_ALPHA;
2573 fglDataFormat := GL_UNSIGNED_BYTE;
2576 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2577 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2578 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2579 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2581 aData^ := aPixel.Data.r;
2583 aData^ := aPixel.Data.g;
2585 aData^ := aPixel.Data.b;
2589 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2591 aPixel.Data.r := aData^;
2593 aPixel.Data.g := aData^;
2595 aPixel.Data.b := aData^;
2600 constructor TfdRGB_UB3.Create;
2610 fglFormat := GL_RGB;
2611 fglDataFormat := GL_UNSIGNED_BYTE;
2614 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2615 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2616 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2617 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2619 aData^ := aPixel.Data.b;
2621 aData^ := aPixel.Data.g;
2623 aData^ := aPixel.Data.r;
2627 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2629 aPixel.Data.b := aData^;
2631 aPixel.Data.g := aData^;
2633 aPixel.Data.r := aData^;
2638 constructor TfdBGR_UB3.Create;
2647 fglFormat := GL_BGR;
2648 fglDataFormat := GL_UNSIGNED_BYTE;
2651 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2652 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2653 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2654 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2656 inherited Map(aPixel, aData, aMapData);
2657 aData^ := aPixel.Data.a;
2661 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2663 inherited Unmap(aData, aPixel, aMapData);
2664 aPixel.Data.a := aData^;
2668 constructor TfdRGBA_UB4.Create;
2674 fglFormat := GL_RGBA;
2675 fglDataFormat := GL_UNSIGNED_BYTE;
2678 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2679 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2680 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2681 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2683 inherited Map(aPixel, aData, aMapData);
2684 aData^ := aPixel.Data.a;
2688 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2690 inherited Unmap(aData, aPixel, aMapData);
2691 aPixel.Data.a := aData^;
2695 constructor TfdBGRA_UB4.Create;
2701 fglFormat := GL_BGRA;
2702 fglDataFormat := GL_UNSIGNED_BYTE;
2705 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2706 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2707 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2708 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2710 PWord(aData)^ := aPixel.Data.a;
2714 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2719 aPixel.Data.a := PWord(aData)^;
2723 constructor TfdAlpha_US1.Create;
2728 fglFormat := GL_ALPHA;
2729 fglDataFormat := GL_UNSIGNED_SHORT;
2732 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2733 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2734 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2735 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2737 PWord(aData)^ := LuminanceWeight(aPixel);
2741 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2743 aPixel.Data.r := PWord(aData)^;
2744 aPixel.Data.g := PWord(aData)^;
2745 aPixel.Data.b := PWord(aData)^;
2750 constructor TfdLuminance_US1.Create;
2757 fglFormat := GL_LUMINANCE;
2758 fglDataFormat := GL_UNSIGNED_SHORT;
2761 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2762 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2763 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2764 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2770 if (fRange.arr[i] > 0) then
2771 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2775 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2780 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2784 constructor TfdUniversal_US1.Create;
2790 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2791 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2792 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2793 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2795 PWord(aData)^ := DepthWeight(aPixel);
2799 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2801 aPixel.Data.r := PWord(aData)^;
2802 aPixel.Data.g := PWord(aData)^;
2803 aPixel.Data.b := PWord(aData)^;
2808 constructor TfdDepth_US1.Create;
2815 fglFormat := GL_DEPTH_COMPONENT;
2816 fglDataFormat := GL_UNSIGNED_SHORT;
2819 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2820 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2821 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2822 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2824 inherited Map(aPixel, aData, aMapData);
2825 PWord(aData)^ := aPixel.Data.a;
2829 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2831 inherited Unmap(aData, aPixel, aMapData);
2832 aPixel.Data.a := PWord(aData)^;
2836 constructor TfdLuminanceAlpha_US2.Create;
2842 fglFormat := GL_LUMINANCE_ALPHA;
2843 fglDataFormat := GL_UNSIGNED_SHORT;
2846 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2847 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2848 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2849 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2851 PWord(aData)^ := aPixel.Data.r;
2853 PWord(aData)^ := aPixel.Data.g;
2855 PWord(aData)^ := aPixel.Data.b;
2859 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2861 aPixel.Data.r := PWord(aData)^;
2863 aPixel.Data.g := PWord(aData)^;
2865 aPixel.Data.b := PWord(aData)^;
2870 constructor TfdRGB_US3.Create;
2880 fglFormat := GL_RGB;
2881 fglDataFormat := GL_UNSIGNED_SHORT;
2884 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2885 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2886 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2887 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2889 PWord(aData)^ := aPixel.Data.b;
2891 PWord(aData)^ := aPixel.Data.g;
2893 PWord(aData)^ := aPixel.Data.r;
2897 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2899 aPixel.Data.b := PWord(aData)^;
2901 aPixel.Data.g := PWord(aData)^;
2903 aPixel.Data.r := PWord(aData)^;
2908 constructor TfdBGR_US3.Create;
2918 fglFormat := GL_BGR;
2919 fglDataFormat := GL_UNSIGNED_SHORT;
2922 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2923 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2924 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2925 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2927 inherited Map(aPixel, aData, aMapData);
2928 PWord(aData)^ := aPixel.Data.a;
2932 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2934 inherited Unmap(aData, aPixel, aMapData);
2935 aPixel.Data.a := PWord(aData)^;
2939 constructor TfdRGBA_US4.Create;
2945 fglFormat := GL_RGBA;
2946 fglDataFormat := GL_UNSIGNED_SHORT;
2949 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2950 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2951 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2952 procedure TfdBGRA_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 TfdBGRA_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 TfdBGRA_US4.Create;
2972 fglFormat := GL_BGRA;
2973 fglDataFormat := GL_UNSIGNED_SHORT;
2976 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2977 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2978 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2979 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2983 PCardinal(aData)^ := 0;
2985 if (fRange.arr[i] > 0) then
2986 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2990 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2995 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2999 constructor TfdUniversal_UI1.Create;
3005 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3006 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3007 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3008 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3010 PCardinal(aData)^ := DepthWeight(aPixel);
3014 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3016 aPixel.Data.r := PCardinal(aData)^;
3017 aPixel.Data.g := PCardinal(aData)^;
3018 aPixel.Data.b := PCardinal(aData)^;
3023 constructor TfdDepth_UI1.Create;
3027 fRange.r := $FFFFFFFF;
3028 fRange.g := $FFFFFFFF;
3029 fRange.b := $FFFFFFFF;
3030 fglFormat := GL_DEPTH_COMPONENT;
3031 fglDataFormat := GL_UNSIGNED_INT;
3034 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3035 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3036 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3037 constructor TfdAlpha4.Create;
3040 fFormat := tfAlpha4;
3041 fWithAlpha := tfAlpha4;
3042 fglInternalFormat := GL_ALPHA4;
3045 constructor TfdAlpha8.Create;
3048 fFormat := tfAlpha8;
3049 fWithAlpha := tfAlpha8;
3050 fglInternalFormat := GL_ALPHA8;
3053 constructor TfdAlpha12.Create;
3056 fFormat := tfAlpha12;
3057 fWithAlpha := tfAlpha12;
3058 fglInternalFormat := GL_ALPHA12;
3061 constructor TfdAlpha16.Create;
3064 fFormat := tfAlpha16;
3065 fWithAlpha := tfAlpha16;
3066 fglInternalFormat := GL_ALPHA16;
3069 constructor TfdLuminance4.Create;
3072 fFormat := tfLuminance4;
3073 fWithAlpha := tfLuminance4Alpha4;
3074 fWithoutAlpha := tfLuminance4;
3075 fglInternalFormat := GL_LUMINANCE4;
3078 constructor TfdLuminance8.Create;
3081 fFormat := tfLuminance8;
3082 fWithAlpha := tfLuminance8Alpha8;
3083 fWithoutAlpha := tfLuminance8;
3084 fglInternalFormat := GL_LUMINANCE8;
3087 constructor TfdLuminance12.Create;
3090 fFormat := tfLuminance12;
3091 fWithAlpha := tfLuminance12Alpha12;
3092 fWithoutAlpha := tfLuminance12;
3093 fglInternalFormat := GL_LUMINANCE12;
3096 constructor TfdLuminance16.Create;
3099 fFormat := tfLuminance16;
3100 fWithAlpha := tfLuminance16Alpha16;
3101 fWithoutAlpha := tfLuminance16;
3102 fglInternalFormat := GL_LUMINANCE16;
3105 constructor TfdLuminance4Alpha4.Create;
3108 fFormat := tfLuminance4Alpha4;
3109 fWithAlpha := tfLuminance4Alpha4;
3110 fWithoutAlpha := tfLuminance4;
3111 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3114 constructor TfdLuminance6Alpha2.Create;
3117 fFormat := tfLuminance6Alpha2;
3118 fWithAlpha := tfLuminance6Alpha2;
3119 fWithoutAlpha := tfLuminance8;
3120 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3123 constructor TfdLuminance8Alpha8.Create;
3126 fFormat := tfLuminance8Alpha8;
3127 fWithAlpha := tfLuminance8Alpha8;
3128 fWithoutAlpha := tfLuminance8;
3129 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3132 constructor TfdLuminance12Alpha4.Create;
3135 fFormat := tfLuminance12Alpha4;
3136 fWithAlpha := tfLuminance12Alpha4;
3137 fWithoutAlpha := tfLuminance12;
3138 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3141 constructor TfdLuminance12Alpha12.Create;
3144 fFormat := tfLuminance12Alpha12;
3145 fWithAlpha := tfLuminance12Alpha12;
3146 fWithoutAlpha := tfLuminance12;
3147 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3150 constructor TfdLuminance16Alpha16.Create;
3153 fFormat := tfLuminance16Alpha16;
3154 fWithAlpha := tfLuminance16Alpha16;
3155 fWithoutAlpha := tfLuminance16;
3156 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3159 constructor TfdR3G3B2.Create;
3162 fFormat := tfR3G3B2;
3163 fWithAlpha := tfRGBA2;
3164 fWithoutAlpha := tfR3G3B2;
3171 fglFormat := GL_RGB;
3172 fglInternalFormat := GL_R3_G3_B2;
3173 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3176 constructor TfdRGB4.Create;
3180 fWithAlpha := tfRGBA4;
3181 fWithoutAlpha := tfRGB4;
3182 fRGBInverted := tfBGR4;
3189 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3190 fglInternalFormat := GL_RGB4;
3191 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3194 constructor TfdR5G6B5.Create;
3197 fFormat := tfR5G6B5;
3198 fWithAlpha := tfRGBA4;
3199 fWithoutAlpha := tfR5G6B5;
3200 fRGBInverted := tfB5G6R5;
3207 fglFormat := GL_RGB;
3208 fglInternalFormat := GL_RGB565;
3209 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3212 constructor TfdRGB5.Create;
3216 fWithAlpha := tfRGB5A1;
3217 fWithoutAlpha := tfRGB5;
3218 fRGBInverted := tfBGR5;
3225 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3226 fglInternalFormat := GL_RGB5;
3227 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3230 constructor TfdRGB8.Create;
3234 fWithAlpha := tfRGBA8;
3235 fWithoutAlpha := tfRGB8;
3236 fRGBInverted := tfBGR8;
3237 fglInternalFormat := GL_RGB8;
3240 constructor TfdRGB10.Create;
3244 fWithAlpha := tfRGB10A2;
3245 fWithoutAlpha := tfRGB10;
3246 fRGBInverted := tfBGR10;
3253 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3254 fglInternalFormat := GL_RGB10;
3255 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3258 constructor TfdRGB12.Create;
3262 fWithAlpha := tfRGBA12;
3263 fWithoutAlpha := tfRGB12;
3264 fRGBInverted := tfBGR12;
3265 fglInternalFormat := GL_RGB12;
3268 constructor TfdRGB16.Create;
3272 fWithAlpha := tfRGBA16;
3273 fWithoutAlpha := tfRGB16;
3274 fRGBInverted := tfBGR16;
3275 fglInternalFormat := GL_RGB16;
3278 constructor TfdRGBA2.Create;
3282 fWithAlpha := tfRGBA2;
3283 fWithoutAlpha := tfR3G3B2;
3284 fRGBInverted := tfBGRA2;
3285 fglInternalFormat := GL_RGBA2;
3288 constructor TfdRGBA4.Create;
3292 fWithAlpha := tfRGBA4;
3293 fWithoutAlpha := tfRGB4;
3294 fRGBInverted := tfBGRA4;
3303 fglFormat := GL_RGBA;
3304 fglInternalFormat := GL_RGBA4;
3305 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3308 constructor TfdRGB5A1.Create;
3311 fFormat := tfRGB5A1;
3312 fWithAlpha := tfRGB5A1;
3313 fWithoutAlpha := tfRGB5;
3314 fRGBInverted := tfBGR5A1;
3323 fglFormat := GL_RGBA;
3324 fglInternalFormat := GL_RGB5_A1;
3325 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3328 constructor TfdRGBA8.Create;
3332 fWithAlpha := tfRGBA8;
3333 fWithoutAlpha := tfRGB8;
3334 fRGBInverted := tfBGRA8;
3335 fglInternalFormat := GL_RGBA8;
3338 constructor TfdRGB10A2.Create;
3341 fFormat := tfRGB10A2;
3342 fWithAlpha := tfRGB10A2;
3343 fWithoutAlpha := tfRGB10;
3344 fRGBInverted := tfBGR10A2;
3353 fglFormat := GL_RGBA;
3354 fglInternalFormat := GL_RGB10_A2;
3355 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3358 constructor TfdRGBA12.Create;
3361 fFormat := tfRGBA12;
3362 fWithAlpha := tfRGBA12;
3363 fWithoutAlpha := tfRGB12;
3364 fRGBInverted := tfBGRA12;
3365 fglInternalFormat := GL_RGBA12;
3368 constructor TfdRGBA16.Create;
3371 fFormat := tfRGBA16;
3372 fWithAlpha := tfRGBA16;
3373 fWithoutAlpha := tfRGB16;
3374 fRGBInverted := tfBGRA16;
3375 fglInternalFormat := GL_RGBA16;
3378 constructor TfdBGR4.Create;
3383 fWithAlpha := tfBGRA4;
3384 fWithoutAlpha := tfBGR4;
3385 fRGBInverted := tfRGB4;
3394 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3395 fglInternalFormat := GL_RGB4;
3396 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3399 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3400 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3401 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3402 constructor TfdB5G6R5.Create;
3405 fFormat := tfB5G6R5;
3406 fWithAlpha := tfBGRA4;
3407 fWithoutAlpha := tfB5G6R5;
3408 fRGBInverted := tfR5G6B5;
3415 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3416 fglInternalFormat := GL_RGB8;
3417 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3420 constructor TfdBGR5.Create;
3425 fWithAlpha := tfBGR5A1;
3426 fWithoutAlpha := tfBGR5;
3427 fRGBInverted := tfRGB5;
3436 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3437 fglInternalFormat := GL_RGB5;
3438 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3441 constructor TfdBGR8.Create;
3445 fWithAlpha := tfBGRA8;
3446 fWithoutAlpha := tfBGR8;
3447 fRGBInverted := tfRGB8;
3448 fglInternalFormat := GL_RGB8;
3451 constructor TfdBGR10.Create;
3455 fWithAlpha := tfBGR10A2;
3456 fWithoutAlpha := tfBGR10;
3457 fRGBInverted := tfRGB10;
3466 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3467 fglInternalFormat := GL_RGB10;
3468 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3471 constructor TfdBGR12.Create;
3475 fWithAlpha := tfBGRA12;
3476 fWithoutAlpha := tfBGR12;
3477 fRGBInverted := tfRGB12;
3478 fglInternalFormat := GL_RGB12;
3481 constructor TfdBGR16.Create;
3485 fWithAlpha := tfBGRA16;
3486 fWithoutAlpha := tfBGR16;
3487 fRGBInverted := tfRGB16;
3488 fglInternalFormat := GL_RGB16;
3491 constructor TfdBGRA2.Create;
3495 fWithAlpha := tfBGRA4;
3496 fWithoutAlpha := tfBGR4;
3497 fRGBInverted := tfRGBA2;
3498 fglInternalFormat := GL_RGBA2;
3501 constructor TfdBGRA4.Create;
3505 fWithAlpha := tfBGRA4;
3506 fWithoutAlpha := tfBGR4;
3507 fRGBInverted := tfRGBA4;
3516 fglFormat := GL_BGRA;
3517 fglInternalFormat := GL_RGBA4;
3518 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3521 constructor TfdBGR5A1.Create;
3524 fFormat := tfBGR5A1;
3525 fWithAlpha := tfBGR5A1;
3526 fWithoutAlpha := tfBGR5;
3527 fRGBInverted := tfRGB5A1;
3536 fglFormat := GL_BGRA;
3537 fglInternalFormat := GL_RGB5_A1;
3538 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3541 constructor TfdBGRA8.Create;
3545 fWithAlpha := tfBGRA8;
3546 fWithoutAlpha := tfBGR8;
3547 fRGBInverted := tfRGBA8;
3548 fglInternalFormat := GL_RGBA8;
3551 constructor TfdBGR10A2.Create;
3554 fFormat := tfBGR10A2;
3555 fWithAlpha := tfBGR10A2;
3556 fWithoutAlpha := tfBGR10;
3557 fRGBInverted := tfRGB10A2;
3566 fglFormat := GL_BGRA;
3567 fglInternalFormat := GL_RGB10_A2;
3568 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3571 constructor TfdBGRA12.Create;
3574 fFormat := tfBGRA12;
3575 fWithAlpha := tfBGRA12;
3576 fWithoutAlpha := tfBGR12;
3577 fRGBInverted := tfRGBA12;
3578 fglInternalFormat := GL_RGBA12;
3581 constructor TfdBGRA16.Create;
3584 fFormat := tfBGRA16;
3585 fWithAlpha := tfBGRA16;
3586 fWithoutAlpha := tfBGR16;
3587 fRGBInverted := tfRGBA16;
3588 fglInternalFormat := GL_RGBA16;
3591 constructor TfdDepth16.Create;
3594 fFormat := tfDepth16;
3595 fWithAlpha := tfEmpty;
3596 fWithoutAlpha := tfDepth16;
3597 fglInternalFormat := GL_DEPTH_COMPONENT16;
3600 constructor TfdDepth24.Create;
3603 fFormat := tfDepth24;
3604 fWithAlpha := tfEmpty;
3605 fWithoutAlpha := tfDepth24;
3606 fglInternalFormat := GL_DEPTH_COMPONENT24;
3609 constructor TfdDepth32.Create;
3612 fFormat := tfDepth32;
3613 fWithAlpha := tfEmpty;
3614 fWithoutAlpha := tfDepth32;
3615 fglInternalFormat := GL_DEPTH_COMPONENT32;
3618 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3619 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3620 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3621 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3623 raise EglBitmap.Create('mapping for compressed formats is not supported');
3626 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3628 raise EglBitmap.Create('mapping for compressed formats is not supported');
3631 constructor TfdS3tcDtx1RGBA.Create;
3634 fFormat := tfS3tcDtx1RGBA;
3635 fWithAlpha := tfS3tcDtx1RGBA;
3636 fUncompressed := tfRGB5A1;
3638 fIsCompressed := true;
3639 fglFormat := GL_COMPRESSED_RGBA;
3640 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3641 fglDataFormat := GL_UNSIGNED_BYTE;
3644 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3645 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3646 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3647 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3649 raise EglBitmap.Create('mapping for compressed formats is not supported');
3652 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3654 raise EglBitmap.Create('mapping for compressed formats is not supported');
3657 constructor TfdS3tcDtx3RGBA.Create;
3660 fFormat := tfS3tcDtx3RGBA;
3661 fWithAlpha := tfS3tcDtx3RGBA;
3662 fUncompressed := tfRGBA8;
3664 fIsCompressed := true;
3665 fglFormat := GL_COMPRESSED_RGBA;
3666 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3667 fglDataFormat := GL_UNSIGNED_BYTE;
3670 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3671 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3672 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3673 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3675 raise EglBitmap.Create('mapping for compressed formats is not supported');
3678 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3680 raise EglBitmap.Create('mapping for compressed formats is not supported');
3683 constructor TfdS3tcDtx5RGBA.Create;
3686 fFormat := tfS3tcDtx3RGBA;
3687 fWithAlpha := tfS3tcDtx3RGBA;
3688 fUncompressed := tfRGBA8;
3690 fIsCompressed := true;
3691 fglFormat := GL_COMPRESSED_RGBA;
3692 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3693 fglDataFormat := GL_UNSIGNED_BYTE;
3696 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3697 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3698 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3699 class procedure TFormatDescriptor.Init;
3701 if not Assigned(FormatDescriptorCS) then
3702 FormatDescriptorCS := TCriticalSection.Create;
3705 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3706 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3708 FormatDescriptorCS.Enter;
3710 result := FormatDescriptors[aFormat];
3711 if not Assigned(result) then begin
3712 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3713 FormatDescriptors[aFormat] := result;
3716 FormatDescriptorCS.Leave;
3720 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3721 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3723 result := Get(Get(aFormat).WithAlpha);
3726 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3727 class procedure TFormatDescriptor.Clear;
3731 FormatDescriptorCS.Enter;
3733 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3734 FreeAndNil(FormatDescriptors[f]);
3736 FormatDescriptorCS.Leave;
3740 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3741 class procedure TFormatDescriptor.Finalize;
3744 FreeAndNil(FormatDescriptorCS);
3747 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3748 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3749 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3750 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3752 Update(aValue, fRange.r, fShift.r);
3755 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3756 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3758 Update(aValue, fRange.g, fShift.g);
3761 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3762 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3764 Update(aValue, fRange.b, fShift.b);
3767 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3768 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3770 Update(aValue, fRange.a, fShift.a);
3773 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3774 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3781 while (aMask > 0) and ((aMask and 1) = 0) do begin
3783 aMask := aMask shr 1;
3786 while (aMask > 0) do begin
3787 aRange := aRange shl 1;
3788 aMask := aMask shr 1;
3792 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3795 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3796 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3802 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3803 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3804 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3805 ((aPixel.Data.a and fRange.a) shl fShift.a);
3806 s := Round(fPixelSize);
3809 2: PWord(aData)^ := data;
3810 4: PCardinal(aData)^ := data;
3811 8: PQWord(aData)^ := data;
3813 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3818 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3819 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3824 s := Round(fPixelSize);
3827 2: data := PWord(aData)^;
3828 4: data := PCardinal(aData)^;
3829 8: data := PQWord(aData)^;
3831 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3834 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3838 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3839 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3840 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3841 procedure TbmpColorTableFormat.CreateColorTable;
3845 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3846 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3848 if (Format = tfLuminance4) then
3849 SetLength(fColorTable, 16)
3851 SetLength(fColorTable, 256);
3855 for i := 0 to High(fColorTable) do begin
3856 fColorTable[i].r := 16 * i;
3857 fColorTable[i].g := 16 * i;
3858 fColorTable[i].b := 16 * i;
3859 fColorTable[i].a := 0;
3864 for i := 0 to High(fColorTable) do begin
3865 fColorTable[i].r := i;
3866 fColorTable[i].g := i;
3867 fColorTable[i].b := i;
3868 fColorTable[i].a := 0;
3873 for i := 0 to High(fColorTable) do begin
3874 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3875 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3876 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3877 fColorTable[i].a := 0;
3883 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3884 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3888 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3889 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3893 if (aMapData = nil) then
3895 d := LuminanceWeight(aPixel) and Range.r;
3896 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3897 inc(PByte(aMapData), 4);
3898 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3905 aData^ := LuminanceWeight(aPixel) and Range.r;
3911 ((aPixel.Data.r and Range.r) shl Shift.r) or
3912 ((aPixel.Data.g and Range.g) shl Shift.g) or
3913 ((aPixel.Data.b and Range.b) shl Shift.b));
3919 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3920 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3927 s := Trunc(fPixelSize);
3928 f := fPixelSize - s;
3929 bits := Round(8 * f);
3931 0: idx := (aData^ shr (8 - bits - {%H-}PtrInt(aMapData))) and ((1 shl bits) - 1);
3933 2: idx := PWord(aData)^;
3934 4: idx := PCardinal(aData)^;
3935 8: idx := PQWord(aData)^;
3937 raise EglBitmap.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3939 if (idx >= Length(fColorTable)) then
3940 raise EglBitmap.CreateFmt('invalid color index: %d', [idx]);
3941 with fColorTable[idx] do begin
3947 inc(PByte(aMapData), bits);
3948 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3950 dec(PByte(aMapData), 8);
3955 destructor TbmpColorTableFormat.Destroy;
3957 SetLength(fColorTable, 0);
3961 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3962 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3963 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3964 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
3968 for i := 0 to 3 do begin
3969 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
3970 if (aSourceFD.Range.arr[i] > 0) then
3971 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
3973 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
3978 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3979 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
3981 with aFuncRec do begin
3982 if (Source.Range.r > 0) then
3983 Dest.Data.r := Source.Data.r;
3984 if (Source.Range.g > 0) then
3985 Dest.Data.g := Source.Data.g;
3986 if (Source.Range.b > 0) then
3987 Dest.Data.b := Source.Data.b;
3988 if (Source.Range.a > 0) then
3989 Dest.Data.a := Source.Data.a;
3993 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3994 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3998 with aFuncRec do begin
4000 if (Source.Range.arr[i] > 0) then
4001 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4006 TShiftData = packed record
4008 0: (r, g, b, a: SmallInt);
4009 1: (arr: array[0..3] of SmallInt);
4011 PShiftData = ^TShiftData;
4013 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4014 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4020 if (Source.Range.arr[i] > 0) then
4021 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4024 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4025 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4027 with aFuncRec do begin
4028 Dest.Data := Source.Data;
4029 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4030 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4031 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4032 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4034 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4035 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4040 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4041 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4045 with aFuncRec do begin
4047 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4051 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4052 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4056 with FuncRec do begin
4057 if (FuncRec.Args = nil) then begin //source has no alpha
4059 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4060 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4061 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4062 Dest.Data.a := Round(Dest.Range.a * Temp);
4064 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4068 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4069 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4071 PglBitmapPixelData = ^TglBitmapPixelData;
4073 with FuncRec do begin
4074 Dest.Data.r := Source.Data.r;
4075 Dest.Data.g := Source.Data.g;
4076 Dest.Data.b := Source.Data.b;
4078 with PglBitmapPixelData(Args)^ do
4079 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4080 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4081 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4084 Dest.Data.a := Dest.Range.a;
4088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4089 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4091 with FuncRec do begin
4092 Dest.Data.r := Source.Data.r;
4093 Dest.Data.g := Source.Data.g;
4094 Dest.Data.b := Source.Data.b;
4095 Dest.Data.a := PCardinal(Args)^;
4099 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4100 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4103 TRGBPix = array [0..2] of byte;
4107 while aWidth > 0 do begin
4108 Temp := PRGBPix(aData)^[0];
4109 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4110 PRGBPix(aData)^[2] := Temp;
4120 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4121 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4123 function TglBitmap.GetFormatDesc: TglBitmapFormatDescriptor;
4125 result := TFormatDescriptor.Get(Format);
4128 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4129 function TglBitmap.GetWidth: Integer;
4131 if (ffX in fDimension.Fields) then
4132 result := fDimension.X
4137 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4138 function TglBitmap.GetHeight: Integer;
4140 if (ffY in fDimension.Fields) then
4141 result := fDimension.Y
4146 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4147 function TglBitmap.GetFileWidth: Integer;
4149 result := Max(1, Width);
4152 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4153 function TglBitmap.GetFileHeight: Integer;
4155 result := Max(1, Height);
4158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4159 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4161 if fCustomData = aValue then
4163 fCustomData := aValue;
4166 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4167 procedure TglBitmap.SetCustomName(const aValue: String);
4169 if fCustomName = aValue then
4171 fCustomName := aValue;
4174 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4175 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4177 if fCustomNameW = aValue then
4179 fCustomNameW := aValue;
4182 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4183 procedure TglBitmap.SetFreeDataOnDestroy(const aValue: Boolean);
4185 if fFreeDataOnDestroy = aValue then
4187 fFreeDataOnDestroy := aValue;
4190 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4191 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4193 if fDeleteTextureOnFree = aValue then
4195 fDeleteTextureOnFree := aValue;
4198 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4199 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4201 if fFormat = aValue then
4203 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4204 raise EglBitmapUnsupportedFormat.Create(Format);
4205 SetDataPointer(fData, aValue, Width, Height); //be careful, Data could be freed by this method
4208 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4209 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4211 if fFreeDataAfterGenTexture = aValue then
4213 fFreeDataAfterGenTexture := aValue;
4216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4217 procedure TglBitmap.SetID(const aValue: Cardinal);
4219 if fID = aValue then
4224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4225 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4227 if fMipMap = aValue then
4232 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4233 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4235 if fTarget = aValue then
4240 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4241 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4243 MaxAnisotropic: Integer;
4245 fAnisotropic := aValue;
4246 if (ID > 0) then begin
4247 if GL_EXT_texture_filter_anisotropic then begin
4248 if fAnisotropic > 0 then begin
4250 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4251 if aValue > MaxAnisotropic then
4252 fAnisotropic := MaxAnisotropic;
4253 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4261 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4262 procedure TglBitmap.CreateID;
4265 glDeleteTextures(1, @fID);
4266 glGenTextures(1, @fID);
4270 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4271 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4273 // Set Up Parameters
4274 SetWrap(fWrapS, fWrapT, fWrapR);
4275 SetFilter(fFilterMin, fFilterMag);
4276 SetAnisotropic(fAnisotropic);
4277 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4279 if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
4280 SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4282 // Mip Maps Generation Mode
4283 aBuildWithGlu := false;
4284 if (MipMap = mmMipmap) then begin
4285 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4286 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4288 aBuildWithGlu := true;
4289 end else if (MipMap = mmMipmapGlu) then
4290 aBuildWithGlu := true;
4293 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4294 procedure TglBitmap.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
4295 const aWidth: Integer; const aHeight: Integer);
4299 if (Data <> aData) then begin
4300 if (Assigned(Data)) then
4305 if not Assigned(fData) then begin
4309 FillChar(fDimension, SizeOf(fDimension), 0);
4310 if aWidth <> -1 then begin
4311 fDimension.Fields := fDimension.Fields + [ffX];
4312 fDimension.X := aWidth;
4315 if aHeight <> -1 then begin
4316 fDimension.Fields := fDimension.Fields + [ffY];
4317 fDimension.Y := aHeight;
4320 s := TFormatDescriptor.Get(aFormat).PixelSize;
4322 fPixelSize := Ceil(s);
4323 fRowSize := Ceil(s * aWidth);
4327 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4328 function TglBitmap.FlipHorz: Boolean;
4333 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4334 function TglBitmap.FlipVert: Boolean;
4339 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4340 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4341 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4342 procedure TglBitmap.AfterConstruction;
4344 inherited AfterConstruction;
4348 fIsResident := false;
4350 fMipMap := glBitmapDefaultMipmap;
4351 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4352 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4354 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4355 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4356 glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4359 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4360 procedure TglBitmap.BeforeDestruction;
4364 if fFreeDataOnDestroy then begin
4366 SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
4368 if (fID > 0) and fDeleteTextureOnFree then
4369 glDeleteTextures(1, @fID);
4370 inherited BeforeDestruction;
4373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4374 procedure TglBitmap.PrepareResType(var aResource: String; var aResType: PChar);
4378 if not Assigned(aResType) then begin
4379 TempPos := Pos('.', aResource);
4380 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4381 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4385 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4386 procedure TglBitmap.LoadFromFile(const aFilename: String);
4390 if not FileExists(aFilename) then
4391 raise EglBitmap.Create('file does not exist: ' + aFilename);
4392 fFilename := aFilename;
4393 fs := TFileStream.Create(fFilename, fmOpenRead);
4402 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4403 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4405 {$IFDEF GLB_SUPPORT_PNG_READ}
4406 if not LoadPNG(aStream) then
4408 {$IFDEF GLB_SUPPORT_JPEG_READ}
4409 if not LoadJPEG(aStream) then
4411 if not LoadDDS(aStream) then
4412 if not LoadTGA(aStream) then
4413 if not LoadBMP(aStream) then
4414 raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4417 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4418 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4419 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4424 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4425 GetMem(tmpData, size);
4427 FillChar(tmpData^, size, #$FF);
4428 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
4430 if Assigned(tmpData) then
4434 AddFunc(Self, aFunc, false, aFormat, aArgs);
4437 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4438 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
4440 rs: TResourceStream;
4442 PrepareResType(aResource, aResType);
4443 rs := TResourceStream.Create(aInstance, aResource, aResType);
4451 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4452 procedure TglBitmap.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4454 rs: TResourceStream;
4456 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
4464 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4465 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4469 fs := TFileStream.Create(aFileName, fmCreate);
4472 SaveToStream(fs, aFileType);
4478 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4479 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4482 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4483 ftPNG: SavePNG(aStream);
4485 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4486 ftJPEG: SaveJPEG(aStream);
4488 ftDDS: SaveDDS(aStream);
4489 ftTGA: SaveTGA(aStream);
4490 ftBMP: SaveBMP(aStream);
4494 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4495 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4497 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4500 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4501 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4502 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4504 DestData, TmpData, SourceData: pByte;
4505 TempHeight, TempWidth: Integer;
4506 SourceFD, DestFD: TFormatDescriptor;
4507 SourceMD, DestMD: Pointer;
4509 FuncRec: TglBitmapFunctionRec;
4511 Assert(Assigned(Data));
4512 Assert(Assigned(aSource));
4513 Assert(Assigned(aSource.Data));
4516 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4517 SourceFD := TFormatDescriptor.Get(aSource.Format);
4518 DestFD := TFormatDescriptor.Get(aFormat);
4520 if (SourceFD.IsCompressed) then
4521 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
4522 if (DestFD.IsCompressed) then
4523 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
4525 // inkompatible Formats so CreateTemp
4526 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4527 aCreateTemp := true;
4530 TempHeight := Max(1, aSource.Height);
4531 TempWidth := Max(1, aSource.Width);
4533 FuncRec.Sender := Self;
4534 FuncRec.Args := aArgs;
4537 if aCreateTemp then begin
4538 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
4539 DestData := TmpData;
4544 SourceFD.PreparePixel(FuncRec.Source);
4545 DestFD.PreparePixel (FuncRec.Dest);
4547 SourceMD := SourceFD.CreateMappingData;
4548 DestMD := DestFD.CreateMappingData;
4550 FuncRec.Size := aSource.Dimension;
4551 FuncRec.Position.Fields := FuncRec.Size.Fields;
4554 SourceData := aSource.Data;
4555 FuncRec.Position.Y := 0;
4556 while FuncRec.Position.Y < TempHeight do begin
4557 FuncRec.Position.X := 0;
4558 while FuncRec.Position.X < TempWidth do begin
4559 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4561 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4562 inc(FuncRec.Position.X);
4564 inc(FuncRec.Position.Y);
4567 // Updating Image or InternalFormat
4569 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) //be careful, Data could be freed by this method
4570 else if (aFormat <> fFormat) then
4575 SourceFD.FreeMappingData(SourceMD);
4576 DestFD.FreeMappingData(DestMD);
4579 if aCreateTemp and Assigned(TmpData) then
4587 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4588 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4590 Row, RowSize: Integer;
4591 SourceData, TmpData: PByte;
4593 FormatDesc: TFormatDescriptor;
4595 function GetRowPointer(Row: Integer): pByte;
4597 result := aSurface.pixels;
4598 Inc(result, Row * RowSize);
4604 FormatDesc := TFormatDescriptor.Get(Format);
4605 if FormatDesc.IsCompressed then
4606 raise EglBitmapUnsupportedFormat.Create(Format);
4608 if Assigned(Data) then begin
4609 case Trunc(FormatDesc.PixelSize) of
4615 raise EglBitmapUnsupportedFormat.Create(Format);
4618 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4619 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4621 RowSize := FormatDesc.GetSize(FileWidth, 1);
4623 for Row := 0 to FileHeight-1 do begin
4624 TmpData := GetRowPointer(Row);
4625 if Assigned(TmpData) then begin
4626 Move(SourceData^, TmpData^, RowSize);
4627 inc(SourceData, RowSize);
4634 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4635 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4637 pSource, pData, pTempData: PByte;
4638 Row, RowSize, TempWidth, TempHeight: Integer;
4639 IntFormat: TglBitmapFormat;
4640 FormatDesc: TFormatDescriptor;
4642 function GetRowPointer(Row: Integer): pByte;
4644 result := aSurface^.pixels;
4645 Inc(result, Row * RowSize);
4650 if (Assigned(aSurface)) then begin
4651 with aSurface^.format^ do begin
4652 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4653 FormatDesc := TFormatDescriptor.Get(IntFormat);
4654 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4657 if (IntFormat = tfEmpty) then
4658 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4661 TempWidth := aSurface^.w;
4662 TempHeight := aSurface^.h;
4663 RowSize := FormatDesc.GetSize(TempWidth, 1);
4664 GetMem(pData, TempHeight * RowSize);
4667 for Row := 0 to TempHeight -1 do begin
4668 pSource := GetRowPointer(Row);
4669 if (Assigned(pSource)) then begin
4670 Move(pSource^, pTempData^, RowSize);
4671 Inc(pTempData, RowSize);
4674 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4677 if Assigned(pData) then
4684 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4685 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4687 Row, Col, AlphaInterleave: Integer;
4688 pSource, pDest: PByte;
4690 function GetRowPointer(Row: Integer): pByte;
4692 result := aSurface.pixels;
4693 Inc(result, Row * Width);
4698 if Assigned(Data) then begin
4699 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4700 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4702 AlphaInterleave := 0;
4705 AlphaInterleave := 1;
4707 AlphaInterleave := 3;
4711 for Row := 0 to Height -1 do begin
4712 pDest := GetRowPointer(Row);
4713 if Assigned(pDest) then begin
4714 for Col := 0 to Width -1 do begin
4715 Inc(pSource, AlphaInterleave);
4727 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4728 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4732 bmp := TglBitmap2D.Create;
4734 bmp.AssignFromSurface(aSurface);
4735 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4743 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4744 function CreateGrayPalette: HPALETTE;
4749 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
4751 Pal.palVersion := $300;
4752 Pal.palNumEntries := 256;
4754 for Idx := 0 to Pal.palNumEntries - 1 do begin
4755 Pal.palPalEntry[Idx].peRed := Idx;
4756 Pal.palPalEntry[Idx].peGreen := Idx;
4757 Pal.palPalEntry[Idx].peBlue := Idx;
4758 Pal.palPalEntry[Idx].peFlags := 0;
4760 Result := CreatePalette(Pal^);
4764 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4765 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4768 pSource, pData: PByte;
4771 if Assigned(Data) then begin
4772 if Assigned(aBitmap) then begin
4773 aBitmap.Width := Width;
4774 aBitmap.Height := Height;
4777 tfAlpha8, tfLuminance8: begin
4778 aBitmap.PixelFormat := pf8bit;
4779 aBitmap.Palette := CreateGrayPalette;
4782 aBitmap.PixelFormat := pf15bit;
4784 aBitmap.PixelFormat := pf16bit;
4786 aBitmap.PixelFormat := pf24bit;
4788 aBitmap.PixelFormat := pf32bit;
4790 raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.');
4794 for Row := 0 to FileHeight -1 do begin
4795 pData := aBitmap.Scanline[Row];
4796 Move(pSource^, pData^, fRowSize);
4797 Inc(pSource, fRowSize);
4798 if (Format in [tfRGB8, tfRGBA8]) then // swap RGB(A) to BGR(A)
4799 SwapRGB(pData, FileWidth, Format = tfRGBA8);
4806 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4807 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4809 pSource, pData, pTempData: PByte;
4810 Row, RowSize, TempWidth, TempHeight: Integer;
4811 IntFormat: TglBitmapFormat;
4815 if (Assigned(aBitmap)) then begin
4816 case aBitmap.PixelFormat of
4818 IntFormat := tfLuminance8;
4820 IntFormat := tfRGB5A1;
4822 IntFormat := tfR5G6B5;
4824 IntFormat := tfBGR8;
4826 IntFormat := tfBGRA8;
4828 raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.');
4831 TempWidth := aBitmap.Width;
4832 TempHeight := aBitmap.Height;
4833 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
4834 GetMem(pData, TempHeight * RowSize);
4837 for Row := 0 to TempHeight -1 do begin
4838 pSource := aBitmap.Scanline[Row];
4839 if (Assigned(pSource)) then begin
4840 Move(pSource^, pTempData^, RowSize);
4841 Inc(pTempData, RowSize);
4844 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4847 if Assigned(pData) then
4854 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4855 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4857 Row, Col, AlphaInterleave: Integer;
4858 pSource, pDest: PByte;
4862 if Assigned(Data) then begin
4863 if (Format in [tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8]) then begin
4864 if Assigned(aBitmap) then begin
4865 aBitmap.PixelFormat := pf8bit;
4866 aBitmap.Palette := CreateGrayPalette;
4867 aBitmap.Width := Width;
4868 aBitmap.Height := Height;
4872 AlphaInterleave := 1;
4874 AlphaInterleave := 3;
4876 AlphaInterleave := 0;
4882 for Row := 0 to Height -1 do begin
4883 pDest := aBitmap.Scanline[Row];
4884 if Assigned(pDest) then begin
4885 for Col := 0 to Width -1 do begin
4886 Inc(pSource, AlphaInterleave);
4899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4900 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4904 tex := TglBitmap2D.Create;
4906 tex.AssignFromBitmap(ABitmap);
4907 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4914 {$IFDEF GLB_LAZARUS}
4915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4916 function TglBitmap.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4918 rid: TRawImageDescription;
4919 FormatDesc: TFormatDescriptor;
4922 if not Assigned(aImage) or (Format = tfEmpty) then
4924 FormatDesc := TFormatDescriptor.Get(Format);
4925 if FormatDesc.IsCompressed then
4928 FillChar(rid{%H-}, SizeOf(rid), 0);
4930 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
4931 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
4932 tfLuminance4Alpha4, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16]) then
4933 rid.Format := ricfGray
4935 rid.Format := ricfRGBA;
4938 rid.Height := Height;
4939 rid.Depth := CountSetBits(FormatDesc.RedMask or FormatDesc.GreenMask or FormatDesc.BlueMask or FormatDesc.AlphaMask);
4940 rid.BitOrder := riboBitsInOrder;
4941 rid.ByteOrder := riboLSBFirst;
4942 rid.LineOrder := riloTopToBottom;
4943 rid.LineEnd := rileTight;
4944 rid.BitsPerPixel := Round(8 * FormatDesc.PixelSize);
4945 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
4946 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
4947 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
4948 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
4949 rid.RedShift := FormatDesc.Shift.r;
4950 rid.GreenShift := FormatDesc.Shift.g;
4951 rid.BlueShift := FormatDesc.Shift.b;
4952 rid.AlphaShift := FormatDesc.Shift.a;
4954 rid.MaskBitsPerPixel := 0;
4955 rid.PaletteColorCount := 0;
4957 aImage.DataDescription := rid;
4960 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
4965 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4966 function TglBitmap.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
4969 FormatDesc: TFormatDescriptor;
4974 procedure CopyConvert;
4976 bfFormat: TbmpBitfieldFormat;
4977 pSourceLine, pDestLine: PByte;
4978 pSourceMD, pDestMD: Pointer;
4980 pixel: TglBitmapPixelData;
4982 bfFormat := TbmpBitfieldFormat.Create;
4983 with aImage.DataDescription do begin
4984 bfFormat.RedMask := ((1 shl RedPrec) - 1) shl RedShift;
4985 bfFormat.GreenMask := ((1 shl GreenPrec) - 1) shl GreenShift;
4986 bfFormat.BlueMask := ((1 shl BluePrec) - 1) shl BlueShift;
4987 bfFormat.AlphaMask := ((1 shl AlphaPrec) - 1) shl AlphaShift;
4988 bfFormat.PixelSize := BitsPerPixel / 8;
4990 pSourceMD := bfFormat.CreateMappingData;
4991 pDestMD := FormatDesc.CreateMappingData;
4993 for y := 0 to aImage.Height-1 do begin
4994 pSourceLine := aImage.PixelData + y * aImage.DataDescription.BytesPerLine;
4995 pDestLine := ImageData + y * Round(FormatDesc.PixelSize * aImage.Width);
4996 for x := 0 to aImage.Width-1 do begin
4997 bfFormat.Unmap(pSourceLine, pixel, pSourceMD);
4998 FormatDesc.Map(pixel, pDestLine, pDestMD);
5002 FormatDesc.FreeMappingData(pDestMD);
5003 bfFormat.FreeMappingData(pSourceMD);
5010 if not Assigned(aImage) then
5012 for f := High(f) downto Low(f) do begin
5013 FormatDesc := TFormatDescriptor.Get(f);
5014 with aImage.DataDescription do
5015 if FormatDesc.MaskMatch(
5016 (QWord(1 shl RedPrec )-1) shl RedShift,
5017 (QWord(1 shl GreenPrec)-1) shl GreenShift,
5018 (QWord(1 shl BluePrec )-1) shl BlueShift,
5019 (QWord(1 shl AlphaPrec)-1) shl AlphaShift) then
5023 if (f = tfEmpty) then
5027 (Round(FormatDesc.PixelSize * 8) = aImage.DataDescription.Depth) and
5028 (aImage.DataDescription.BitsPerPixel = aImage.DataDescription.Depth);
5030 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
5031 ImageData := GetMem(ImageSize);
5034 Move(aImage.PixelData^, ImageData^, ImageSize)
5037 SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method
5039 if Assigned(ImageData) then
5047 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5048 function TglBitmap.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
5050 rid: TRawImageDescription;
5051 FormatDesc: TFormatDescriptor;
5052 Pixel: TglBitmapPixelData;
5058 if not Assigned(aImage) or (Format = tfEmpty) then
5060 FormatDesc := TFormatDescriptor.Get(Format);
5061 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5064 FillChar(rid{%H-}, SizeOf(rid), 0);
5065 rid.Format := ricfGray;
5067 rid.Height := Height;
5068 rid.Depth := CountSetBits(FormatDesc.Range.a);
5069 rid.BitOrder := riboBitsInOrder;
5070 rid.ByteOrder := riboLSBFirst;
5071 rid.LineOrder := riloTopToBottom;
5072 rid.LineEnd := rileTight;
5073 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
5074 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
5079 rid.GreenShift := 0;
5081 rid.AlphaShift := 0;
5083 rid.MaskBitsPerPixel := 0;
5084 rid.PaletteColorCount := 0;
5086 aImage.DataDescription := rid;
5089 srcMD := FormatDesc.CreateMappingData;
5091 FormatDesc.PreparePixel(Pixel);
5093 dst := aImage.PixelData;
5094 for y := 0 to Height-1 do
5095 for x := 0 to Width-1 do begin
5096 FormatDesc.Unmap(src, Pixel, srcMD);
5097 case rid.BitsPerPixel of
5099 dst^ := Pixel.Data.a;
5103 PWord(dst)^ := Pixel.Data.a;
5107 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
5108 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
5109 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
5113 PCardinal(dst)^ := Pixel.Data.a;
5117 raise EglBitmapUnsupportedFormat.Create(Format);
5121 FormatDesc.FreeMappingData(srcMD);
5126 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5127 function TglBitmap.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5131 tex := TglBitmap2D.Create;
5133 tex.AssignFromLazIntfImage(aImage);
5134 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5142 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
5143 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5145 rs: TResourceStream;
5147 PrepareResType(aResource, aResType);
5148 rs := TResourceStream.Create(aInstance, aResource, aResType);
5150 result := AddAlphaFromStream(rs, aFunc, aArgs);
5156 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5157 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
5158 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5160 rs: TResourceStream;
5162 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
5164 result := AddAlphaFromStream(rs, aFunc, aArgs);
5170 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5171 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5173 if TFormatDescriptor.Get(Format).IsCompressed then
5174 raise EglBitmapUnsupportedFormat.Create(Format);
5175 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
5178 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5179 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5183 FS := TFileStream.Create(aFileName, fmOpenRead);
5185 result := AddAlphaFromStream(FS, aFunc, aArgs);
5191 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5192 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5196 tex := TglBitmap2D.Create(aStream);
5198 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5204 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5205 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5207 DestData, DestData2, SourceData: pByte;
5208 TempHeight, TempWidth: Integer;
5209 SourceFD, DestFD: TFormatDescriptor;
5210 SourceMD, DestMD, DestMD2: Pointer;
5212 FuncRec: TglBitmapFunctionRec;
5216 Assert(Assigned(Data));
5217 Assert(Assigned(aBitmap));
5218 Assert(Assigned(aBitmap.Data));
5220 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
5221 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
5223 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
5224 DestFD := TFormatDescriptor.Get(Format);
5226 if not Assigned(aFunc) then begin
5227 aFunc := glBitmapAlphaFunc;
5228 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5230 FuncRec.Args := aArgs;
5233 TempHeight := aBitmap.FileHeight;
5234 TempWidth := aBitmap.FileWidth;
5236 FuncRec.Sender := Self;
5237 FuncRec.Size := Dimension;
5238 FuncRec.Position.Fields := FuncRec.Size.Fields;
5242 SourceData := aBitmap.Data;
5245 SourceFD.PreparePixel(FuncRec.Source);
5246 DestFD.PreparePixel (FuncRec.Dest);
5248 SourceMD := SourceFD.CreateMappingData;
5249 DestMD := DestFD.CreateMappingData;
5250 DestMD2 := DestFD.CreateMappingData;
5252 FuncRec.Position.Y := 0;
5253 while FuncRec.Position.Y < TempHeight do begin
5254 FuncRec.Position.X := 0;
5255 while FuncRec.Position.X < TempWidth do begin
5256 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5257 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5259 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5260 inc(FuncRec.Position.X);
5262 inc(FuncRec.Position.Y);
5265 SourceFD.FreeMappingData(SourceMD);
5266 DestFD.FreeMappingData(DestMD);
5267 DestFD.FreeMappingData(DestMD2);
5272 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5273 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5275 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5278 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5279 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5281 PixelData: TglBitmapPixelData;
5283 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5284 result := AddAlphaFromColorKeyFloat(
5285 aRed / PixelData.Range.r,
5286 aGreen / PixelData.Range.g,
5287 aBlue / PixelData.Range.b,
5288 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5291 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5292 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5294 values: array[0..2] of Single;
5297 PixelData: TglBitmapPixelData;
5299 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5300 with PixelData do begin
5302 values[1] := aGreen;
5305 for i := 0 to 2 do begin
5306 tmp := Trunc(Range.arr[i] * aDeviation);
5307 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5308 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5313 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5316 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5317 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5319 result := AddAlphaFromValueFloat(aAlpha / $FF);
5322 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5323 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5325 PixelData: TglBitmapPixelData;
5327 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5328 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5331 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5332 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5334 PixelData: TglBitmapPixelData;
5336 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5338 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5339 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5342 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5343 function TglBitmap.RemoveAlpha: Boolean;
5345 FormatDesc: TFormatDescriptor;
5348 FormatDesc := TFormatDescriptor.Get(Format);
5349 if Assigned(Data) then begin
5350 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5351 raise EglBitmapUnsupportedFormat.Create(Format);
5352 result := ConvertTo(FormatDesc.WithoutAlpha);
5356 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5357 function TglBitmap.Clone: TglBitmap;
5364 Temp := (ClassType.Create as TglBitmap);
5366 // copy texture data if assigned
5367 if Assigned(Data) then begin
5368 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5369 GetMem(TempPtr, Size);
5371 Move(Data^, TempPtr^, Size);
5372 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5374 if Assigned(TempPtr) then
5380 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5385 Temp.fTarget := Target;
5386 Temp.fFormat := Format;
5387 Temp.fMipMap := MipMap;
5388 Temp.fAnisotropic := Anisotropic;
5389 Temp.fBorderColor := fBorderColor;
5390 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5391 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5392 Temp.fFilterMin := fFilterMin;
5393 Temp.fFilterMag := fFilterMag;
5394 Temp.fWrapS := fWrapS;
5395 Temp.fWrapT := fWrapT;
5396 Temp.fWrapR := fWrapR;
5397 Temp.fFilename := fFilename;
5398 Temp.fCustomName := fCustomName;
5399 Temp.fCustomNameW := fCustomNameW;
5400 Temp.fCustomData := fCustomData;
5409 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5410 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5412 SourceFD, DestFD: TFormatDescriptor;
5413 SourcePD, DestPD: TglBitmapPixelData;
5414 ShiftData: TShiftData;
5416 function CanCopyDirect: Boolean;
5419 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5420 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5421 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5422 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5425 function CanShift: Boolean;
5428 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5429 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5430 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5431 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5434 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5437 while (aSource > aDest) and (aSource > 0) do begin
5439 aSource := aSource shr 1;
5444 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5445 SourceFD := TFormatDescriptor.Get(Format);
5446 DestFD := TFormatDescriptor.Get(aFormat);
5448 SourceFD.PreparePixel(SourcePD);
5449 DestFD.PreparePixel (DestPD);
5451 if CanCopyDirect then
5452 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5453 else if CanShift then begin
5454 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5455 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5456 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5457 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5458 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5460 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5465 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5466 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5468 if aUseRGB or aUseAlpha then
5469 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5470 ((Byte(aUseAlpha) and 1) shl 1) or
5471 (Byte(aUseRGB) and 1) ));
5474 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5475 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5477 fBorderColor[0] := aRed;
5478 fBorderColor[1] := aGreen;
5479 fBorderColor[2] := aBlue;
5480 fBorderColor[3] := aAlpha;
5481 if (ID > 0) then begin
5483 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5487 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5488 procedure TglBitmap.FreeData;
5493 SetDataPointer(TempPtr, tfEmpty); //be careful, Data could be freed by this method
5496 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5497 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5498 const aAlpha: Byte);
5500 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5503 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5504 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5506 PixelData: TglBitmapPixelData;
5508 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5510 aRed / PixelData.Range.r,
5511 aGreen / PixelData.Range.g,
5512 aBlue / PixelData.Range.b,
5513 aAlpha / PixelData.Range.a);
5516 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5517 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5519 PixelData: TglBitmapPixelData;
5521 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5522 with PixelData do begin
5523 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5524 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5525 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5526 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5528 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5531 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5532 procedure TglBitmap.SetFilter(const aMin, aMag: GLenum);
5537 fFilterMin := GL_NEAREST;
5539 fFilterMin := GL_LINEAR;
5540 GL_NEAREST_MIPMAP_NEAREST:
5541 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5542 GL_LINEAR_MIPMAP_NEAREST:
5543 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5544 GL_NEAREST_MIPMAP_LINEAR:
5545 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5546 GL_LINEAR_MIPMAP_LINEAR:
5547 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5549 raise EglBitmap.Create('SetFilter - Unknow MIN filter.');
5555 fFilterMag := GL_NEAREST;
5557 fFilterMag := GL_LINEAR;
5559 raise EglBitmap.Create('SetFilter - Unknow MAG filter.');
5563 if (ID > 0) then begin
5565 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5567 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5569 GL_NEAREST, GL_LINEAR:
5570 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5571 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5572 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5573 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5574 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5577 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5581 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5582 procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum);
5584 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5588 aTarget := GL_CLAMP;
5591 aTarget := GL_REPEAT;
5593 GL_CLAMP_TO_EDGE: begin
5594 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5595 aTarget := GL_CLAMP_TO_EDGE
5597 aTarget := GL_CLAMP;
5600 GL_CLAMP_TO_BORDER: begin
5601 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5602 aTarget := GL_CLAMP_TO_BORDER
5604 aTarget := GL_CLAMP;
5607 GL_MIRRORED_REPEAT: begin
5608 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5609 aTarget := GL_MIRRORED_REPEAT
5611 raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5614 raise EglBitmap.Create('SetWrap - Unknow Texturewrap');
5619 CheckAndSetWrap(S, fWrapS);
5620 CheckAndSetWrap(T, fWrapT);
5621 CheckAndSetWrap(R, fWrapR);
5623 if (ID > 0) then begin
5625 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5626 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5627 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5631 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5632 procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum);
5634 procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer);
5636 if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or
5637 (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then
5638 fSwizzle[aIndex] := aValue
5640 raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value');
5644 if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
5645 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
5646 CheckAndSetValue(r, 0);
5647 CheckAndSetValue(g, 1);
5648 CheckAndSetValue(b, 2);
5649 CheckAndSetValue(a, 3);
5651 if (ID > 0) then begin
5653 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, @fSwizzle[0]);
5657 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5658 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5660 if aEnableTextureUnit then
5663 glBindTexture(Target, ID);
5666 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5667 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5669 if aDisableTextureUnit then
5671 glBindTexture(Target, 0);
5674 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5675 constructor TglBitmap.Create;
5677 if (ClassType = TglBitmap) then
5678 raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5679 {$IFDEF GLB_NATIVE_OGL}
5680 glbReadOpenGLExtensions;
5683 fFormat := glBitmapGetDefaultFormat;
5684 fFreeDataOnDestroy := true;
5687 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5688 constructor TglBitmap.Create(const aFileName: String);
5691 LoadFromFile(aFileName);
5694 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5695 constructor TglBitmap.Create(const aStream: TStream);
5698 LoadFromStream(aStream);
5701 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5702 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte);
5707 if not Assigned(aData) then begin
5708 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5709 GetMem(aData, ImageSize);
5711 FillChar(aData^, ImageSize, #$FF);
5712 SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5714 if Assigned(aData) then
5719 SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5720 fFreeDataOnDestroy := false;
5724 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5725 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer);
5728 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5731 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5732 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5735 LoadFromResource(aInstance, aResource, aResType);
5738 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5739 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5742 LoadFromResourceID(aInstance, aResourceID, aResType);
5745 {$IFDEF GLB_SUPPORT_PNG_READ}
5746 {$IF DEFINED(GLB_LAZ_PNG)}
5747 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5748 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5749 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5750 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5753 PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A;
5755 reader: TLazReaderPNG;
5756 intf: TLazIntfImage;
5758 magic: String[MAGIC_LEN];
5761 StreamPos := aStream.Position;
5763 SetLength(magic, MAGIC_LEN);
5764 aStream.Read(magic[1], MAGIC_LEN);
5765 aStream.Position := StreamPos;
5766 if (magic <> PNG_MAGIC) then begin
5771 intf := TLazIntfImage.Create(0, 0);
5772 reader := TLazReaderPNG.Create;
5774 reader.UpdateDescription := true;
5775 reader.ImageRead(aStream, intf);
5776 AssignFromLazIntfImage(intf);
5779 aStream.Position := StreamPos;
5788 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
5789 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5790 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5792 Surface: PSDL_Surface;
5796 RWops := glBitmapCreateRWops(aStream);
5798 if IMG_isPNG(RWops) > 0 then begin
5799 Surface := IMG_LoadPNG_RW(RWops);
5801 AssignFromSurface(Surface);
5804 SDL_FreeSurface(Surface);
5812 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5813 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5814 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5816 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5819 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5820 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5823 signature: array [0..7] of byte;
5825 png_info: png_infop;
5827 TempHeight, TempWidth: Integer;
5828 Format: TglBitmapFormat;
5831 png_rows: array of pByte;
5832 Row, LineSize: Integer;
5836 if not init_libPNG then
5837 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5841 StreamPos := aStream.Position;
5842 aStream.Read(signature{%H-}, 8);
5843 aStream.Position := StreamPos;
5845 if png_check_sig(@signature, 8) <> 0 then begin
5847 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5849 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5852 png_info := png_create_info_struct(png);
5853 if png_info = nil then begin
5854 png_destroy_read_struct(@png, nil, nil);
5855 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5858 // set read callback
5859 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5861 // read informations
5862 png_read_info(png, png_info);
5865 TempHeight := png_get_image_height(png, png_info);
5866 TempWidth := png_get_image_width(png, png_info);
5869 case png_get_color_type(png, png_info) of
5870 PNG_COLOR_TYPE_GRAY:
5871 Format := tfLuminance8;
5872 PNG_COLOR_TYPE_GRAY_ALPHA:
5873 Format := tfLuminance8Alpha8;
5876 PNG_COLOR_TYPE_RGB_ALPHA:
5879 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5882 // cut upper 8 bit from 16 bit formats
5883 if png_get_bit_depth(png, png_info) > 8 then
5884 png_set_strip_16(png);
5886 // expand bitdepth smaller than 8
5887 if png_get_bit_depth(png, png_info) < 8 then
5888 png_set_expand(png);
5890 // allocating mem for scanlines
5891 LineSize := png_get_rowbytes(png, png_info);
5892 GetMem(png_data, TempHeight * LineSize);
5894 SetLength(png_rows, TempHeight);
5895 for Row := Low(png_rows) to High(png_rows) do begin
5896 png_rows[Row] := png_data;
5897 Inc(png_rows[Row], Row * LineSize);
5900 // read complete image into scanlines
5901 png_read_image(png, @png_rows[0]);
5904 png_read_end(png, png_info);
5906 // destroy read struct
5907 png_destroy_read_struct(@png, @png_info, nil);
5909 SetLength(png_rows, 0);
5912 SetDataPointer(png_data, Format, TempWidth, TempHeight); //be careful, Data could be freed by this method
5916 if Assigned(png_data) then
5926 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5927 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5928 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5933 Row, Col, PixSize, LineSize: Integer;
5934 NewImage, pSource, pDest, pAlpha: pByte;
5935 PngFormat: TglBitmapFormat;
5936 FormatDesc: TFormatDescriptor;
5939 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
5944 StreamPos := aStream.Position;
5945 aStream.Read(Header[0], SizeOf(Header));
5946 aStream.Position := StreamPos;
5948 {Test if the header matches}
5949 if Header = PngHeader then begin
5950 Png := TPNGObject.Create;
5952 Png.LoadFromStream(aStream);
5954 case Png.Header.ColorType of
5956 PngFormat := tfLuminance8;
5957 COLOR_GRAYSCALEALPHA:
5958 PngFormat := tfLuminance8Alpha8;
5960 PngFormat := tfBGR8;
5962 PngFormat := tfBGRA8;
5964 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5967 FormatDesc := TFormatDescriptor.Get(PngFormat);
5968 PixSize := Round(FormatDesc.PixelSize);
5969 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
5971 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5975 case Png.Header.ColorType of
5976 COLOR_RGB, COLOR_GRAYSCALE:
5978 for Row := 0 to Png.Height -1 do begin
5979 Move (Png.Scanline[Row]^, pDest^, LineSize);
5980 Inc(pDest, LineSize);
5983 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5985 PixSize := PixSize -1;
5987 for Row := 0 to Png.Height -1 do begin
5988 pSource := Png.Scanline[Row];
5989 pAlpha := pByte(Png.AlphaScanline[Row]);
5991 for Col := 0 to Png.Width -1 do begin
5992 Move (pSource^, pDest^, PixSize);
5993 Inc(pSource, PixSize);
5994 Inc(pDest, PixSize);
6003 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
6006 SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); //be careful, Data could be freed by this method
6010 if Assigned(NewImage) then
6022 {$IFDEF GLB_SUPPORT_PNG_WRITE}
6023 {$IFDEF GLB_LIB_PNG}
6024 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6025 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
6027 TStream(png_get_io_ptr(png)).Write(buffer^, size);
6031 {$IF DEFINED(GLB_LAZ_PNG)}
6032 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6033 procedure TglBitmap.SavePNG(const aStream: TStream);
6035 png: TPortableNetworkGraphic;
6036 intf: TLazIntfImage;
6039 png := TPortableNetworkGraphic.Create;
6040 intf := TLazIntfImage.Create(0, 0);
6042 if not AssignToLazIntfImage(intf) then
6043 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6044 intf.GetRawImage(raw);
6045 png.LoadFromRawImage(raw, false);
6046 png.SaveToStream(aStream);
6053 {$ELSEIF DEFINED(GLB_LIB_PNG)}
6054 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6055 procedure TglBitmap.SavePNG(const aStream: TStream);
6058 png_info: png_infop;
6059 png_rows: array of pByte;
6063 FormatDesc: TFormatDescriptor;
6065 if not (ftPNG in FormatGetSupportedFiles(Format)) then
6066 raise EglBitmapUnsupportedFormat.Create(Format);
6068 if not init_libPNG then
6069 raise Exception.Create('unable to initialize libPNG.');
6073 tfAlpha8, tfLuminance8:
6074 ColorType := PNG_COLOR_TYPE_GRAY;
6076 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
6078 ColorType := PNG_COLOR_TYPE_RGB;
6080 ColorType := PNG_COLOR_TYPE_RGBA;
6082 raise EglBitmapUnsupportedFormat.Create(Format);
6085 FormatDesc := TFormatDescriptor.Get(Format);
6086 LineSize := FormatDesc.GetSize(Width, 1);
6088 // creating array for scanline
6089 SetLength(png_rows, Height);
6091 for Row := 0 to Height - 1 do begin
6092 png_rows[Row] := Data;
6093 Inc(png_rows[Row], Row * LineSize)
6097 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
6099 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
6102 png_info := png_create_info_struct(png);
6103 if png_info = nil then begin
6104 png_destroy_write_struct(@png, nil);
6105 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
6108 // set read callback
6109 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
6112 png_set_compression_level(png, 6);
6114 if Format in [tfBGR8, tfBGRA8] then
6117 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
6118 png_write_info(png, png_info);
6119 png_write_image(png, @png_rows[0]);
6120 png_write_end(png, png_info);
6121 png_destroy_write_struct(@png, @png_info);
6123 SetLength(png_rows, 0);
6130 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
6131 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6132 procedure TglBitmap.SavePNG(const aStream: TStream);
6136 pSource, pDest: pByte;
6137 X, Y, PixSize: Integer;
6138 ColorType: Cardinal;
6144 if not (ftPNG in FormatGetSupportedFiles (Format)) then
6145 raise EglBitmapUnsupportedFormat.Create(Format);
6148 tfAlpha8, tfLuminance8: begin
6149 ColorType := COLOR_GRAYSCALE;
6153 tfLuminance8Alpha8: begin
6154 ColorType := COLOR_GRAYSCALEALPHA;
6158 tfBGR8, tfRGB8: begin
6159 ColorType := COLOR_RGB;
6163 tfBGRA8, tfRGBA8: begin
6164 ColorType := COLOR_RGBALPHA;
6169 raise EglBitmapUnsupportedFormat.Create(Format);
6172 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
6176 for Y := 0 to Height -1 do begin
6177 pDest := png.ScanLine[Y];
6178 for X := 0 to Width -1 do begin
6179 Move(pSource^, pDest^, PixSize);
6180 Inc(pDest, PixSize);
6181 Inc(pSource, PixSize);
6183 png.AlphaScanline[Y]^[X] := pSource^;
6188 // convert RGB line to BGR
6189 if Format in [tfRGB8, tfRGBA8] then begin
6190 pTemp := png.ScanLine[Y];
6191 for X := 0 to Width -1 do begin
6192 Temp := pByteArray(pTemp)^[0];
6193 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
6194 pByteArray(pTemp)^[2] := Temp;
6201 Png.CompressionLevel := 6;
6202 Png.SaveToStream(aStream);
6210 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6211 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6212 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6213 {$IFDEF GLB_LIB_JPEG}
6215 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
6216 glBitmap_libJPEG_source_mgr = record
6217 pub: jpeg_source_mgr;
6220 SrcBuffer: array [1..4096] of byte;
6223 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
6224 glBitmap_libJPEG_dest_mgr = record
6225 pub: jpeg_destination_mgr;
6227 DestStream: TStream;
6228 DestBuffer: array [1..4096] of byte;
6231 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
6237 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
6243 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
6248 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
6254 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
6260 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6261 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
6263 src: glBitmap_libJPEG_source_mgr_ptr;
6266 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6268 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
6269 if (bytes <= 0) then begin
6270 src^.SrcBuffer[1] := $FF;
6271 src^.SrcBuffer[2] := JPEG_EOI;
6275 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
6276 src^.pub.bytes_in_buffer := bytes;
6281 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6282 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
6284 src: glBitmap_libJPEG_source_mgr_ptr;
6286 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6288 if num_bytes > 0 then begin
6289 // wanted byte isn't in buffer so set stream position and read buffer
6290 if num_bytes > src^.pub.bytes_in_buffer then begin
6291 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
6292 src^.pub.fill_input_buffer(cinfo);
6294 // wanted byte is in buffer so only skip
6295 inc(src^.pub.next_input_byte, num_bytes);
6296 dec(src^.pub.bytes_in_buffer, num_bytes);
6301 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6302 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
6304 dest: glBitmap_libJPEG_dest_mgr_ptr;
6306 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6308 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
6309 // write complete buffer
6310 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
6313 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
6314 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
6320 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6321 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
6324 dest: glBitmap_libJPEG_dest_mgr_ptr;
6326 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6328 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6329 // check for endblock
6330 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6332 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6337 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6342 {$IFDEF GLB_SUPPORT_JPEG_READ}
6343 {$IF DEFINED(GLB_LAZ_JPEG)}
6344 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6345 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6348 JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
6351 intf: TLazIntfImage;
6352 reader: TFPReaderJPEG;
6354 magic: String[MAGIC_LEN];
6357 StreamPos := aStream.Position;
6359 SetLength(magic, MAGIC_LEN);
6360 aStream.Read(magic[1], MAGIC_LEN);
6361 aStream.Position := StreamPos;
6362 if (magic <> JPEG_MAGIC) then begin
6367 reader := TFPReaderJPEG.Create;
6368 intf := TLazIntfImage.Create(0, 0);
6370 intf.DataDescription := GetDescriptionFromDevice(0, 0, 0);
6371 reader.ImageRead(aStream, intf);
6372 AssignFromLazIntfImage(intf);
6375 aStream.Position := StreamPos;
6384 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
6385 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6386 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6388 Surface: PSDL_Surface;
6393 RWops := glBitmapCreateRWops(aStream);
6395 if IMG_isJPG(RWops) > 0 then begin
6396 Surface := IMG_LoadJPG_RW(RWops);
6398 AssignFromSurface(Surface);
6401 SDL_FreeSurface(Surface);
6409 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6410 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6411 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6414 Temp: array[0..1]of Byte;
6416 jpeg: jpeg_decompress_struct;
6417 jpeg_err: jpeg_error_mgr;
6419 IntFormat: TglBitmapFormat;
6421 TempHeight, TempWidth: Integer;
6426 FormatDesc: TFormatDescriptor;
6430 if not init_libJPEG then
6431 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6434 // reading first two bytes to test file and set cursor back to begin
6435 StreamPos := aStream.Position;
6436 aStream.Read({%H-}Temp[0], 2);
6437 aStream.Position := StreamPos;
6439 // if Bitmap then read file.
6440 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6441 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6442 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6445 jpeg.err := jpeg_std_error(@jpeg_err);
6446 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6447 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6449 // decompression struct
6450 jpeg_create_decompress(@jpeg);
6452 // allocation space for streaming methods
6453 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6455 // seeting up custom functions
6456 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6457 pub.init_source := glBitmap_libJPEG_init_source;
6458 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6459 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6460 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6461 pub.term_source := glBitmap_libJPEG_term_source;
6463 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6464 pub.next_input_byte := nil; // until buffer loaded
6466 SrcStream := aStream;
6469 // set global decoding state
6470 jpeg.global_state := DSTATE_START;
6472 // read header of jpeg
6473 jpeg_read_header(@jpeg, false);
6475 // setting output parameter
6476 case jpeg.jpeg_color_space of
6479 jpeg.out_color_space := JCS_GRAYSCALE;
6480 IntFormat := tfLuminance8;
6483 jpeg.out_color_space := JCS_RGB;
6484 IntFormat := tfRGB8;
6488 jpeg_start_decompress(@jpeg);
6490 TempHeight := jpeg.output_height;
6491 TempWidth := jpeg.output_width;
6493 FormatDesc := TFormatDescriptor.Get(IntFormat);
6495 // creating new image
6496 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6500 for Row := 0 to TempHeight -1 do begin
6501 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6502 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6505 // finish decompression
6506 jpeg_finish_decompress(@jpeg);
6508 // destroy decompression
6509 jpeg_destroy_decompress(@jpeg);
6511 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
6515 if Assigned(pImage) then
6525 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6526 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6527 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6532 Temp: array[0..1]of Byte;
6536 // reading first two bytes to test file and set cursor back to begin
6537 StreamPos := aStream.Position;
6538 aStream.Read(Temp[0], 2);
6539 aStream.Position := StreamPos;
6541 // if Bitmap then read file.
6542 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6543 bmp := TBitmap.Create;
6545 jpg := TJPEGImage.Create;
6547 jpg.LoadFromStream(aStream);
6549 result := AssignFromBitmap(bmp);
6561 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6562 {$IF DEFINED(GLB_LAZ_JPEG)}
6563 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6564 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6567 intf: TLazIntfImage;
6570 jpeg := TJPEGImage.Create;
6571 intf := TLazIntfImage.Create(0, 0);
6573 if not AssignToLazIntfImage(intf) then
6574 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6575 intf.GetRawImage(raw);
6576 jpeg.LoadFromRawImage(raw, false);
6577 jpeg.SaveToStream(aStream);
6584 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6585 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6586 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6588 jpeg: jpeg_compress_struct;
6589 jpeg_err: jpeg_error_mgr;
6591 pTemp, pTemp2: pByte;
6593 procedure CopyRow(pDest, pSource: pByte);
6597 for X := 0 to Width - 1 do begin
6598 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6599 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6600 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6607 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6608 raise EglBitmapUnsupportedFormat.Create(Format);
6610 if not init_libJPEG then
6611 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6614 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6615 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6618 jpeg.err := jpeg_std_error(@jpeg_err);
6619 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6620 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6622 // compression struct
6623 jpeg_create_compress(@jpeg);
6625 // allocation space for streaming methods
6626 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6628 // seeting up custom functions
6629 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6630 pub.init_destination := glBitmap_libJPEG_init_destination;
6631 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6632 pub.term_destination := glBitmap_libJPEG_term_destination;
6634 pub.next_output_byte := @DestBuffer[1];
6635 pub.free_in_buffer := Length(DestBuffer);
6637 DestStream := aStream;
6640 // very important state
6641 jpeg.global_state := CSTATE_START;
6642 jpeg.image_width := Width;
6643 jpeg.image_height := Height;
6645 tfAlpha8, tfLuminance8: begin
6646 jpeg.input_components := 1;
6647 jpeg.in_color_space := JCS_GRAYSCALE;
6649 tfRGB8, tfBGR8: begin
6650 jpeg.input_components := 3;
6651 jpeg.in_color_space := JCS_RGB;
6655 jpeg_set_defaults(@jpeg);
6656 jpeg_set_quality(@jpeg, 95, true);
6657 jpeg_start_compress(@jpeg, true);
6660 if Format = tfBGR8 then
6661 GetMem(pTemp2, fRowSize)
6666 for Row := 0 to jpeg.image_height -1 do begin
6668 if Format = tfBGR8 then
6669 CopyRow(pTemp2, pTemp)
6674 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6675 inc(pTemp, fRowSize);
6679 if Format = tfBGR8 then
6682 jpeg_finish_compress(@jpeg);
6683 jpeg_destroy_compress(@jpeg);
6689 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6690 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6691 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6696 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6697 raise EglBitmapUnsupportedFormat.Create(Format);
6699 Bmp := TBitmap.Create;
6701 Jpg := TJPEGImage.Create;
6703 AssignToBitmap(Bmp);
6704 if (Format in [tfAlpha8, tfLuminance8]) then begin
6705 Jpg.Grayscale := true;
6706 Jpg.PixelFormat := jf8Bit;
6709 Jpg.SaveToStream(aStream);
6720 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6721 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6722 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6729 BMP_COMP_BITFIELDS = 3;
6732 TBMPHeader = packed record
6737 bfOffBits: Cardinal;
6740 TBMPInfo = packed record
6746 biCompression: Cardinal;
6747 biSizeImage: Cardinal;
6748 biXPelsPerMeter: Longint;
6749 biYPelsPerMeter: Longint;
6750 biClrUsed: Cardinal;
6751 biClrImportant: Cardinal;
6754 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6755 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6757 //////////////////////////////////////////////////////////////////////////////////////////////////
6758 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6761 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6762 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6765 case aInfo.biCompression of
6767 BMP_COMP_RLE8: begin
6768 raise EglBitmap.Create('RLE compression is not supported');
6770 BMP_COMP_BITFIELDS: begin
6771 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6772 aStream.Read(aMask.r, SizeOf(aMask.r));
6773 aStream.Read(aMask.g, SizeOf(aMask.g));
6774 aStream.Read(aMask.b, SizeOf(aMask.b));
6775 aStream.Read(aMask.a, SizeOf(aMask.a));
6777 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
6781 //get suitable format
6782 case aInfo.biBitCount of
6783 8: result := tfLuminance8;
6784 16: result := tfBGR5;
6785 24: result := tfBGR8;
6786 32: result := tfBGRA8;
6790 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6793 ColorTable: TbmpColorTable;
6796 if (aInfo.biBitCount >= 16) then
6798 aFormat := tfLuminance8;
6799 c := aInfo.biClrUsed;
6801 c := 1 shl aInfo.biBitCount;
6802 SetLength(ColorTable, c);
6803 for i := 0 to c-1 do begin
6804 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6805 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6809 result := TbmpColorTableFormat.Create;
6810 result.PixelSize := aInfo.biBitCount / 8;
6811 result.ColorTable := ColorTable;
6812 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6815 //////////////////////////////////////////////////////////////////////////////////////////////////
6816 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6817 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6819 TmpFormat: TglBitmapFormat;
6820 FormatDesc: TFormatDescriptor;
6823 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6824 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6825 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6826 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6827 aFormat := FormatDesc.Format;
6832 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6833 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6834 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6835 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6837 result := TbmpBitfieldFormat.Create;
6838 result.PixelSize := aInfo.biBitCount / 8;
6839 result.RedMask := aMask.r;
6840 result.GreenMask := aMask.g;
6841 result.BlueMask := aMask.b;
6842 result.AlphaMask := aMask.a;
6849 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6850 PaddingBuff: Cardinal;
6851 LineBuf, ImageData, TmpData: PByte;
6852 SourceMD, DestMD: Pointer;
6853 BmpFormat: TglBitmapFormat;
6856 Mask: TglBitmapColorRec;
6861 SpecialFormat: TFormatDescriptor;
6862 FormatDesc: TFormatDescriptor;
6864 //////////////////////////////////////////////////////////////////////////////////////////////////
6865 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6868 Pixel: TglBitmapPixelData;
6870 aStream.Read(aLineBuf^, rbLineSize);
6871 SpecialFormat.PreparePixel(Pixel);
6872 for i := 0 to Info.biWidth-1 do begin
6873 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6874 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6875 FormatDesc.Map(Pixel, aData, DestMD);
6881 BmpFormat := tfEmpty;
6882 SpecialFormat := nil;
6888 StartPos := aStream.Position;
6889 aStream.Read(Header{%H-}, SizeOf(Header));
6891 if Header.bfType = BMP_MAGIC then begin
6893 BmpFormat := ReadInfo(Info, Mask);
6894 SpecialFormat := ReadColorTable(BmpFormat, Info);
6895 if not Assigned(SpecialFormat) then
6896 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6897 aStream.Position := StartPos + Header.bfOffBits;
6899 if (BmpFormat <> tfEmpty) then begin
6900 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6901 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6902 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6903 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6906 DestMD := FormatDesc.CreateMappingData;
6907 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6908 GetMem(ImageData, ImageSize);
6909 if Assigned(SpecialFormat) then begin
6910 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6911 SourceMD := SpecialFormat.CreateMappingData;
6916 FillChar(ImageData^, ImageSize, $FF);
6917 TmpData := ImageData;
6918 if (Info.biHeight > 0) then
6919 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6920 for i := 0 to Abs(Info.biHeight)-1 do begin
6921 if Assigned(SpecialFormat) then
6922 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6924 aStream.Read(TmpData^, wbLineSize); //else only read data
6925 if (Info.biHeight > 0) then
6926 dec(TmpData, wbLineSize)
6928 inc(TmpData, wbLineSize);
6929 aStream.Read(PaddingBuff{%H-}, Padding);
6931 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method
6934 if Assigned(LineBuf) then
6936 if Assigned(SourceMD) then
6937 SpecialFormat.FreeMappingData(SourceMD);
6938 FormatDesc.FreeMappingData(DestMD);
6941 if Assigned(ImageData) then
6946 raise EglBitmap.Create('LoadBMP - No suitable format found');
6948 aStream.Position := StartPos;
6952 FreeAndNil(SpecialFormat);
6955 else aStream.Position := StartPos;
6958 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6959 procedure TglBitmap.SaveBMP(const aStream: TStream);
6963 Converter: TFormatDescriptor;
6964 FormatDesc: TFormatDescriptor;
6965 SourceFD, DestFD: Pointer;
6966 pData, srcData, dstData, ConvertBuffer: pByte;
6968 Pixel: TglBitmapPixelData;
6969 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6970 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6972 PaddingBuff: Cardinal;
6974 function GetLineWidth : Integer;
6976 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6980 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6981 raise EglBitmapUnsupportedFormat.Create(Format);
6984 FormatDesc := TFormatDescriptor.Get(Format);
6985 ImageSize := FormatDesc.GetSize(Dimension);
6987 FillChar(Header{%H-}, SizeOf(Header), 0);
6988 Header.bfType := BMP_MAGIC;
6989 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6990 Header.bfReserved1 := 0;
6991 Header.bfReserved2 := 0;
6992 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6994 FillChar(Info{%H-}, SizeOf(Info), 0);
6995 Info.biSize := SizeOf(Info);
6996 Info.biWidth := Width;
6997 Info.biHeight := Height;
6999 Info.biCompression := BMP_COMP_RGB;
7000 Info.biSizeImage := ImageSize;
7005 Info.biBitCount := 4;
7006 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
7007 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
7008 Converter := TbmpColorTableFormat.Create;
7009 with (Converter as TbmpColorTableFormat) do begin
7012 Range := glBitmapColorRec($F, $F, $F, $0);
7017 tfR3G3B2, tfLuminance8: begin
7018 Info.biBitCount := 8;
7019 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
7020 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
7021 Converter := TbmpColorTableFormat.Create;
7022 with (Converter as TbmpColorTableFormat) do begin
7025 if (Format = tfR3G3B2) then begin
7026 Range := glBitmapColorRec($7, $7, $3, $0);
7027 Shift := glBitmapShiftRec(0, 3, 6, 0);
7029 Range := glBitmapColorRec($FF, $FF, $FF, $0);
7034 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
7035 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
7036 Info.biBitCount := 16;
7037 Info.biCompression := BMP_COMP_BITFIELDS;
7040 tfBGR8, tfRGB8: begin
7041 Info.biBitCount := 24;
7042 if (Format = tfRGB8) then
7043 Converter := TfdBGR8.Create; //use BGR8 Format Descriptor to Swap RGB Values
7046 tfRGB10, tfRGB10A2, tfRGBA8,
7047 tfBGR10, tfBGR10A2, tfBGRA8: begin
7048 Info.biBitCount := 32;
7049 Info.biCompression := BMP_COMP_BITFIELDS;
7052 raise EglBitmapUnsupportedFormat.Create(Format);
7054 Info.biXPelsPerMeter := 2835;
7055 Info.biYPelsPerMeter := 2835;
7058 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7059 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
7060 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
7062 RedMask := FormatDesc.RedMask;
7063 GreenMask := FormatDesc.GreenMask;
7064 BlueMask := FormatDesc.BlueMask;
7065 AlphaMask := FormatDesc.AlphaMask;
7069 aStream.Write(Header, SizeOf(Header));
7070 aStream.Write(Info, SizeOf(Info));
7073 if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
7074 with (Converter as TbmpColorTableFormat) do
7075 aStream.Write(ColorTable[0].b,
7076 SizeOf(TbmpColorTableEnty) * Length(ColorTable));
7079 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7080 aStream.Write(RedMask, SizeOf(Cardinal));
7081 aStream.Write(GreenMask, SizeOf(Cardinal));
7082 aStream.Write(BlueMask, SizeOf(Cardinal));
7083 aStream.Write(AlphaMask, SizeOf(Cardinal));
7087 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
7088 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
7089 Padding := GetLineWidth - wbLineSize;
7093 inc(pData, (Height-1) * rbLineSize);
7095 // prepare row buffer. But only for RGB because RGBA supports color masks
7096 // so it's possible to change color within the image.
7097 if Assigned(Converter) then begin
7098 FormatDesc.PreparePixel(Pixel);
7099 GetMem(ConvertBuffer, wbLineSize);
7100 SourceFD := FormatDesc.CreateMappingData;
7101 DestFD := Converter.CreateMappingData;
7103 ConvertBuffer := nil;
7106 for LineIdx := 0 to Height - 1 do begin
7108 if Assigned(Converter) then begin
7110 dstData := ConvertBuffer;
7111 for PixelIdx := 0 to Info.biWidth-1 do begin
7112 FormatDesc.Unmap(srcData, Pixel, SourceFD);
7113 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
7114 Converter.Map(Pixel, dstData, DestFD);
7116 aStream.Write(ConvertBuffer^, wbLineSize);
7118 aStream.Write(pData^, rbLineSize);
7120 dec(pData, rbLineSize);
7121 if (Padding > 0) then
7122 aStream.Write(PaddingBuff, Padding);
7125 // destroy row buffer
7126 if Assigned(ConvertBuffer) then begin
7127 FormatDesc.FreeMappingData(SourceFD);
7128 Converter.FreeMappingData(DestFD);
7129 FreeMem(ConvertBuffer);
7133 if Assigned(Converter) then
7138 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7139 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7140 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7142 TTGAHeader = packed record
7146 //ColorMapSpec: Array[0..4] of Byte;
7147 ColorMapStart: Word;
7148 ColorMapLength: Word;
7149 ColorMapEntrySize: Byte;
7159 TGA_UNCOMPRESSED_RGB = 2;
7160 TGA_UNCOMPRESSED_GRAY = 3;
7161 TGA_COMPRESSED_RGB = 10;
7162 TGA_COMPRESSED_GRAY = 11;
7164 TGA_NONE_COLOR_TABLE = 0;
7166 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7167 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
7170 ImageData: System.PByte;
7171 StartPosition: Int64;
7172 PixelSize, LineSize: Integer;
7173 tgaFormat: TglBitmapFormat;
7174 FormatDesc: TFormatDescriptor;
7175 Counter: packed record
7177 low, high, dir: Integer;
7184 ////////////////////////////////////////////////////////////////////////////////////////
7185 procedure ReadUncompressed;
7188 buf, tmp1, tmp2: System.PByte;
7191 if (Counter.X.dir < 0) then
7192 GetMem(buf, LineSize);
7194 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
7196 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
7197 if (Counter.X.dir < 0) then begin //flip X
7198 aStream.Read(buf^, LineSize);
7200 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
7201 for i := 0 to Header.Width-1 do begin //for all pixels in line
7202 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
7207 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
7210 aStream.Read(tmp1^, LineSize);
7211 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
7214 if Assigned(buf) then
7219 ////////////////////////////////////////////////////////////////////////////////////////
7220 procedure ReadCompressed;
7222 /////////////////////////////////////////////////////////////////
7224 TmpData: System.PByte;
7225 LinePixelsRead: Integer;
7226 procedure CheckLine;
7228 if (LinePixelsRead >= Header.Width) then begin
7229 LinePixelsRead := 0;
7230 inc(Counter.Y.low, Counter.Y.dir); //next line index
7231 TmpData := ImageData;
7232 inc(TmpData, Counter.Y.low * LineSize); //set line
7233 if (Counter.X.dir < 0) then //if x flipped then
7234 inc(TmpData, LineSize - PixelSize); //set last pixel
7238 /////////////////////////////////////////////////////////////////
7241 CacheSize, CachePos: Integer;
7242 procedure CachedRead(out Buffer; Count: Integer);
7246 if (CachePos + Count > CacheSize) then begin
7247 //if buffer overflow save non read bytes
7249 if (CacheSize - CachePos > 0) then begin
7250 BytesRead := CacheSize - CachePos;
7251 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
7252 inc(CachePos, BytesRead);
7255 //load cache from file
7256 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
7257 aStream.Read(Cache^, CacheSize);
7260 //read rest of requested bytes
7261 if (Count - BytesRead > 0) then begin
7262 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
7263 inc(CachePos, Count - BytesRead);
7266 //if no buffer overflow just read the data
7267 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
7268 inc(CachePos, Count);
7272 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
7277 inc(aBuffer, Counter.X.dir);
7280 PWord(aBuffer)^ := PWord(aData)^;
7281 inc(aBuffer, 2 * Counter.X.dir);
7284 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
7285 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
7286 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
7287 inc(aBuffer, 3 * Counter.X.dir);
7290 PCardinal(aBuffer)^ := PCardinal(aData)^;
7291 inc(aBuffer, 4 * Counter.X.dir);
7297 TotalPixelsToRead, TotalPixelsRead: Integer;
7299 buf: array [0..3] of Byte; //1 pixel is max 32bit long
7300 PixelRepeat: Boolean;
7301 PixelsToRead, PixelCount: Integer;
7306 TotalPixelsToRead := Header.Width * Header.Height;
7307 TotalPixelsRead := 0;
7308 LinePixelsRead := 0;
7310 GetMem(Cache, CACHE_SIZE);
7312 TmpData := ImageData;
7313 inc(TmpData, Counter.Y.low * LineSize); //set line
7314 if (Counter.X.dir < 0) then //if x flipped then
7315 inc(TmpData, LineSize - PixelSize); //set last pixel
7319 CachedRead(Temp, 1);
7320 PixelRepeat := (Temp and $80) > 0;
7321 PixelsToRead := (Temp and $7F) + 1;
7322 inc(TotalPixelsRead, PixelsToRead);
7325 CachedRead(buf[0], PixelSize);
7326 while (PixelsToRead > 0) do begin
7328 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
7329 while (PixelCount > 0) do begin
7330 if not PixelRepeat then
7331 CachedRead(buf[0], PixelSize);
7332 PixelToBuffer(@buf[0], TmpData);
7333 inc(LinePixelsRead);
7338 until (TotalPixelsRead >= TotalPixelsToRead);
7344 function IsGrayFormat: Boolean;
7346 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
7352 // reading header to test file and set cursor back to begin
7353 StartPosition := aStream.Position;
7354 aStream.Read(Header{%H-}, SizeOf(Header));
7356 // no colormapped files
7357 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
7358 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
7361 if Header.ImageID <> 0 then // skip image ID
7362 aStream.Position := aStream.Position + Header.ImageID;
7364 tgaFormat := tfEmpty;
7366 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
7367 0: tgaFormat := tfLuminance8;
7368 8: tgaFormat := tfAlpha8;
7371 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
7372 0: tgaFormat := tfLuminance16;
7373 8: tgaFormat := tfLuminance8Alpha8;
7374 end else case (Header.ImageDesc and $F) of
7375 0: tgaFormat := tfBGR5;
7376 1: tgaFormat := tfBGR5A1;
7377 4: tgaFormat := tfBGRA4;
7380 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7381 0: tgaFormat := tfBGR8;
7384 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7385 2: tgaFormat := tfBGR10A2;
7386 8: tgaFormat := tfBGRA8;
7390 if (tgaFormat = tfEmpty) then
7391 raise EglBitmap.Create('LoadTga - unsupported format');
7393 FormatDesc := TFormatDescriptor.Get(tgaFormat);
7394 PixelSize := FormatDesc.GetSize(1, 1);
7395 LineSize := FormatDesc.GetSize(Header.Width, 1);
7397 GetMem(ImageData, LineSize * Header.Height);
7400 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7401 Counter.X.low := Header.Height-1;;
7402 Counter.X.high := 0;
7403 Counter.X.dir := -1;
7406 Counter.X.high := Header.Height-1;
7411 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7413 Counter.Y.high := Header.Height-1;
7416 Counter.Y.low := Header.Height-1;;
7417 Counter.Y.high := 0;
7418 Counter.Y.dir := -1;
7422 case Header.ImageType of
7423 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7425 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7429 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method
7432 if Assigned(ImageData) then
7437 aStream.Position := StartPosition;
7440 else aStream.Position := StartPosition;
7443 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7444 procedure TglBitmap.SaveTGA(const aStream: TStream);
7447 LineSize, Size, x, y: Integer;
7448 Pixel: TglBitmapPixelData;
7449 LineBuf, SourceData, DestData: PByte;
7450 SourceMD, DestMD: Pointer;
7451 FormatDesc: TFormatDescriptor;
7452 Converter: TFormatDescriptor;
7454 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7455 raise EglBitmapUnsupportedFormat.Create(Format);
7458 FillChar(Header{%H-}, SizeOf(Header), 0);
7461 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7462 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7463 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7465 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7468 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7470 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7471 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7473 else if (Format in [tfBGR8, tfRGB8]) then
7481 Header.ImageDesc := 1 and $F;
7482 tfRGB10A2, tfBGR10A2:
7483 Header.ImageDesc := 2 and $F;
7485 Header.ImageDesc := 4 and $F;
7486 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7487 Header.ImageDesc := 8 and $F;
7490 Header.Width := Width;
7491 Header.Height := Height;
7492 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7493 aStream.Write(Header, SizeOf(Header));
7495 // convert RGB(A) to BGR(A)
7497 FormatDesc := TFormatDescriptor.Get(Format);
7498 Size := FormatDesc.GetSize(Dimension);
7499 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7500 if (FormatDesc.RGBInverted = tfEmpty) then
7501 raise EglBitmap.Create('inverted RGB format is empty');
7502 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7503 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7504 (Converter.PixelSize <> FormatDesc.PixelSize) then
7505 raise EglBitmap.Create('invalid inverted RGB format');
7508 if Assigned(Converter) then begin
7509 LineSize := FormatDesc.GetSize(Width, 1);
7510 GetMem(LineBuf, LineSize);
7511 SourceMD := FormatDesc.CreateMappingData;
7512 DestMD := Converter.CreateMappingData;
7515 for y := 0 to Height-1 do begin
7516 DestData := LineBuf;
7517 for x := 0 to Width-1 do begin
7518 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7519 Converter.Map(Pixel, DestData, DestMD);
7521 aStream.Write(LineBuf^, LineSize);
7525 FormatDesc.FreeMappingData(SourceMD);
7526 FormatDesc.FreeMappingData(DestMD);
7529 aStream.Write(Data^, Size);
7532 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7533 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7534 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7536 DDS_MAGIC: Cardinal = $20534444;
7538 // DDS_header.dwFlags
7539 DDSD_CAPS = $00000001;
7540 DDSD_HEIGHT = $00000002;
7541 DDSD_WIDTH = $00000004;
7542 DDSD_PIXELFORMAT = $00001000;
7544 // DDS_header.sPixelFormat.dwFlags
7545 DDPF_ALPHAPIXELS = $00000001;
7546 DDPF_ALPHA = $00000002;
7547 DDPF_FOURCC = $00000004;
7548 DDPF_RGB = $00000040;
7549 DDPF_LUMINANCE = $00020000;
7551 // DDS_header.sCaps.dwCaps1
7552 DDSCAPS_TEXTURE = $00001000;
7554 // DDS_header.sCaps.dwCaps2
7555 DDSCAPS2_CUBEMAP = $00000200;
7557 D3DFMT_DXT1 = $31545844;
7558 D3DFMT_DXT3 = $33545844;
7559 D3DFMT_DXT5 = $35545844;
7562 TDDSPixelFormat = packed record
7566 dwRGBBitCount: Cardinal;
7567 dwRBitMask: Cardinal;
7568 dwGBitMask: Cardinal;
7569 dwBBitMask: Cardinal;
7570 dwABitMask: Cardinal;
7573 TDDSCaps = packed record
7577 dwReserved: Cardinal;
7580 TDDSHeader = packed record
7585 dwPitchOrLinearSize: Cardinal;
7587 dwMipMapCount: Cardinal;
7588 dwReserved: array[0..10] of Cardinal;
7589 PixelFormat: TDDSPixelFormat;
7591 dwReserved2: Cardinal;
7594 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7595 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7598 Converter: TbmpBitfieldFormat;
7600 function GetDDSFormat: TglBitmapFormat;
7602 fd: TFormatDescriptor;
7604 Range: TglBitmapColorRec;
7608 with Header.PixelFormat do begin
7610 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7611 case Header.PixelFormat.dwFourCC of
7612 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7613 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7614 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7616 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7618 //find matching format
7619 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7620 fd := TFormatDescriptor.Get(result);
7621 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7622 (8 * fd.PixelSize = dwRGBBitCount) then
7626 //find format with same Range
7627 Range.r := dwRBitMask;
7628 Range.g := dwGBitMask;
7629 Range.b := dwBBitMask;
7630 Range.a := dwABitMask;
7631 for i := 0 to 3 do begin
7632 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7633 Range.arr[i] := Range.arr[i] shr 1;
7635 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7636 fd := TFormatDescriptor.Get(result);
7639 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7647 //no format with same range found -> use default
7648 if (result = tfEmpty) then begin
7649 if (dwABitMask > 0) then
7655 Converter := TbmpBitfieldFormat.Create;
7656 Converter.RedMask := dwRBitMask;
7657 Converter.GreenMask := dwGBitMask;
7658 Converter.BlueMask := dwBBitMask;
7659 Converter.AlphaMask := dwABitMask;
7660 Converter.PixelSize := dwRGBBitCount / 8;
7667 x, y, LineSize, RowSize, Magic: Cardinal;
7668 NewImage, TmpData, RowData, SrcData: System.PByte;
7669 SourceMD, DestMD: Pointer;
7670 Pixel: TglBitmapPixelData;
7671 ddsFormat: TglBitmapFormat;
7672 FormatDesc: TFormatDescriptor;
7677 StreamPos := aStream.Position;
7680 aStream.Read(Magic{%H-}, sizeof(Magic));
7681 if (Magic <> DDS_MAGIC) then begin
7682 aStream.Position := StreamPos;
7687 aStream.Read(Header{%H-}, sizeof(Header));
7688 if (Header.dwSize <> SizeOf(Header)) or
7689 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7690 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7692 aStream.Position := StreamPos;
7696 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7697 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
7699 ddsFormat := GetDDSFormat;
7701 if (ddsFormat = tfEmpty) then
7702 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7704 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7705 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7706 GetMem(NewImage, Header.dwHeight * LineSize);
7708 TmpData := NewImage;
7711 if Assigned(Converter) then begin
7712 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7713 GetMem(RowData, RowSize);
7714 SourceMD := Converter.CreateMappingData;
7715 DestMD := FormatDesc.CreateMappingData;
7717 for y := 0 to Header.dwHeight-1 do begin
7718 TmpData := NewImage;
7719 inc(TmpData, y * LineSize);
7721 aStream.Read(SrcData^, RowSize);
7722 for x := 0 to Header.dwWidth-1 do begin
7723 Converter.Unmap(SrcData, Pixel, SourceMD);
7724 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7725 FormatDesc.Map(Pixel, TmpData, DestMD);
7729 Converter.FreeMappingData(SourceMD);
7730 FormatDesc.FreeMappingData(DestMD);
7736 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7737 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7738 for Y := 0 to Header.dwHeight-1 do begin
7739 aStream.Read(TmpData^, RowSize);
7740 Inc(TmpData, LineSize);
7745 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7746 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7747 for Y := 0 to Header.dwHeight-1 do begin
7748 aStream.Read(TmpData^, RowSize);
7749 Inc(TmpData, LineSize);
7752 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7754 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method
7757 if Assigned(NewImage) then
7762 FreeAndNil(Converter);
7766 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7767 procedure TglBitmap.SaveDDS(const aStream: TStream);
7770 FormatDesc: TFormatDescriptor;
7772 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7773 raise EglBitmapUnsupportedFormat.Create(Format);
7775 FormatDesc := TFormatDescriptor.Get(Format);
7778 FillChar(Header{%H-}, SizeOf(Header), 0);
7779 Header.dwSize := SizeOf(Header);
7780 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7782 Header.dwWidth := Max(1, Width);
7783 Header.dwHeight := Max(1, Height);
7786 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7789 Header.PixelFormat.dwSize := sizeof(Header);
7790 if (FormatDesc.IsCompressed) then begin
7791 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7793 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7794 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7795 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7797 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7798 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7799 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7800 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7801 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7802 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7803 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7804 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7805 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7807 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7808 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7809 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7810 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7811 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7812 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7815 if (FormatDesc.HasAlpha) then
7816 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7818 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7819 aStream.Write(Header, SizeOf(Header));
7820 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7823 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7824 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7825 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7826 procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7827 const aWidth: Integer; const aHeight: Integer);
7832 if (aHeight > 1) then begin
7833 Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1);
7834 GetMem(pTemp, Size);
7836 Move(aData^, pTemp^, Size);
7845 inherited SetDataPointer(pTemp, aFormat, aWidth);
7848 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7849 function TglBitmap1D.FlipHorz: Boolean;
7852 pTempDest, pDest, pSource: PByte;
7854 result := inherited FlipHorz;
7855 if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin
7857 GetMem(pDest, fRowSize);
7860 Inc(pTempDest, fRowSize);
7861 for Col := 0 to Width-1 do begin
7862 dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data
7863 Move(pSource^, pTempDest^, fPixelSize);
7864 Inc(pSource, fPixelSize);
7866 SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method
7869 if Assigned(pDest) then
7876 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7877 procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean);
7879 FormatDesc: TFormatDescriptor;
7882 FormatDesc := TFormatDescriptor.Get(Format);
7883 if FormatDesc.IsCompressed then begin
7884 if not Assigned(glCompressedTexImage1D) then
7885 raise EglBitmap.Create('compressed formats not supported by video adapter');
7886 glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
7887 end else if aBuildWithGlu then
7888 gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7890 glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7893 if (FreeDataAfterGenTexture) then
7897 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7898 procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean);
7900 BuildWithGlu, TexRec: Boolean;
7903 if Assigned(Data) then begin
7904 // Check Texture Size
7905 if (aTestTextureSize) then begin
7906 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7908 if (Width > TexSize) then
7909 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7911 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7912 (Target = GL_TEXTURE_RECTANGLE);
7913 if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7914 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7918 SetupParameters(BuildWithGlu);
7919 UploadData(BuildWithGlu);
7920 glAreTexturesResident(1, @fID, @fIsResident);
7924 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7925 procedure TglBitmap1D.AfterConstruction;
7928 Target := GL_TEXTURE_1D;
7931 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7932 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7933 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7934 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7936 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7937 result := fLines[aIndex]
7942 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7943 procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7944 const aWidth: Integer; const aHeight: Integer);
7946 Idx, LineWidth: Integer;
7948 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7950 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7952 if Assigned(Data) then begin
7953 SetLength(fLines, GetHeight);
7954 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7956 for Idx := 0 to GetHeight-1 do begin
7957 fLines[Idx] := Data;
7958 Inc(fLines[Idx], Idx * LineWidth);
7961 else SetLength(fLines, 0);
7963 SetLength(fLines, 0);
7967 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7968 procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
7970 FormatDesc: TFormatDescriptor;
7972 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7974 FormatDesc := TFormatDescriptor.Get(Format);
7975 if FormatDesc.IsCompressed then begin
7976 if not Assigned(glCompressedTexImage2D) then
7977 raise EglBitmap.Create('compressed formats not supported by video adapter');
7978 glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7979 end else if aBuildWithGlu then begin
7980 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7981 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7983 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7984 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7988 if (FreeDataAfterGenTexture) then
7992 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7993 procedure TglBitmap2D.AfterConstruction;
7996 Target := GL_TEXTURE_2D;
7999 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8000 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
8003 Size, w, h: Integer;
8004 FormatDesc: TFormatDescriptor;
8006 FormatDesc := TFormatDescriptor.Get(aFormat);
8007 if FormatDesc.IsCompressed then
8008 raise EglBitmapUnsupportedFormat.Create(aFormat);
8010 w := aRight - aLeft;
8011 h := aBottom - aTop;
8012 Size := FormatDesc.GetSize(w, h);
8015 glPixelStorei(GL_PACK_ALIGNMENT, 1);
8016 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8017 SetDataPointer(Temp, aFormat, w, h); //be careful, Data could be freed by this method
8020 if Assigned(Temp) then
8026 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8027 procedure TglBitmap2D.GetDataFromTexture;
8030 TempWidth, TempHeight: Integer;
8031 TempIntFormat: Cardinal;
8032 IntFormat, f: TglBitmapFormat;
8033 FormatDesc: TFormatDescriptor;
8038 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
8039 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
8040 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
8042 IntFormat := tfEmpty;
8043 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
8044 FormatDesc := TFormatDescriptor.Get(f);
8045 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
8046 IntFormat := FormatDesc.Format;
8051 // Getting data from OpenGL
8052 FormatDesc := TFormatDescriptor.Get(IntFormat);
8053 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
8055 if FormatDesc.IsCompressed then begin
8056 if not Assigned(glGetCompressedTexImage) then
8057 raise EglBitmap.Create('compressed formats not supported by video adapter');
8058 glGetCompressedTexImage(Target, 0, Temp)
8060 glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8061 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
8063 if Assigned(Temp) then
8069 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8070 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
8072 BuildWithGlu, PotTex, TexRec: Boolean;
8075 if Assigned(Data) then begin
8076 // Check Texture Size
8077 if (aTestTextureSize) then begin
8078 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8080 if ((Height > TexSize) or (Width > TexSize)) then
8081 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8083 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
8084 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
8085 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8086 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8090 SetupParameters(BuildWithGlu);
8091 UploadData(Target, BuildWithGlu);
8092 glAreTexturesResident(1, @fID, @fIsResident);
8096 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8097 function TglBitmap2D.FlipHorz: Boolean;
8100 TempDestData, DestData, SourceData: PByte;
8103 result := inherited FlipHorz;
8104 if Assigned(Data) then begin
8106 ImgSize := Height * fRowSize;
8107 GetMem(DestData, ImgSize);
8109 TempDestData := DestData;
8110 Dec(TempDestData, fRowSize + fPixelSize);
8111 for Row := 0 to Height -1 do begin
8112 Inc(TempDestData, fRowSize * 2);
8113 for Col := 0 to Width -1 do begin
8114 Move(SourceData^, TempDestData^, fPixelSize);
8115 Inc(SourceData, fPixelSize);
8116 Dec(TempDestData, fPixelSize);
8119 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8122 if Assigned(DestData) then
8129 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8130 function TglBitmap2D.FlipVert: Boolean;
8133 TempDestData, DestData, SourceData: PByte;
8135 result := inherited FlipVert;
8136 if Assigned(Data) then begin
8138 GetMem(DestData, Height * fRowSize);
8140 TempDestData := DestData;
8141 Inc(TempDestData, Width * (Height -1) * fPixelSize);
8142 for Row := 0 to Height -1 do begin
8143 Move(SourceData^, TempDestData^, fRowSize);
8144 Dec(TempDestData, fRowSize);
8145 Inc(SourceData, fRowSize);
8147 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8150 if Assigned(DestData) then
8157 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8158 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8159 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8161 TMatrixItem = record
8166 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
8167 TglBitmapToNormalMapRec = Record
8169 Heights: array of Single;
8170 MatrixU : array of TMatrixItem;
8171 MatrixV : array of TMatrixItem;
8175 ONE_OVER_255 = 1 / 255;
8177 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8178 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
8182 with FuncRec do begin
8184 Source.Data.r * LUMINANCE_WEIGHT_R +
8185 Source.Data.g * LUMINANCE_WEIGHT_G +
8186 Source.Data.b * LUMINANCE_WEIGHT_B;
8187 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
8191 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8192 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
8195 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
8198 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8199 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
8201 TVec = Array[0..2] of Single;
8208 function GetHeight(X, Y: Integer): Single;
8210 with FuncRec do begin
8211 X := Max(0, Min(Size.X -1, X));
8212 Y := Max(0, Min(Size.Y -1, Y));
8213 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
8218 with FuncRec do begin
8219 with PglBitmapToNormalMapRec(Args)^ do begin
8221 for Idx := Low(MatrixU) to High(MatrixU) do
8222 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
8225 for Idx := Low(MatrixU) to High(MatrixU) do
8226 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
8228 Vec[0] := -du * Scale;
8229 Vec[1] := -dv * Scale;
8234 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8235 if Len <> 0 then begin
8236 Vec[0] := Vec[0] * Len;
8237 Vec[1] := Vec[1] * Len;
8238 Vec[2] := Vec[2] * Len;
8242 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
8243 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
8244 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
8248 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8249 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
8251 Rec: TglBitmapToNormalMapRec;
8253 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
8255 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
8256 Matrix[Index].X := X;
8257 Matrix[Index].Y := Y;
8258 Matrix[Index].W := W;
8263 if TFormatDescriptor.Get(Format).IsCompressed then
8264 raise EglBitmapUnsupportedFormat.Create(Format);
8266 if aScale > 100 then
8268 else if aScale < -100 then
8271 Rec.Scale := aScale;
8273 SetLength(Rec.Heights, Width * Height);
8277 SetLength(Rec.MatrixU, 2);
8278 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
8279 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
8281 SetLength(Rec.MatrixV, 2);
8282 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
8283 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
8287 SetLength(Rec.MatrixU, 6);
8288 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
8289 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
8290 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
8291 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
8292 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
8293 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
8295 SetLength(Rec.MatrixV, 6);
8296 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
8297 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
8298 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
8299 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
8300 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
8301 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
8305 SetLength(Rec.MatrixU, 6);
8306 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
8307 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
8308 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
8309 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
8310 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
8311 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
8313 SetLength(Rec.MatrixV, 6);
8314 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
8315 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
8316 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
8317 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
8318 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
8319 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
8323 SetLength(Rec.MatrixU, 20);
8324 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
8325 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
8326 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
8327 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
8328 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
8329 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
8330 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
8331 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
8332 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
8333 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
8334 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
8335 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
8336 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
8337 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
8338 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
8339 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
8340 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
8341 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
8342 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
8343 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
8345 SetLength(Rec.MatrixV, 20);
8346 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
8347 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
8348 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
8349 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
8350 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
8351 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
8352 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
8353 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
8354 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
8355 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
8356 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
8357 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
8358 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
8359 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
8360 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
8361 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
8362 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
8363 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
8364 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
8365 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
8370 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
8371 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
8373 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
8374 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
8376 SetLength(Rec.Heights, 0);
8380 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8381 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8382 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8383 procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean);
8385 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8388 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8389 procedure TglBitmapCubeMap.AfterConstruction;
8393 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8394 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8397 Target := GL_TEXTURE_CUBE_MAP;
8398 fGenMode := GL_REFLECTION_MAP;
8401 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8402 procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean);
8404 BuildWithGlu: Boolean;
8407 if (aTestTextureSize) then begin
8408 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8410 if (Height > TexSize) or (Width > TexSize) then
8411 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8413 if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8414 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8419 SetupParameters(BuildWithGlu);
8420 UploadData(aCubeTarget, BuildWithGlu);
8423 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8424 procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean);
8426 inherited Bind (aEnableTextureUnit);
8427 if aEnableTexCoordsGen then begin
8428 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8429 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8430 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8431 glEnable(GL_TEXTURE_GEN_S);
8432 glEnable(GL_TEXTURE_GEN_T);
8433 glEnable(GL_TEXTURE_GEN_R);
8437 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8438 procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean);
8440 inherited Unbind(aDisableTextureUnit);
8441 if aDisableTexCoordsGen then begin
8442 glDisable(GL_TEXTURE_GEN_S);
8443 glDisable(GL_TEXTURE_GEN_T);
8444 glDisable(GL_TEXTURE_GEN_R);
8448 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8449 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8450 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8452 TVec = Array[0..2] of Single;
8453 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8455 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8456 TglBitmapNormalMapRec = record
8458 Func: TglBitmapNormalMapGetVectorFunc;
8461 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8462 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8464 aVec[0] := aHalfSize;
8465 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8466 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8469 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8470 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8472 aVec[0] := - aHalfSize;
8473 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8474 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8477 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8478 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8480 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8481 aVec[1] := aHalfSize;
8482 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8485 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8486 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8488 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8489 aVec[1] := - aHalfSize;
8490 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8493 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8494 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8496 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8497 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8498 aVec[2] := aHalfSize;
8501 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8502 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8504 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8505 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8506 aVec[2] := - aHalfSize;
8509 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8510 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8516 with FuncRec do begin
8517 with PglBitmapNormalMapRec(Args)^ do begin
8518 Func(Vec, Position, HalfSize);
8521 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8522 if Len <> 0 then begin
8523 Vec[0] := Vec[0] * Len;
8524 Vec[1] := Vec[1] * Len;
8525 Vec[2] := Vec[2] * Len;
8528 // Scale Vector and AddVectro
8529 Vec[0] := Vec[0] * 0.5 + 0.5;
8530 Vec[1] := Vec[1] * 0.5 + 0.5;
8531 Vec[2] := Vec[2] * 0.5 + 0.5;
8536 Dest.Data.arr[i] := Round(Vec[i] * 255);
8540 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8541 procedure TglBitmapNormalMap.AfterConstruction;
8544 fGenMode := GL_NORMAL_MAP;
8547 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8548 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean);
8550 Rec: TglBitmapNormalMapRec;
8551 SizeRec: TglBitmapPixelPosition;
8553 Rec.HalfSize := aSize div 2;
8554 FreeDataAfterGenTexture := false;
8556 SizeRec.Fields := [ffX, ffY];
8561 Rec.Func := glBitmapNormalMapPosX;
8562 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8563 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize);
8566 Rec.Func := glBitmapNormalMapNegX;
8567 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8568 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize);
8571 Rec.Func := glBitmapNormalMapPosY;
8572 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8573 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize);
8576 Rec.Func := glBitmapNormalMapNegY;
8577 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8578 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize);
8581 Rec.Func := glBitmapNormalMapPosZ;
8582 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8583 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize);
8586 Rec.Func := glBitmapNormalMapNegZ;
8587 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8588 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize);
8593 glBitmapSetDefaultFormat (tfEmpty);
8594 glBitmapSetDefaultMipmap (mmMipmap);
8595 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8596 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8597 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8599 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8600 glBitmapSetDefaultDeleteTextureOnFree (true);
8602 TFormatDescriptor.Init;
8604 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8605 OpenGLInitialized := false;
8606 InitOpenGLCS := TCriticalSection.Create;
8610 TFormatDescriptor.Finalize;
8612 {$IFDEF GLB_NATIVE_OGL}
8613 if Assigned(GL_LibHandle) then
8614 glbFreeLibrary(GL_LibHandle);
8616 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8617 if Assigned(GLU_LibHandle) then
8618 glbFreeLibrary(GLU_LibHandle);
8619 FreeAndNil(InitOpenGLCS);