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 ------------------------------------------------------------
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 error '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 Delphi (including support for Delphi's (not Lazarus') TBitmap)
242 {.$DEFINE GLB_DELPHI}
244 // activate to enable the support for TLazIntfImage from Lazarus
245 {.$DEFINE GLB_LAZARUS}
249 // activate to enable the support of SDL_image to load files. (READ ONLY)
250 // If you enable SDL_image all other libraries will be ignored!
251 {.$DEFINE GLB_SDL_IMAGE}
255 // activate to enable Lazarus TPortableNetworkGraphic support
256 // if you enable this pngImage and libPNG will be ignored
257 {.$DEFINE GLB_LAZ_PNG}
259 // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/
260 // if you enable pngimage the libPNG will be ignored
261 {.$DEFINE GLB_PNGIMAGE}
263 // activate to use the libPNG -> http://www.libpng.org/
264 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libpng
265 {.$DEFINE GLB_LIB_PNG}
269 // activate to enable Lazarus TJPEGImage support
270 // if you enable this delphi jpegs and libJPEG will be ignored
271 {.$DEFINE GLB_LAZ_JPEG}
273 // if you enable delphi jpegs the libJPEG will be ignored
274 {.$DEFINE GLB_DELPHI_JPEG}
276 // activate to use the libJPEG -> http://www.ijg.org/
277 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libjpeg
278 {.$DEFINE GLB_LIB_JPEG}
281 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
282 // PRIVATE: do not change anything! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299 {$IF DEFINED(WIN32) or DEFINED(WIN64) or DEFINED(WINDOWS)}
301 {$ELSEIF DEFINED(LINUX)}
305 // native OpenGL Support
306 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) OR DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
307 {$DEFINE GLB_NATIVE_OGL}
310 // checking define combinations
312 {$IFDEF GLB_SDL_IMAGE}
314 {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
319 {$MESSAGE warn 'The Lazarus TPortableNetworkGraphics will be ignored because you are using SDL_image.'}
323 {$IFDEF GLB_PNGIMAGE}
324 {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
325 {$undef GLB_PNGIMAGE}
328 {$IFDEF GLB_LAZ_JPEG}
329 {$MESSAGE warn 'The Lazarus TJPEGImage will be ignored because you are using SDL_image.'}
330 {$undef GLB_LAZ_JPEG}
333 {$IFDEF GLB_DELPHI_JPEG}
334 {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
335 {$undef GLB_DELPHI_JPEG}
339 {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
343 {$IFDEF GLB_LIB_JPEG}
344 {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
345 {$undef GLB_LIB_JPEG}
348 {$DEFINE GLB_SUPPORT_PNG_READ}
349 {$DEFINE GLB_SUPPORT_JPEG_READ}
352 // Lazarus TPortableNetworkGraphic
354 {$IFNDEF GLB_LAZARUS}
355 {$MESSAGE warn 'Lazarus TPortableNetworkGraphic won''t work without Lazarus. Lazarus will be activated.'}
356 {$DEFINE GLB_LAZARUS}
359 {$IFDEF GLB_PNGIMAGE}
360 {$MESSAGE warn 'The pngimage will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
361 {$undef GLB_PNGIMAGE}
365 {$MESSAGE warn 'The library libPNG will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
369 {$DEFINE GLB_SUPPORT_PNG_READ}
370 {$DEFINE GLB_SUPPORT_PNG_WRITE}
374 {$IFDEF GLB_PNGIMAGE}
376 {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'}
380 {$DEFINE GLB_SUPPORT_PNG_READ}
381 {$DEFINE GLB_SUPPORT_PNG_WRITE}
386 {$DEFINE GLB_SUPPORT_PNG_READ}
387 {$DEFINE GLB_SUPPORT_PNG_WRITE}
390 // Lazarus TJPEGImage
391 {$IFDEF GLB_LAZ_JPEG}
392 {$IFNDEF GLB_LAZARUS}
393 {$MESSAGE warn 'Lazarus TJPEGImage won''t work without Lazarus. Lazarus will be activated.'}
394 {$DEFINE GLB_LAZARUS}
397 {$IFDEF GLB_DELPHI_JPEG}
398 {$MESSAGE warn 'The Delphi JPEGImage will be ignored if you are using the Lazarus TJPEGImage.'}
399 {$undef GLB_DELPHI_JPEG}
402 {$IFDEF GLB_LIB_JPEG}
403 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the Lazarus TJPEGImage.'}
404 {$undef GLB_LIB_JPEG}
407 {$DEFINE GLB_SUPPORT_JPEG_READ}
408 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
412 {$IFDEF GLB_DELPHI_JPEG}
413 {$IFDEF GLB_LIB_JPEG}
414 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
415 {$undef GLB_LIB_JPEG}
418 {$DEFINE GLB_SUPPORT_JPEG_READ}
419 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
423 {$IFDEF GLB_LIB_JPEG}
424 {$DEFINE GLB_SUPPORT_JPEG_READ}
425 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
429 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) AND DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
430 {$MESSAGE warn 'GLB_NATIVE_OGL_STATIC will be ignored because you enabled GLB_NATIVE_OGL_DYNAMIC'}
444 {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF}
445 {$IF DEFINED(GLB_WIN) AND
446 (DEFINED(GLB_NATIVE_OGL) OR
447 DEFINED(GLB_DELPHI))} windows, {$IFEND}
449 {$IFDEF GLB_SDL} SDL, {$ENDIF}
450 {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, Graphics, {$ENDIF}
451 {$IFDEF GLB_DELPHI} Dialogs, Graphics, Types, {$ENDIF}
453 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
454 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
455 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
456 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
457 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
461 {$IFDEF GLB_NATIVE_OGL}
470 GL_EXTENSIONS = $1F03;
472 GL_TEXTURE_1D = $0DE0;
473 GL_TEXTURE_2D = $0DE1;
474 GL_TEXTURE_RECTANGLE = $84F5;
476 GL_NORMAL_MAP = $8511;
477 GL_TEXTURE_CUBE_MAP = $8513;
478 GL_REFLECTION_MAP = $8512;
479 GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515;
480 GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516;
481 GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517;
482 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518;
483 GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519;
484 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A;
486 GL_TEXTURE_WIDTH = $1000;
487 GL_TEXTURE_HEIGHT = $1001;
488 GL_TEXTURE_INTERNAL_FORMAT = $1003;
489 GL_TEXTURE_SWIZZLE_RGBA = $8E46;
496 GL_TEXTURE_GEN_S = $0C60;
497 GL_TEXTURE_GEN_T = $0C61;
498 GL_TEXTURE_GEN_R = $0C62;
499 GL_TEXTURE_GEN_Q = $0C63;
511 GL_LUMINANCE = $1909;
512 GL_LUMINANCE4 = $803F;
513 GL_LUMINANCE8 = $8040;
514 GL_LUMINANCE12 = $8041;
515 GL_LUMINANCE16 = $8042;
517 GL_LUMINANCE_ALPHA = $190A;
518 GL_LUMINANCE4_ALPHA4 = $8043;
519 GL_LUMINANCE6_ALPHA2 = $8044;
520 GL_LUMINANCE8_ALPHA8 = $8045;
521 GL_LUMINANCE12_ALPHA4 = $8046;
522 GL_LUMINANCE12_ALPHA12 = $8047;
523 GL_LUMINANCE16_ALPHA16 = $8048;
546 GL_DEPTH_COMPONENT = $1902;
547 GL_DEPTH_COMPONENT16 = $81A5;
548 GL_DEPTH_COMPONENT24 = $81A6;
549 GL_DEPTH_COMPONENT32 = $81A7;
551 GL_COMPRESSED_RGB = $84ED;
552 GL_COMPRESSED_RGBA = $84EE;
553 GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
554 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
555 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
556 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
558 GL_UNSIGNED_BYTE = $1401;
559 GL_UNSIGNED_BYTE_3_3_2 = $8032;
560 GL_UNSIGNED_BYTE_2_3_3_REV = $8362;
562 GL_UNSIGNED_SHORT = $1403;
563 GL_UNSIGNED_SHORT_5_6_5 = $8363;
564 GL_UNSIGNED_SHORT_4_4_4_4 = $8033;
565 GL_UNSIGNED_SHORT_5_5_5_1 = $8034;
566 GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
567 GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
568 GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
570 GL_UNSIGNED_INT = $1405;
571 GL_UNSIGNED_INT_8_8_8_8 = $8035;
572 GL_UNSIGNED_INT_10_10_10_2 = $8036;
573 GL_UNSIGNED_INT_8_8_8_8_REV = $8367;
574 GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
577 GL_TEXTURE_MAG_FILTER = $2800;
578 GL_TEXTURE_MIN_FILTER = $2801;
580 GL_NEAREST_MIPMAP_NEAREST = $2700;
581 GL_NEAREST_MIPMAP_LINEAR = $2702;
583 GL_LINEAR_MIPMAP_NEAREST = $2701;
584 GL_LINEAR_MIPMAP_LINEAR = $2703;
587 GL_TEXTURE_WRAP_S = $2802;
588 GL_TEXTURE_WRAP_T = $2803;
589 GL_TEXTURE_WRAP_R = $8072;
592 GL_CLAMP_TO_EDGE = $812F;
593 GL_CLAMP_TO_BORDER = $812D;
594 GL_MIRRORED_REPEAT = $8370;
597 GL_GENERATE_MIPMAP = $8191;
598 GL_TEXTURE_BORDER_COLOR = $1004;
599 GL_MAX_TEXTURE_SIZE = $0D33;
600 GL_PACK_ALIGNMENT = $0D05;
601 GL_UNPACK_ALIGNMENT = $0CF5;
603 GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
604 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
605 GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C;
606 GL_TEXTURE_GEN_MODE = $2500;
608 {$IF DEFINED(GLB_WIN)}
609 libglu = 'glu32.dll';
610 libopengl = 'opengl32.dll';
611 {$ELSEIF DEFINED(GLB_LINUX)}
612 libglu = 'libGLU.so.1';
613 libopengl = 'libGL.so.1';
617 GLboolean = BYTEBOOL;
625 PGLboolean = ^GLboolean;
630 TglCompressedTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
631 TglCompressedTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
632 TglGetCompressedTexImage = procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
634 {$IF DEFINED(GLB_WIN)}
635 TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall;
636 {$ELSEIF DEFINED(GLB_LINUX)}
637 TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl;
638 TglXGetProcAddressARB = function(const name: PAnsiChar): pointer; cdecl;
641 {$IF DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
642 TglEnable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
643 TglDisable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
645 TglGetString = function(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
646 TglGetIntegerv = procedure(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
648 TglTexParameteri = procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
649 TglTexParameteriv = procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
650 TglTexParameterfv = procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
651 TglGetTexParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
652 TglGetTexParameterfv = procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
653 TglGetTexLevelParameteriv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
654 TglGetTexLevelParameterfv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
656 TglTexGeni = procedure(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
657 TglGenTextures = procedure(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
658 TglBindTexture = procedure(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
659 TglDeleteTextures = procedure(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
661 TglAreTexturesResident = function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
662 TglReadPixels = procedure(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
663 TglPixelStorei = procedure(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
665 TglTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
666 TglTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
667 TglGetTexImage = procedure(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
669 TgluBuild1DMipmaps = function(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
670 TgluBuild2DMipmaps = function(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
672 {$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)}
673 procedure glEnable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
674 procedure glDisable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
676 function glGetString(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
677 procedure glGetIntegerv(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
679 procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
680 procedure glTexParameteriv(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
681 procedure glTexParameterfv(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
682 procedure glGetTexParameteriv(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
683 procedure glGetTexParameterfv(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
684 procedure glGetTexLevelParameteriv(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
685 procedure glGetTexLevelParameterfv(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
687 procedure glTexGeni(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
688 procedure glGenTextures(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
689 procedure glBindTexture(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
690 procedure glDeleteTextures(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
692 function glAreTexturesResident(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
693 procedure glReadPixels(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
694 procedure glPixelStorei(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
696 procedure glTexImage1D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
697 procedure glTexImage2D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
698 procedure glGetTexImage(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
700 function gluBuild1DMipmaps(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
701 function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
711 GL_SGIS_generate_mipmap,
713 GL_ARB_texture_border_clamp,
714 GL_ARB_texture_mirrored_repeat,
715 GL_ARB_texture_rectangle,
716 GL_ARB_texture_non_power_of_two,
717 GL_ARB_texture_swizzle,
718 GL_ARB_texture_cube_map,
720 GL_IBM_texture_mirrored_repeat,
722 GL_NV_texture_rectangle,
724 GL_EXT_texture_edge_clamp,
725 GL_EXT_texture_rectangle,
726 GL_EXT_texture_swizzle,
727 GL_EXT_texture_cube_map,
728 GL_EXT_texture_filter_anisotropic: Boolean;
730 glCompressedTexImage1D: TglCompressedTexImage1D;
731 glCompressedTexImage2D: TglCompressedTexImage2D;
732 glGetCompressedTexImage: TglGetCompressedTexImage;
734 {$IF DEFINED(GLB_WIN)}
735 wglGetProcAddress: TwglGetProcAddress;
736 {$ELSEIF DEFINED(GLB_LINUX)}
737 glXGetProcAddress: TglXGetProcAddress;
738 glXGetProcAddressARB: TglXGetProcAddress;
741 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
743 glDisable: TglDisable;
745 glGetString: TglGetString;
746 glGetIntegerv: TglGetIntegerv;
748 glTexParameteri: TglTexParameteri;
749 glTexParameteriv: TglTexParameteriv;
750 glTexParameterfv: TglTexParameterfv;
751 glGetTexParameteriv: TglGetTexParameteriv;
752 glGetTexParameterfv: TglGetTexParameterfv;
753 glGetTexLevelParameteriv: TglGetTexLevelParameteriv;
754 glGetTexLevelParameterfv: TglGetTexLevelParameterfv;
756 glTexGeni: TglTexGeni;
757 glGenTextures: TglGenTextures;
758 glBindTexture: TglBindTexture;
759 glDeleteTextures: TglDeleteTextures;
761 glAreTexturesResident: TglAreTexturesResident;
762 glReadPixels: TglReadPixels;
763 glPixelStorei: TglPixelStorei;
765 glTexImage1D: TglTexImage1D;
766 glTexImage2D: TglTexImage2D;
767 glGetTexImage: TglGetTexImage;
769 gluBuild1DMipmaps: TgluBuild1DMipmaps;
770 gluBuild2DMipmaps: TgluBuild2DMipmaps;
775 ////////////////////////////////////////////////////////////////////////////////////////////////////
777 tfEmpty = 0, //must be smallest value!
793 tfLuminance12Alpha12,
794 tfLuminance16Alpha16,
838 TglBitmapFileType = (
839 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
840 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
844 TglBitmapFileTypes = set of TglBitmapFileType;
851 TglBitmapNormalMapFunc = (
857 ////////////////////////////////////////////////////////////////////////////////////////////////////
858 EglBitmap = class(Exception);
859 EglBitmapNotSupported = class(Exception);
860 EglBitmapSizeToLarge = class(EglBitmap);
861 EglBitmapNonPowerOfTwo = class(EglBitmap);
862 EglBitmapUnsupportedFormat = class(EglBitmap)
864 constructor Create(const aFormat: TglBitmapFormat); overload;
865 constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload;
868 ////////////////////////////////////////////////////////////////////////////////////////////////////
869 TglBitmapColorRec = packed record
871 0: (r, g, b, a: Cardinal);
872 1: (arr: array[0..3] of Cardinal);
875 TglBitmapPixelData = packed record
876 Data, Range: TglBitmapColorRec;
877 Format: TglBitmapFormat;
879 PglBitmapPixelData = ^TglBitmapPixelData;
881 ////////////////////////////////////////////////////////////////////////////////////////////////////
882 TglBitmapPixelPositionFields = set of (ffX, ffY);
883 TglBitmapPixelPosition = record
884 Fields : TglBitmapPixelPositionFields;
889 TglBitmapFormatDescriptor = class(TObject)
891 function GetIsCompressed: Boolean; virtual; abstract;
892 function GetHasRed: Boolean; virtual; abstract;
893 function GetHasGreen: Boolean; virtual; abstract;
894 function GetHasBlue: Boolean; virtual; abstract;
895 function GetHasAlpha: Boolean; virtual; abstract;
897 function GetglDataFormat: GLenum; virtual; abstract;
898 function GetglFormat: GLenum; virtual; abstract;
899 function GetglInternalFormat: GLenum; virtual; abstract;
901 property IsCompressed: Boolean read GetIsCompressed;
902 property HasRed: Boolean read GetHasRed;
903 property HasGreen: Boolean read GetHasGreen;
904 property HasBlue: Boolean read GetHasBlue;
905 property HasAlpha: Boolean read GetHasAlpha;
907 property glFormat: GLenum read GetglFormat;
908 property glInternalFormat: GLenum read GetglInternalFormat;
909 property glDataFormat: GLenum read GetglDataFormat;
912 ////////////////////////////////////////////////////////////////////////////////////////////////////
914 TglBitmapFunctionRec = record
916 Size: TglBitmapPixelPosition;
917 Position: TglBitmapPixelPosition;
918 Source: TglBitmapPixelData;
919 Dest: TglBitmapPixelData;
922 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
924 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
927 function GetFormatDesc: TglBitmapFormatDescriptor;
931 fAnisotropic: Integer;
932 fDeleteTextureOnFree: Boolean;
933 fFreeDataOnDestroy: Boolean;
934 fFreeDataAfterGenTexture: Boolean;
936 fIsResident: GLboolean;
937 fBorderColor: array[0..3] of Single;
939 fDimension: TglBitmapPixelPosition;
940 fMipMap: TglBitmapMipMap;
941 fFormat: TglBitmapFormat;
957 fSwizzle: array[0..3] of GLenum;
962 fCustomNameW: WideString;
963 fCustomData: Pointer;
966 function GetWidth: Integer; virtual;
967 function GetHeight: Integer; virtual;
969 function GetFileWidth: Integer; virtual;
970 function GetFileHeight: Integer; virtual;
973 procedure SetCustomData(const aValue: Pointer);
974 procedure SetCustomName(const aValue: String);
975 procedure SetCustomNameW(const aValue: WideString);
976 procedure SetFreeDataOnDestroy(const aValue: Boolean);
977 procedure SetDeleteTextureOnFree(const aValue: Boolean);
978 procedure SetFormat(const aValue: TglBitmapFormat);
979 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
980 procedure SetID(const aValue: Cardinal);
981 procedure SetMipMap(const aValue: TglBitmapMipMap);
982 procedure SetTarget(const aValue: Cardinal);
983 procedure SetAnisotropic(const aValue: Integer);
986 procedure SetupParameters(out aBuildWithGlu: Boolean);
987 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
988 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; //be careful, aData could be freed by this method
989 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
991 function FlipHorz: Boolean; virtual;
992 function FlipVert: Boolean; virtual;
994 property Width: Integer read GetWidth;
995 property Height: Integer read GetHeight;
997 property FileWidth: Integer read GetFileWidth;
998 property FileHeight: Integer read GetFileHeight;
1001 property ID: Cardinal read fID write SetID;
1002 property Target: Cardinal read fTarget write SetTarget;
1003 property Format: TglBitmapFormat read fFormat write SetFormat;
1004 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
1005 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
1007 property FormatDesc: TglBitmapFormatDescriptor read GetFormatDesc;
1009 property Filename: String read fFilename;
1010 property CustomName: String read fCustomName write SetCustomName;
1011 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
1012 property CustomData: Pointer read fCustomData write SetCustomData;
1014 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
1015 property FreeDataOnDestroy: Boolean read fFreeDataOnDestroy write SetFreeDataOnDestroy;
1016 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
1018 property Dimension: TglBitmapPixelPosition read fDimension;
1019 property Data: PByte read fData;
1020 property IsResident: GLboolean read fIsResident;
1022 procedure AfterConstruction; override;
1023 procedure BeforeDestruction; override;
1025 procedure PrepareResType(var aResource: String; var aResType: PChar);
1028 procedure LoadFromFile(const aFilename: String);
1029 procedure LoadFromStream(const aStream: TStream); virtual;
1030 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
1031 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil);
1032 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil);
1033 procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
1036 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
1037 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
1040 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
1041 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
1042 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
1046 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
1047 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
1048 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
1049 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
1050 const aArgs: Pointer = nil): Boolean;
1054 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
1055 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
1056 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
1057 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
1058 const aArgs: Pointer = nil): Boolean;
1061 {$IFDEF GLB_LAZARUS}
1062 function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1063 function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
1064 function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1065 function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil;
1066 const aArgs: Pointer = nil): Boolean;
1069 function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil;
1070 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1071 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
1072 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1074 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
1075 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1076 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1077 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1079 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
1080 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
1081 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
1083 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
1084 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
1085 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
1087 function RemoveAlpha: Boolean; virtual;
1090 function Clone: TglBitmap;
1091 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
1092 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
1093 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
1097 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
1098 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
1099 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
1102 procedure SetFilter(const aMin, aMag: GLenum);
1104 const S: GLenum = GL_CLAMP_TO_EDGE;
1105 const T: GLenum = GL_CLAMP_TO_EDGE;
1106 const R: GLenum = GL_CLAMP_TO_EDGE);
1107 procedure SetSwizzle(const r, g, b, a: GLenum);
1109 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
1110 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
1113 constructor Create; overload;
1114 constructor Create(const aFileName: String); overload;
1115 constructor Create(const aStream: TStream); overload;
1116 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte = nil); overload;
1117 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
1118 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
1119 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
1121 {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1122 {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF}
1124 {$IFDEF GLB_SUPPORT_JPEG_READ} function LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1125 {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF}
1127 function LoadBMP(const aStream: TStream): Boolean; virtual;
1128 procedure SaveBMP(const aStream: TStream); virtual;
1130 function LoadTGA(const aStream: TStream): Boolean; virtual;
1131 procedure SaveTGA(const aStream: TStream); virtual;
1133 function LoadDDS(const aStream: TStream): Boolean; virtual;
1134 procedure SaveDDS(const aStream: TStream); virtual;
1137 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1138 TglBitmap1D = class(TglBitmap)
1140 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1141 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1142 procedure UploadData(const aBuildWithGlu: Boolean);
1145 procedure AfterConstruction; override;
1146 function FlipHorz: Boolean; override;
1147 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1150 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1151 TglBitmap2D = class(TglBitmap)
1153 fLines: array of PByte;
1154 function GetScanline(const aIndex: Integer): Pointer;
1155 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1156 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1157 procedure UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
1161 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
1163 procedure AfterConstruction; override;
1165 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
1166 procedure GetDataFromTexture;
1167 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1169 function FlipHorz: Boolean; override;
1170 function FlipVert: Boolean; override;
1172 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
1173 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1176 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1177 TglBitmapCubeMap = class(TglBitmap2D)
1180 procedure GenTexture(const aTestTextureSize: Boolean = true); reintroduce;
1182 procedure AfterConstruction; override;
1183 procedure GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean = true);
1184 procedure Bind(const aEnableTexCoordsGen: Boolean = true; const aEnableTextureUnit: Boolean = true); reintroduce; virtual;
1185 procedure Unbind(const aDisableTexCoordsGen: Boolean = true; const aDisableTextureUnit: Boolean = true); reintroduce; virtual;
1188 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1189 TglBitmapNormalMap = class(TglBitmapCubeMap)
1191 procedure AfterConstruction; override;
1192 procedure GenerateNormalMap(const aSize: Integer = 32; const aTestTextureSize: Boolean = true);
1196 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1198 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1199 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1200 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1201 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1202 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1203 procedure glBitmapSetDefaultWrap(
1204 const S: Cardinal = GL_CLAMP_TO_EDGE;
1205 const T: Cardinal = GL_CLAMP_TO_EDGE;
1206 const R: Cardinal = GL_CLAMP_TO_EDGE);
1208 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1209 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1210 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1211 function glBitmapGetDefaultFormat: TglBitmapFormat;
1212 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1213 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1215 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1216 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1217 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1220 glBitmapDefaultDeleteTextureOnFree: Boolean;
1221 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1222 glBitmapDefaultFormat: TglBitmapFormat;
1223 glBitmapDefaultMipmap: TglBitmapMipMap;
1224 glBitmapDefaultFilterMin: Cardinal;
1225 glBitmapDefaultFilterMag: Cardinal;
1226 glBitmapDefaultWrapS: Cardinal;
1227 glBitmapDefaultWrapT: Cardinal;
1228 glBitmapDefaultWrapR: Cardinal;
1229 glDefaultSwizzle: array[0..3] of GLenum;
1232 function CreateGrayPalette: HPALETTE;
1238 Math, syncobjs, typinfo
1239 {$IF DEFINED(GLB_SUPPORT_JPEG_READ) AND DEFINED(GLB_LAZ_JPEG)}, FPReadJPEG{$IFEND};
1243 QWord = System.UInt64;
1250 ////////////////////////////////////////////////////////////////////////////////////////////////////
1251 TShiftRec = packed record
1253 0: (r, g, b, a: Byte);
1254 1: (arr: array[0..3] of Byte);
1257 TFormatDescriptor = class(TglBitmapFormatDescriptor)
1259 function GetRedMask: QWord;
1260 function GetGreenMask: QWord;
1261 function GetBlueMask: QWord;
1262 function GetAlphaMask: QWord;
1264 fFormat: TglBitmapFormat;
1265 fWithAlpha: TglBitmapFormat;
1266 fWithoutAlpha: TglBitmapFormat;
1267 fRGBInverted: TglBitmapFormat;
1268 fUncompressed: TglBitmapFormat;
1270 fIsCompressed: Boolean;
1272 fRange: TglBitmapColorRec;
1276 fglInternalFormat: GLenum;
1277 fglDataFormat: GLenum;
1279 function GetIsCompressed: Boolean; override;
1280 function GetHasRed: Boolean; override;
1281 function GetHasGreen: Boolean; override;
1282 function GetHasBlue: Boolean; override;
1283 function GetHasAlpha: Boolean; override;
1285 function GetglFormat: GLenum; override;
1286 function GetglInternalFormat: GLenum; override;
1287 function GetglDataFormat: GLenum; override;
1289 function GetComponents: Integer; virtual;
1291 property Format: TglBitmapFormat read fFormat;
1292 property WithAlpha: TglBitmapFormat read fWithAlpha;
1293 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1294 property RGBInverted: TglBitmapFormat read fRGBInverted;
1295 property Components: Integer read GetComponents;
1296 property PixelSize: Single read fPixelSize;
1298 property Range: TglBitmapColorRec read fRange;
1299 property Shift: TShiftRec read fShift;
1301 property RedMask: QWord read GetRedMask;
1302 property GreenMask: QWord read GetGreenMask;
1303 property BlueMask: QWord read GetBlueMask;
1304 property AlphaMask: QWord read GetAlphaMask;
1306 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1307 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1309 function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual;
1310 function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
1312 function CreateMappingData: Pointer; virtual;
1313 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1315 function IsEmpty: Boolean; virtual;
1316 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual;
1318 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1320 constructor Create; virtual;
1322 class procedure Init;
1323 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1324 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1325 class procedure Clear;
1326 class procedure Finalize;
1328 TFormatDescriptorClass = class of TFormatDescriptor;
1330 TfdEmpty = class(TFormatDescriptor);
1332 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1333 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1334 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1335 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1336 constructor Create; override;
1339 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1340 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1341 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1342 constructor Create; override;
1345 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1346 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1347 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1348 constructor Create; override;
1351 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1352 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1353 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1354 constructor Create; override;
1357 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1358 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1359 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1360 constructor Create; override;
1363 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1364 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1365 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1366 constructor Create; override;
1369 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1370 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1371 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1372 constructor Create; override;
1375 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1376 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1377 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1378 constructor Create; override;
1381 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1382 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1383 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1384 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1385 constructor Create; override;
1388 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1389 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1390 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1391 constructor Create; override;
1394 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1395 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1396 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1397 constructor Create; override;
1400 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1401 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1402 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1403 constructor Create; override;
1406 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1407 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1408 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1409 constructor Create; override;
1412 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1413 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1414 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1415 constructor Create; override;
1418 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1419 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1420 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1421 constructor Create; override;
1424 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1425 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1426 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1427 constructor Create; override;
1430 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1431 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1432 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1433 constructor Create; override;
1436 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1437 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1438 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1439 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1440 constructor Create; override;
1443 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1444 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1445 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1446 constructor Create; override;
1449 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1450 TfdAlpha4 = class(TfdAlpha_UB1)
1451 constructor Create; override;
1454 TfdAlpha8 = class(TfdAlpha_UB1)
1455 constructor Create; override;
1458 TfdAlpha12 = class(TfdAlpha_US1)
1459 constructor Create; override;
1462 TfdAlpha16 = class(TfdAlpha_US1)
1463 constructor Create; override;
1466 TfdLuminance4 = class(TfdLuminance_UB1)
1467 constructor Create; override;
1470 TfdLuminance8 = class(TfdLuminance_UB1)
1471 constructor Create; override;
1474 TfdLuminance12 = class(TfdLuminance_US1)
1475 constructor Create; override;
1478 TfdLuminance16 = class(TfdLuminance_US1)
1479 constructor Create; override;
1482 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1483 constructor Create; override;
1486 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1487 constructor Create; override;
1490 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1491 constructor Create; override;
1494 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1495 constructor Create; override;
1498 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1499 constructor Create; override;
1502 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1503 constructor Create; override;
1506 TfdR3G3B2 = class(TfdUniversal_UB1)
1507 constructor Create; override;
1510 TfdRGB4 = class(TfdUniversal_US1)
1511 constructor Create; override;
1514 TfdR5G6B5 = class(TfdUniversal_US1)
1515 constructor Create; override;
1518 TfdRGB5 = class(TfdUniversal_US1)
1519 constructor Create; override;
1522 TfdRGB8 = class(TfdRGB_UB3)
1523 constructor Create; override;
1526 TfdRGB10 = class(TfdUniversal_UI1)
1527 constructor Create; override;
1530 TfdRGB12 = class(TfdRGB_US3)
1531 constructor Create; override;
1534 TfdRGB16 = class(TfdRGB_US3)
1535 constructor Create; override;
1538 TfdRGBA2 = class(TfdRGBA_UB4)
1539 constructor Create; override;
1542 TfdRGBA4 = class(TfdUniversal_US1)
1543 constructor Create; override;
1546 TfdRGB5A1 = class(TfdUniversal_US1)
1547 constructor Create; override;
1550 TfdRGBA8 = class(TfdRGBA_UB4)
1551 constructor Create; override;
1554 TfdRGB10A2 = class(TfdUniversal_UI1)
1555 constructor Create; override;
1558 TfdRGBA12 = class(TfdRGBA_US4)
1559 constructor Create; override;
1562 TfdRGBA16 = class(TfdRGBA_US4)
1563 constructor Create; override;
1566 TfdBGR4 = class(TfdUniversal_US1)
1567 constructor Create; override;
1570 TfdB5G6R5 = class(TfdUniversal_US1)
1571 constructor Create; override;
1574 TfdBGR5 = class(TfdUniversal_US1)
1575 constructor Create; override;
1578 TfdBGR8 = class(TfdBGR_UB3)
1579 constructor Create; override;
1582 TfdBGR10 = class(TfdUniversal_UI1)
1583 constructor Create; override;
1586 TfdBGR12 = class(TfdBGR_US3)
1587 constructor Create; override;
1590 TfdBGR16 = class(TfdBGR_US3)
1591 constructor Create; override;
1594 TfdBGRA2 = class(TfdBGRA_UB4)
1595 constructor Create; override;
1598 TfdBGRA4 = class(TfdUniversal_US1)
1599 constructor Create; override;
1602 TfdBGR5A1 = class(TfdUniversal_US1)
1603 constructor Create; override;
1606 TfdBGRA8 = class(TfdBGRA_UB4)
1607 constructor Create; override;
1610 TfdBGR10A2 = class(TfdUniversal_UI1)
1611 constructor Create; override;
1614 TfdBGRA12 = class(TfdBGRA_US4)
1615 constructor Create; override;
1618 TfdBGRA16 = class(TfdBGRA_US4)
1619 constructor Create; override;
1622 TfdDepth16 = class(TfdDepth_US1)
1623 constructor Create; override;
1626 TfdDepth24 = class(TfdDepth_UI1)
1627 constructor Create; override;
1630 TfdDepth32 = class(TfdDepth_UI1)
1631 constructor Create; override;
1634 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1635 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1636 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1637 constructor Create; override;
1640 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1641 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1642 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1643 constructor Create; override;
1646 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1647 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1648 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1649 constructor Create; override;
1652 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1653 TbmpBitfieldFormat = class(TFormatDescriptor)
1655 procedure SetRedMask (const aValue: QWord);
1656 procedure SetGreenMask(const aValue: QWord);
1657 procedure SetBlueMask (const aValue: QWord);
1658 procedure SetAlphaMask(const aValue: QWord);
1660 procedure Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte);
1662 property RedMask: QWord read GetRedMask write SetRedMask;
1663 property GreenMask: QWord read GetGreenMask write SetGreenMask;
1664 property BlueMask: QWord read GetBlueMask write SetBlueMask;
1665 property AlphaMask: QWord read GetAlphaMask write SetAlphaMask;
1667 property PixelSize: Single read fPixelSize write fPixelSize;
1669 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1670 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1673 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1674 TbmpColorTableEnty = packed record
1677 TbmpColorTable = array of TbmpColorTableEnty;
1678 TbmpColorTableFormat = class(TFormatDescriptor)
1680 fColorTable: TbmpColorTable;
1682 property PixelSize: Single read fPixelSize write fPixelSize;
1683 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1684 property Range: TglBitmapColorRec read fRange write fRange;
1685 property Shift: TShiftRec read fShift write fShift;
1686 property Format: TglBitmapFormat read fFormat write fFormat;
1688 procedure CreateColorTable;
1690 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1691 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1692 destructor Destroy; override;
1696 LUMINANCE_WEIGHT_R = 0.30;
1697 LUMINANCE_WEIGHT_G = 0.59;
1698 LUMINANCE_WEIGHT_B = 0.11;
1700 ALPHA_WEIGHT_R = 0.30;
1701 ALPHA_WEIGHT_G = 0.59;
1702 ALPHA_WEIGHT_B = 0.11;
1704 DEPTH_WEIGHT_R = 0.333333333;
1705 DEPTH_WEIGHT_G = 0.333333333;
1706 DEPTH_WEIGHT_B = 0.333333333;
1708 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1710 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1723 TfdLuminance4Alpha4,
1724 TfdLuminance6Alpha2,
1725 TfdLuminance8Alpha8,
1726 TfdLuminance12Alpha4,
1727 TfdLuminance12Alpha12,
1728 TfdLuminance16Alpha16,
1773 FormatDescriptorCS: TCriticalSection;
1774 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1776 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1777 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1779 inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1782 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1783 constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat);
1785 inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1788 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1789 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1791 result.Fields := [];
1794 result.Fields := result.Fields + [ffX];
1796 result.Fields := result.Fields + [ffY];
1798 result.X := Max(0, X);
1799 result.Y := Max(0, Y);
1802 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1803 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1811 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1812 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1817 for i := 0 to high(r1.arr) do
1818 if (r1.arr[i] <> r2.arr[i]) then
1823 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1824 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1832 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1833 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1842 tfR3G3B2, tfLuminance8,
1845 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1846 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1852 tfRGB10, tfRGB10A2, tfRGBA8,
1853 tfBGR10, tfBGR10A2, tfBGRA8]) then
1854 result := result + [ftBMP];
1858 tfLuminance8, tfAlpha8,
1861 tfLuminance16, tfLuminance8Alpha8,
1862 tfRGB5, tfRGB5A1, tfRGBA4,
1863 tfBGR5, tfBGR5A1, tfBGRA4,
1869 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1870 result := result + [ftTGA];
1874 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1875 tfR3G3B2, tfRGBA2, tfBGRA2,
1878 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1879 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1880 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1886 tfLuminance16Alpha16,
1891 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1892 result := result + [ftDDS];
1894 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1896 tfAlpha8, tfLuminance8, tfLuminance8Alpha8,
1898 tfBGR8, tfBGRA8] then
1899 result := result + [ftPNG];
1902 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1903 if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then
1904 result := result + [ftJPEG];
1908 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1909 function IsPowerOfTwo(aNumber: Integer): Boolean;
1911 while (aNumber and 1) = 0 do
1912 aNumber := aNumber shr 1;
1913 result := aNumber = 1;
1916 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1917 function GetTopMostBit(aBitSet: QWord): Integer;
1920 while aBitSet > 0 do begin
1922 aBitSet := aBitSet shr 1;
1926 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1927 function CountSetBits(aBitSet: QWord): Integer;
1930 while aBitSet > 0 do begin
1931 if (aBitSet and 1) = 1 then
1933 aBitSet := aBitSet shr 1;
1937 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1938 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1941 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1942 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1943 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1946 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1947 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1950 DEPTH_WEIGHT_R * aPixel.Data.r +
1951 DEPTH_WEIGHT_G * aPixel.Data.g +
1952 DEPTH_WEIGHT_B * aPixel.Data.b);
1955 {$IFDEF GLB_NATIVE_OGL}
1956 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1957 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1958 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1960 GL_LibHandle: Pointer = nil;
1962 function glbGetProcAddress(aProcName: PAnsiChar; aLibHandle: Pointer = nil; const aRaiseOnErr: Boolean = true): Pointer;
1964 if not Assigned(aLibHandle) then
1965 aLibHandle := GL_LibHandle;
1967 {$IF DEFINED(GLB_WIN)}
1968 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1969 if Assigned(result) then
1972 if Assigned(wglGetProcAddress) then
1973 result := wglGetProcAddress(aProcName);
1974 {$ELSEIF DEFINED(GLB_LINUX)}
1975 if Assigned(glXGetProcAddress) then begin
1976 result := glXGetProcAddress(aProcName);
1977 if Assigned(result) then
1981 if Assigned(glXGetProcAddressARB) then begin
1982 result := glXGetProcAddressARB(aProcName);
1983 if Assigned(result) then
1987 result := dlsym(aLibHandle, aProcName);
1989 if not Assigned(result) and aRaiseOnErr then
1990 raise EglBitmap.Create('unable to load procedure form library: ' + aProcName);
1993 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1995 GLU_LibHandle: Pointer = nil;
1996 OpenGLInitialized: Boolean;
1997 InitOpenGLCS: TCriticalSection;
1999 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2000 procedure glbInitOpenGL;
2002 ////////////////////////////////////////////////////////////////////////////////
2003 function glbLoadLibrary(const aName: PChar): Pointer;
2005 {$IF DEFINED(GLB_WIN)}
2006 result := {%H-}Pointer(LoadLibrary(aName));
2007 {$ELSEIF DEFINED(GLB_LINUX)}
2008 result := dlopen(Name, RTLD_LAZY);
2014 ////////////////////////////////////////////////////////////////////////////////
2015 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
2018 if not Assigned(aLibHandle) then
2021 {$IF DEFINED(GLB_WIN)}
2022 Result := FreeLibrary({%H-}HINST(aLibHandle));
2023 {$ELSEIF DEFINED(GLB_LINUX)}
2024 Result := dlclose(aLibHandle) = 0;
2029 if Assigned(GL_LibHandle) then
2030 glbFreeLibrary(GL_LibHandle);
2032 if Assigned(GLU_LibHandle) then
2033 glbFreeLibrary(GLU_LibHandle);
2035 GL_LibHandle := glbLoadLibrary(libopengl);
2036 if not Assigned(GL_LibHandle) then
2037 raise EglBitmap.Create('unable to load library: ' + libopengl);
2039 GLU_LibHandle := glbLoadLibrary(libglu);
2040 if not Assigned(GLU_LibHandle) then
2041 raise EglBitmap.Create('unable to load library: ' + libglu);
2043 {$IF DEFINED(GLB_WIN)}
2044 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
2045 {$ELSEIF DEFINED(GLB_LINUX)}
2046 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
2047 glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
2050 glEnable := glbGetProcAddress('glEnable');
2051 glDisable := glbGetProcAddress('glDisable');
2052 glGetString := glbGetProcAddress('glGetString');
2053 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
2054 glTexParameteri := glbGetProcAddress('glTexParameteri');
2055 glTexParameteriv := glbGetProcAddress('glTexParameteriv');
2056 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
2057 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
2058 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
2059 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
2060 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
2061 glTexGeni := glbGetProcAddress('glTexGeni');
2062 glGenTextures := glbGetProcAddress('glGenTextures');
2063 glBindTexture := glbGetProcAddress('glBindTexture');
2064 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
2065 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
2066 glReadPixels := glbGetProcAddress('glReadPixels');
2067 glPixelStorei := glbGetProcAddress('glPixelStorei');
2068 glTexImage1D := glbGetProcAddress('glTexImage1D');
2069 glTexImage2D := glbGetProcAddress('glTexImage2D');
2070 glGetTexImage := glbGetProcAddress('glGetTexImage');
2072 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
2073 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
2077 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2078 procedure glbReadOpenGLExtensions;
2081 MajorVersion, MinorVersion: Integer;
2083 ///////////////////////////////////////////////////////////////////////////////////////////
2084 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
2091 Separator := Pos(AnsiString('.'), aBuffer);
2092 if (Separator > 1) and (Separator < Length(aBuffer)) and
2093 (aBuffer[Separator - 1] in ['0'..'9']) and
2094 (aBuffer[Separator + 1] in ['0'..'9']) then begin
2097 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
2100 Delete(aBuffer, 1, Separator);
2101 Separator := Pos(AnsiString('.'), aBuffer) + 1;
2103 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
2106 Delete(aBuffer, Separator, 255);
2107 Separator := Pos(AnsiString('.'), aBuffer);
2109 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
2110 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2114 ///////////////////////////////////////////////////////////////////////////////////////////
2115 function CheckExtension(const Extension: AnsiString): Boolean;
2119 ExtPos := Pos(Extension, Buffer);
2120 result := ExtPos > 0;
2122 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2125 ///////////////////////////////////////////////////////////////////////////////////////////
2126 function CheckVersion(const aMajor, aMinor: Integer): Boolean;
2128 result := (MajorVersion > aMajor) or ((MajorVersion = aMajor) and (MinorVersion >= aMinor));
2132 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2135 if not OpenGLInitialized then begin
2137 OpenGLInitialized := true;
2145 Buffer := glGetString(GL_VERSION);
2146 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2148 GL_VERSION_1_2 := CheckVersion(1, 2);
2149 GL_VERSION_1_3 := CheckVersion(1, 3);
2150 GL_VERSION_1_4 := CheckVersion(1, 4);
2151 GL_VERSION_2_0 := CheckVersion(2, 0);
2152 GL_VERSION_3_3 := CheckVersion(3, 3);
2155 Buffer := glGetString(GL_EXTENSIONS);
2156 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2157 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2158 GL_ARB_texture_swizzle := CheckExtension('GL_ARB_texture_swizzle');
2159 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
2160 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2161 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2162 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2163 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2164 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2165 GL_EXT_texture_swizzle := CheckExtension('GL_EXT_texture_swizzle');
2166 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
2167 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2168 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2169 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2171 if GL_VERSION_1_3 then begin
2172 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2173 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2174 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2176 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB', nil, false);
2177 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB', nil, false);
2178 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB', nil, false);
2183 {$IFDEF GLB_SDL_IMAGE}
2184 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2185 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2186 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2187 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2189 result := TStream(context^.unknown.data1).Seek(offset, whence);
2192 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2194 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2197 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2199 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2202 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2207 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2209 result := SDL_AllocRW;
2211 if result = nil then
2212 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2214 result^.seek := glBitmapRWseek;
2215 result^.read := glBitmapRWread;
2216 result^.write := glBitmapRWwrite;
2217 result^.close := glBitmapRWclose;
2218 result^.unknown.data1 := Stream;
2222 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2223 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2225 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2229 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2231 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2234 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2235 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2237 glBitmapDefaultMipmap := aValue;
2240 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2241 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2243 glBitmapDefaultFormat := aFormat;
2246 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2247 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2249 glBitmapDefaultFilterMin := aMin;
2250 glBitmapDefaultFilterMag := aMag;
2253 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2254 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2256 glBitmapDefaultWrapS := S;
2257 glBitmapDefaultWrapT := T;
2258 glBitmapDefaultWrapR := R;
2261 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2262 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
2264 glDefaultSwizzle[0] := r;
2265 glDefaultSwizzle[1] := g;
2266 glDefaultSwizzle[2] := b;
2267 glDefaultSwizzle[3] := a;
2270 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2271 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2273 result := glBitmapDefaultDeleteTextureOnFree;
2276 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2277 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2279 result := glBitmapDefaultFreeDataAfterGenTextures;
2282 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2283 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2285 result := glBitmapDefaultMipmap;
2288 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2289 function glBitmapGetDefaultFormat: TglBitmapFormat;
2291 result := glBitmapDefaultFormat;
2294 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2295 procedure glBitmapGetDefaultFilter(var aMin, aMag: GLenum);
2297 aMin := glBitmapDefaultFilterMin;
2298 aMag := glBitmapDefaultFilterMag;
2301 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2302 procedure glBitmapGetDefaultTextureWrap(var S, T, R: GLenum);
2304 S := glBitmapDefaultWrapS;
2305 T := glBitmapDefaultWrapT;
2306 R := glBitmapDefaultWrapR;
2309 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2310 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
2312 r := glDefaultSwizzle[0];
2313 g := glDefaultSwizzle[1];
2314 b := glDefaultSwizzle[2];
2315 a := glDefaultSwizzle[3];
2318 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2319 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2320 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2321 function TFormatDescriptor.GetRedMask: QWord;
2323 result := fRange.r shl fShift.r;
2326 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2327 function TFormatDescriptor.GetGreenMask: QWord;
2329 result := fRange.g shl fShift.g;
2332 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2333 function TFormatDescriptor.GetBlueMask: QWord;
2335 result := fRange.b shl fShift.b;
2338 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2339 function TFormatDescriptor.GetAlphaMask: QWord;
2341 result := fRange.a shl fShift.a;
2344 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2345 function TFormatDescriptor.GetIsCompressed: Boolean;
2347 result := fIsCompressed;
2350 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2351 function TFormatDescriptor.GetHasRed: Boolean;
2353 result := (fRange.r > 0);
2356 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2357 function TFormatDescriptor.GetHasGreen: Boolean;
2359 result := (fRange.g > 0);
2362 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2363 function TFormatDescriptor.GetHasBlue: Boolean;
2365 result := (fRange.b > 0);
2368 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2369 function TFormatDescriptor.GetHasAlpha: Boolean;
2371 result := (fRange.a > 0);
2374 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2375 function TFormatDescriptor.GetglFormat: GLenum;
2377 result := fglFormat;
2380 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2381 function TFormatDescriptor.GetglInternalFormat: GLenum;
2383 result := fglInternalFormat;
2386 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2387 function TFormatDescriptor.GetglDataFormat: GLenum;
2389 result := fglDataFormat;
2392 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2393 function TFormatDescriptor.GetComponents: Integer;
2399 if (fRange.arr[i] > 0) then
2403 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2404 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2408 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2409 w := Max(1, aSize.X);
2410 h := Max(1, aSize.Y);
2411 result := GetSize(w, h);
2416 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2417 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2420 if (aWidth <= 0) or (aHeight <= 0) then
2422 result := Ceil(aWidth * aHeight * fPixelSize);
2425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2426 function TFormatDescriptor.CreateMappingData: Pointer;
2431 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2432 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2437 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2438 function TFormatDescriptor.IsEmpty: Boolean;
2440 result := (fFormat = tfEmpty);
2443 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2444 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2447 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2448 raise EglBitmap.Create('FormatCheckFormat - All Masks are 0');
2449 if (aRedMask <> RedMask) then
2451 if (aGreenMask <> GreenMask) then
2453 if (aBlueMask <> BlueMask) then
2455 if (aAlphaMask <> AlphaMask) then
2460 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2461 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2463 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2464 aPixel.Data := fRange;
2465 aPixel.Range := fRange;
2466 aPixel.Format := fFormat;
2469 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2470 constructor TFormatDescriptor.Create;
2475 fWithAlpha := tfEmpty;
2476 fWithoutAlpha := tfEmpty;
2477 fRGBInverted := tfEmpty;
2478 fUncompressed := tfEmpty;
2480 fIsCompressed := false;
2483 fglInternalFormat := 0;
2486 FillChar(fRange, 0, SizeOf(fRange));
2487 FillChar(fShift, 0, SizeOf(fShift));
2490 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2491 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2492 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2493 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2495 aData^ := aPixel.Data.a;
2499 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2504 aPixel.Data.a := aData^;
2508 constructor TfdAlpha_UB1.Create;
2513 fglFormat := GL_ALPHA;
2514 fglDataFormat := GL_UNSIGNED_BYTE;
2517 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2518 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2519 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2520 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2522 aData^ := LuminanceWeight(aPixel);
2526 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2528 aPixel.Data.r := aData^;
2529 aPixel.Data.g := aData^;
2530 aPixel.Data.b := aData^;
2535 constructor TfdLuminance_UB1.Create;
2542 fglFormat := GL_LUMINANCE;
2543 fglDataFormat := GL_UNSIGNED_BYTE;
2546 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2547 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2548 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2549 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2555 if (fRange.arr[i] > 0) then
2556 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2560 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2565 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2569 constructor TfdUniversal_UB1.Create;
2575 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2576 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2577 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2578 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2580 inherited Map(aPixel, aData, aMapData);
2581 aData^ := aPixel.Data.a;
2585 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2587 inherited Unmap(aData, aPixel, aMapData);
2588 aPixel.Data.a := aData^;
2592 constructor TfdLuminanceAlpha_UB2.Create;
2598 fglFormat := GL_LUMINANCE_ALPHA;
2599 fglDataFormat := GL_UNSIGNED_BYTE;
2602 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2603 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2604 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2605 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2607 aData^ := aPixel.Data.r;
2609 aData^ := aPixel.Data.g;
2611 aData^ := aPixel.Data.b;
2615 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2617 aPixel.Data.r := aData^;
2619 aPixel.Data.g := aData^;
2621 aPixel.Data.b := aData^;
2626 constructor TfdRGB_UB3.Create;
2636 fglFormat := GL_RGB;
2637 fglDataFormat := GL_UNSIGNED_BYTE;
2640 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2641 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2642 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2643 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2645 aData^ := aPixel.Data.b;
2647 aData^ := aPixel.Data.g;
2649 aData^ := aPixel.Data.r;
2653 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2655 aPixel.Data.b := aData^;
2657 aPixel.Data.g := aData^;
2659 aPixel.Data.r := aData^;
2664 constructor TfdBGR_UB3.Create;
2673 fglFormat := GL_BGR;
2674 fglDataFormat := GL_UNSIGNED_BYTE;
2677 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2678 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2679 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2680 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2682 inherited Map(aPixel, aData, aMapData);
2683 aData^ := aPixel.Data.a;
2687 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2689 inherited Unmap(aData, aPixel, aMapData);
2690 aPixel.Data.a := aData^;
2694 constructor TfdRGBA_UB4.Create;
2700 fglFormat := GL_RGBA;
2701 fglDataFormat := GL_UNSIGNED_BYTE;
2704 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2705 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2706 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2707 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2709 inherited Map(aPixel, aData, aMapData);
2710 aData^ := aPixel.Data.a;
2714 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2716 inherited Unmap(aData, aPixel, aMapData);
2717 aPixel.Data.a := aData^;
2721 constructor TfdBGRA_UB4.Create;
2727 fglFormat := GL_BGRA;
2728 fglDataFormat := GL_UNSIGNED_BYTE;
2731 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2732 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2733 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2734 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2736 PWord(aData)^ := aPixel.Data.a;
2740 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2745 aPixel.Data.a := PWord(aData)^;
2749 constructor TfdAlpha_US1.Create;
2754 fglFormat := GL_ALPHA;
2755 fglDataFormat := GL_UNSIGNED_SHORT;
2758 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2759 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2760 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2761 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2763 PWord(aData)^ := LuminanceWeight(aPixel);
2767 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2769 aPixel.Data.r := PWord(aData)^;
2770 aPixel.Data.g := PWord(aData)^;
2771 aPixel.Data.b := PWord(aData)^;
2776 constructor TfdLuminance_US1.Create;
2783 fglFormat := GL_LUMINANCE;
2784 fglDataFormat := GL_UNSIGNED_SHORT;
2787 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2788 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2789 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2790 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2796 if (fRange.arr[i] > 0) then
2797 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2801 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2806 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2810 constructor TfdUniversal_US1.Create;
2816 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2817 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2818 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2819 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2821 PWord(aData)^ := DepthWeight(aPixel);
2825 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2827 aPixel.Data.r := PWord(aData)^;
2828 aPixel.Data.g := PWord(aData)^;
2829 aPixel.Data.b := PWord(aData)^;
2834 constructor TfdDepth_US1.Create;
2841 fglFormat := GL_DEPTH_COMPONENT;
2842 fglDataFormat := GL_UNSIGNED_SHORT;
2845 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2846 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2847 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2848 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2850 inherited Map(aPixel, aData, aMapData);
2851 PWord(aData)^ := aPixel.Data.a;
2855 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2857 inherited Unmap(aData, aPixel, aMapData);
2858 aPixel.Data.a := PWord(aData)^;
2862 constructor TfdLuminanceAlpha_US2.Create;
2868 fglFormat := GL_LUMINANCE_ALPHA;
2869 fglDataFormat := GL_UNSIGNED_SHORT;
2872 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2873 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2874 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2875 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2877 PWord(aData)^ := aPixel.Data.r;
2879 PWord(aData)^ := aPixel.Data.g;
2881 PWord(aData)^ := aPixel.Data.b;
2885 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2887 aPixel.Data.r := PWord(aData)^;
2889 aPixel.Data.g := PWord(aData)^;
2891 aPixel.Data.b := PWord(aData)^;
2896 constructor TfdRGB_US3.Create;
2906 fglFormat := GL_RGB;
2907 fglDataFormat := GL_UNSIGNED_SHORT;
2910 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2911 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2912 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2913 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2915 PWord(aData)^ := aPixel.Data.b;
2917 PWord(aData)^ := aPixel.Data.g;
2919 PWord(aData)^ := aPixel.Data.r;
2923 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2925 aPixel.Data.b := PWord(aData)^;
2927 aPixel.Data.g := PWord(aData)^;
2929 aPixel.Data.r := PWord(aData)^;
2934 constructor TfdBGR_US3.Create;
2944 fglFormat := GL_BGR;
2945 fglDataFormat := GL_UNSIGNED_SHORT;
2948 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2949 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2950 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2951 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2953 inherited Map(aPixel, aData, aMapData);
2954 PWord(aData)^ := aPixel.Data.a;
2958 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2960 inherited Unmap(aData, aPixel, aMapData);
2961 aPixel.Data.a := PWord(aData)^;
2965 constructor TfdRGBA_US4.Create;
2971 fglFormat := GL_RGBA;
2972 fglDataFormat := GL_UNSIGNED_SHORT;
2975 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2976 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2977 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2978 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2980 inherited Map(aPixel, aData, aMapData);
2981 PWord(aData)^ := aPixel.Data.a;
2985 procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2987 inherited Unmap(aData, aPixel, aMapData);
2988 aPixel.Data.a := PWord(aData)^;
2992 constructor TfdBGRA_US4.Create;
2998 fglFormat := GL_BGRA;
2999 fglDataFormat := GL_UNSIGNED_SHORT;
3002 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3003 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3004 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3005 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3009 PCardinal(aData)^ := 0;
3011 if (fRange.arr[i] > 0) then
3012 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
3016 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3021 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
3025 constructor TfdUniversal_UI1.Create;
3031 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3032 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3033 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3034 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3036 PCardinal(aData)^ := DepthWeight(aPixel);
3040 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3042 aPixel.Data.r := PCardinal(aData)^;
3043 aPixel.Data.g := PCardinal(aData)^;
3044 aPixel.Data.b := PCardinal(aData)^;
3049 constructor TfdDepth_UI1.Create;
3053 fRange.r := $FFFFFFFF;
3054 fRange.g := $FFFFFFFF;
3055 fRange.b := $FFFFFFFF;
3056 fglFormat := GL_DEPTH_COMPONENT;
3057 fglDataFormat := GL_UNSIGNED_INT;
3060 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3061 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3062 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3063 constructor TfdAlpha4.Create;
3066 fFormat := tfAlpha4;
3067 fWithAlpha := tfAlpha4;
3068 fglInternalFormat := GL_ALPHA4;
3071 constructor TfdAlpha8.Create;
3074 fFormat := tfAlpha8;
3075 fWithAlpha := tfAlpha8;
3076 fglInternalFormat := GL_ALPHA8;
3079 constructor TfdAlpha12.Create;
3082 fFormat := tfAlpha12;
3083 fWithAlpha := tfAlpha12;
3084 fglInternalFormat := GL_ALPHA12;
3087 constructor TfdAlpha16.Create;
3090 fFormat := tfAlpha16;
3091 fWithAlpha := tfAlpha16;
3092 fglInternalFormat := GL_ALPHA16;
3095 constructor TfdLuminance4.Create;
3098 fFormat := tfLuminance4;
3099 fWithAlpha := tfLuminance4Alpha4;
3100 fWithoutAlpha := tfLuminance4;
3101 fglInternalFormat := GL_LUMINANCE4;
3104 constructor TfdLuminance8.Create;
3107 fFormat := tfLuminance8;
3108 fWithAlpha := tfLuminance8Alpha8;
3109 fWithoutAlpha := tfLuminance8;
3110 fglInternalFormat := GL_LUMINANCE8;
3113 constructor TfdLuminance12.Create;
3116 fFormat := tfLuminance12;
3117 fWithAlpha := tfLuminance12Alpha12;
3118 fWithoutAlpha := tfLuminance12;
3119 fglInternalFormat := GL_LUMINANCE12;
3122 constructor TfdLuminance16.Create;
3125 fFormat := tfLuminance16;
3126 fWithAlpha := tfLuminance16Alpha16;
3127 fWithoutAlpha := tfLuminance16;
3128 fglInternalFormat := GL_LUMINANCE16;
3131 constructor TfdLuminance4Alpha4.Create;
3134 fFormat := tfLuminance4Alpha4;
3135 fWithAlpha := tfLuminance4Alpha4;
3136 fWithoutAlpha := tfLuminance4;
3137 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3140 constructor TfdLuminance6Alpha2.Create;
3143 fFormat := tfLuminance6Alpha2;
3144 fWithAlpha := tfLuminance6Alpha2;
3145 fWithoutAlpha := tfLuminance8;
3146 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3149 constructor TfdLuminance8Alpha8.Create;
3152 fFormat := tfLuminance8Alpha8;
3153 fWithAlpha := tfLuminance8Alpha8;
3154 fWithoutAlpha := tfLuminance8;
3155 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3158 constructor TfdLuminance12Alpha4.Create;
3161 fFormat := tfLuminance12Alpha4;
3162 fWithAlpha := tfLuminance12Alpha4;
3163 fWithoutAlpha := tfLuminance12;
3164 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3167 constructor TfdLuminance12Alpha12.Create;
3170 fFormat := tfLuminance12Alpha12;
3171 fWithAlpha := tfLuminance12Alpha12;
3172 fWithoutAlpha := tfLuminance12;
3173 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3176 constructor TfdLuminance16Alpha16.Create;
3179 fFormat := tfLuminance16Alpha16;
3180 fWithAlpha := tfLuminance16Alpha16;
3181 fWithoutAlpha := tfLuminance16;
3182 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3185 constructor TfdR3G3B2.Create;
3188 fFormat := tfR3G3B2;
3189 fWithAlpha := tfRGBA2;
3190 fWithoutAlpha := tfR3G3B2;
3197 fglFormat := GL_RGB;
3198 fglInternalFormat := GL_R3_G3_B2;
3199 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3202 constructor TfdRGB4.Create;
3206 fWithAlpha := tfRGBA4;
3207 fWithoutAlpha := tfRGB4;
3208 fRGBInverted := tfBGR4;
3215 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3216 fglInternalFormat := GL_RGB4;
3217 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3220 constructor TfdR5G6B5.Create;
3223 fFormat := tfR5G6B5;
3224 fWithAlpha := tfRGBA4;
3225 fWithoutAlpha := tfR5G6B5;
3226 fRGBInverted := tfB5G6R5;
3233 fglFormat := GL_RGB;
3234 fglInternalFormat := GL_RGB565;
3235 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3238 constructor TfdRGB5.Create;
3242 fWithAlpha := tfRGB5A1;
3243 fWithoutAlpha := tfRGB5;
3244 fRGBInverted := tfBGR5;
3251 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3252 fglInternalFormat := GL_RGB5;
3253 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3256 constructor TfdRGB8.Create;
3260 fWithAlpha := tfRGBA8;
3261 fWithoutAlpha := tfRGB8;
3262 fRGBInverted := tfBGR8;
3263 fglInternalFormat := GL_RGB8;
3266 constructor TfdRGB10.Create;
3270 fWithAlpha := tfRGB10A2;
3271 fWithoutAlpha := tfRGB10;
3272 fRGBInverted := tfBGR10;
3279 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3280 fglInternalFormat := GL_RGB10;
3281 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3284 constructor TfdRGB12.Create;
3288 fWithAlpha := tfRGBA12;
3289 fWithoutAlpha := tfRGB12;
3290 fRGBInverted := tfBGR12;
3291 fglInternalFormat := GL_RGB12;
3294 constructor TfdRGB16.Create;
3298 fWithAlpha := tfRGBA16;
3299 fWithoutAlpha := tfRGB16;
3300 fRGBInverted := tfBGR16;
3301 fglInternalFormat := GL_RGB16;
3304 constructor TfdRGBA2.Create;
3308 fWithAlpha := tfRGBA2;
3309 fWithoutAlpha := tfR3G3B2;
3310 fRGBInverted := tfBGRA2;
3311 fglInternalFormat := GL_RGBA2;
3314 constructor TfdRGBA4.Create;
3318 fWithAlpha := tfRGBA4;
3319 fWithoutAlpha := tfRGB4;
3320 fRGBInverted := tfBGRA4;
3329 fglFormat := GL_RGBA;
3330 fglInternalFormat := GL_RGBA4;
3331 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3334 constructor TfdRGB5A1.Create;
3337 fFormat := tfRGB5A1;
3338 fWithAlpha := tfRGB5A1;
3339 fWithoutAlpha := tfRGB5;
3340 fRGBInverted := tfBGR5A1;
3349 fglFormat := GL_RGBA;
3350 fglInternalFormat := GL_RGB5_A1;
3351 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3354 constructor TfdRGBA8.Create;
3358 fWithAlpha := tfRGBA8;
3359 fWithoutAlpha := tfRGB8;
3360 fRGBInverted := tfBGRA8;
3361 fglInternalFormat := GL_RGBA8;
3364 constructor TfdRGB10A2.Create;
3367 fFormat := tfRGB10A2;
3368 fWithAlpha := tfRGB10A2;
3369 fWithoutAlpha := tfRGB10;
3370 fRGBInverted := tfBGR10A2;
3379 fglFormat := GL_RGBA;
3380 fglInternalFormat := GL_RGB10_A2;
3381 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3384 constructor TfdRGBA12.Create;
3387 fFormat := tfRGBA12;
3388 fWithAlpha := tfRGBA12;
3389 fWithoutAlpha := tfRGB12;
3390 fRGBInverted := tfBGRA12;
3391 fglInternalFormat := GL_RGBA12;
3394 constructor TfdRGBA16.Create;
3397 fFormat := tfRGBA16;
3398 fWithAlpha := tfRGBA16;
3399 fWithoutAlpha := tfRGB16;
3400 fRGBInverted := tfBGRA16;
3401 fglInternalFormat := GL_RGBA16;
3404 constructor TfdBGR4.Create;
3409 fWithAlpha := tfBGRA4;
3410 fWithoutAlpha := tfBGR4;
3411 fRGBInverted := tfRGB4;
3420 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3421 fglInternalFormat := GL_RGB4;
3422 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3426 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3428 constructor TfdB5G6R5.Create;
3431 fFormat := tfB5G6R5;
3432 fWithAlpha := tfBGRA4;
3433 fWithoutAlpha := tfB5G6R5;
3434 fRGBInverted := tfR5G6B5;
3441 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3442 fglInternalFormat := GL_RGB8;
3443 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3446 constructor TfdBGR5.Create;
3451 fWithAlpha := tfBGR5A1;
3452 fWithoutAlpha := tfBGR5;
3453 fRGBInverted := tfRGB5;
3462 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3463 fglInternalFormat := GL_RGB5;
3464 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3467 constructor TfdBGR8.Create;
3471 fWithAlpha := tfBGRA8;
3472 fWithoutAlpha := tfBGR8;
3473 fRGBInverted := tfRGB8;
3474 fglInternalFormat := GL_RGB8;
3477 constructor TfdBGR10.Create;
3481 fWithAlpha := tfBGR10A2;
3482 fWithoutAlpha := tfBGR10;
3483 fRGBInverted := tfRGB10;
3492 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3493 fglInternalFormat := GL_RGB10;
3494 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3497 constructor TfdBGR12.Create;
3501 fWithAlpha := tfBGRA12;
3502 fWithoutAlpha := tfBGR12;
3503 fRGBInverted := tfRGB12;
3504 fglInternalFormat := GL_RGB12;
3507 constructor TfdBGR16.Create;
3511 fWithAlpha := tfBGRA16;
3512 fWithoutAlpha := tfBGR16;
3513 fRGBInverted := tfRGB16;
3514 fglInternalFormat := GL_RGB16;
3517 constructor TfdBGRA2.Create;
3521 fWithAlpha := tfBGRA4;
3522 fWithoutAlpha := tfBGR4;
3523 fRGBInverted := tfRGBA2;
3524 fglInternalFormat := GL_RGBA2;
3527 constructor TfdBGRA4.Create;
3531 fWithAlpha := tfBGRA4;
3532 fWithoutAlpha := tfBGR4;
3533 fRGBInverted := tfRGBA4;
3542 fglFormat := GL_BGRA;
3543 fglInternalFormat := GL_RGBA4;
3544 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3547 constructor TfdBGR5A1.Create;
3550 fFormat := tfBGR5A1;
3551 fWithAlpha := tfBGR5A1;
3552 fWithoutAlpha := tfBGR5;
3553 fRGBInverted := tfRGB5A1;
3562 fglFormat := GL_BGRA;
3563 fglInternalFormat := GL_RGB5_A1;
3564 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3567 constructor TfdBGRA8.Create;
3571 fWithAlpha := tfBGRA8;
3572 fWithoutAlpha := tfBGR8;
3573 fRGBInverted := tfRGBA8;
3574 fglInternalFormat := GL_RGBA8;
3577 constructor TfdBGR10A2.Create;
3580 fFormat := tfBGR10A2;
3581 fWithAlpha := tfBGR10A2;
3582 fWithoutAlpha := tfBGR10;
3583 fRGBInverted := tfRGB10A2;
3592 fglFormat := GL_BGRA;
3593 fglInternalFormat := GL_RGB10_A2;
3594 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3597 constructor TfdBGRA12.Create;
3600 fFormat := tfBGRA12;
3601 fWithAlpha := tfBGRA12;
3602 fWithoutAlpha := tfBGR12;
3603 fRGBInverted := tfRGBA12;
3604 fglInternalFormat := GL_RGBA12;
3607 constructor TfdBGRA16.Create;
3610 fFormat := tfBGRA16;
3611 fWithAlpha := tfBGRA16;
3612 fWithoutAlpha := tfBGR16;
3613 fRGBInverted := tfRGBA16;
3614 fglInternalFormat := GL_RGBA16;
3617 constructor TfdDepth16.Create;
3620 fFormat := tfDepth16;
3621 fWithAlpha := tfEmpty;
3622 fWithoutAlpha := tfDepth16;
3623 fglInternalFormat := GL_DEPTH_COMPONENT16;
3626 constructor TfdDepth24.Create;
3629 fFormat := tfDepth24;
3630 fWithAlpha := tfEmpty;
3631 fWithoutAlpha := tfDepth24;
3632 fglInternalFormat := GL_DEPTH_COMPONENT24;
3635 constructor TfdDepth32.Create;
3638 fFormat := tfDepth32;
3639 fWithAlpha := tfEmpty;
3640 fWithoutAlpha := tfDepth32;
3641 fglInternalFormat := GL_DEPTH_COMPONENT32;
3644 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3645 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3646 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3647 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3649 raise EglBitmap.Create('mapping for compressed formats is not supported');
3652 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3654 raise EglBitmap.Create('mapping for compressed formats is not supported');
3657 constructor TfdS3tcDtx1RGBA.Create;
3660 fFormat := tfS3tcDtx1RGBA;
3661 fWithAlpha := tfS3tcDtx1RGBA;
3662 fUncompressed := tfRGB5A1;
3664 fIsCompressed := true;
3665 fglFormat := GL_COMPRESSED_RGBA;
3666 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3667 fglDataFormat := GL_UNSIGNED_BYTE;
3670 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3671 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3672 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3673 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3675 raise EglBitmap.Create('mapping for compressed formats is not supported');
3678 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3680 raise EglBitmap.Create('mapping for compressed formats is not supported');
3683 constructor TfdS3tcDtx3RGBA.Create;
3686 fFormat := tfS3tcDtx3RGBA;
3687 fWithAlpha := tfS3tcDtx3RGBA;
3688 fUncompressed := tfRGBA8;
3690 fIsCompressed := true;
3691 fglFormat := GL_COMPRESSED_RGBA;
3692 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3693 fglDataFormat := GL_UNSIGNED_BYTE;
3696 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3697 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3698 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3699 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3701 raise EglBitmap.Create('mapping for compressed formats is not supported');
3704 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3706 raise EglBitmap.Create('mapping for compressed formats is not supported');
3709 constructor TfdS3tcDtx5RGBA.Create;
3712 fFormat := tfS3tcDtx3RGBA;
3713 fWithAlpha := tfS3tcDtx3RGBA;
3714 fUncompressed := tfRGBA8;
3716 fIsCompressed := true;
3717 fglFormat := GL_COMPRESSED_RGBA;
3718 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3719 fglDataFormat := GL_UNSIGNED_BYTE;
3722 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3723 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3724 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3725 class procedure TFormatDescriptor.Init;
3727 if not Assigned(FormatDescriptorCS) then
3728 FormatDescriptorCS := TCriticalSection.Create;
3731 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3732 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3734 FormatDescriptorCS.Enter;
3736 result := FormatDescriptors[aFormat];
3737 if not Assigned(result) then begin
3738 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3739 FormatDescriptors[aFormat] := result;
3742 FormatDescriptorCS.Leave;
3746 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3747 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3749 result := Get(Get(aFormat).WithAlpha);
3752 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3753 class procedure TFormatDescriptor.Clear;
3757 FormatDescriptorCS.Enter;
3759 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3760 FreeAndNil(FormatDescriptors[f]);
3762 FormatDescriptorCS.Leave;
3766 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3767 class procedure TFormatDescriptor.Finalize;
3770 FreeAndNil(FormatDescriptorCS);
3773 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3774 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3775 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3776 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3778 Update(aValue, fRange.r, fShift.r);
3781 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3782 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3784 Update(aValue, fRange.g, fShift.g);
3787 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3788 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3790 Update(aValue, fRange.b, fShift.b);
3793 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3794 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3796 Update(aValue, fRange.a, fShift.a);
3799 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3800 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3807 while (aMask > 0) and ((aMask and 1) = 0) do begin
3809 aMask := aMask shr 1;
3812 while (aMask > 0) do begin
3813 aRange := aRange shl 1;
3814 aMask := aMask shr 1;
3818 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3821 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3822 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3828 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3829 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3830 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3831 ((aPixel.Data.a and fRange.a) shl fShift.a);
3832 s := Round(fPixelSize);
3835 2: PWord(aData)^ := data;
3836 4: PCardinal(aData)^ := data;
3837 8: PQWord(aData)^ := data;
3839 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3844 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3845 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3850 s := Round(fPixelSize);
3853 2: data := PWord(aData)^;
3854 4: data := PCardinal(aData)^;
3855 8: data := PQWord(aData)^;
3857 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3860 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3864 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3865 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3866 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3867 procedure TbmpColorTableFormat.CreateColorTable;
3871 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3872 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3874 if (Format = tfLuminance4) then
3875 SetLength(fColorTable, 16)
3877 SetLength(fColorTable, 256);
3881 for i := 0 to High(fColorTable) do begin
3882 fColorTable[i].r := 16 * i;
3883 fColorTable[i].g := 16 * i;
3884 fColorTable[i].b := 16 * i;
3885 fColorTable[i].a := 0;
3890 for i := 0 to High(fColorTable) do begin
3891 fColorTable[i].r := i;
3892 fColorTable[i].g := i;
3893 fColorTable[i].b := i;
3894 fColorTable[i].a := 0;
3899 for i := 0 to High(fColorTable) do begin
3900 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3901 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3902 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3903 fColorTable[i].a := 0;
3909 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3910 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3914 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3915 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3919 if (aMapData = nil) then
3921 d := LuminanceWeight(aPixel) and Range.r;
3922 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3923 inc(PByte(aMapData), 4);
3924 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3931 aData^ := LuminanceWeight(aPixel) and Range.r;
3937 ((aPixel.Data.r and Range.r) shl Shift.r) or
3938 ((aPixel.Data.g and Range.g) shl Shift.g) or
3939 ((aPixel.Data.b and Range.b) shl Shift.b));
3945 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3946 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3953 s := Trunc(fPixelSize);
3954 f := fPixelSize - s;
3955 bits := Round(8 * f);
3957 0: idx := (aData^ shr (8 - bits - {%H-}PtrInt(aMapData))) and ((1 shl bits) - 1);
3959 2: idx := PWord(aData)^;
3960 4: idx := PCardinal(aData)^;
3961 8: idx := PQWord(aData)^;
3963 raise EglBitmap.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3965 if (idx >= Length(fColorTable)) then
3966 raise EglBitmap.CreateFmt('invalid color index: %d', [idx]);
3967 with fColorTable[idx] do begin
3973 inc(PByte(aMapData), bits);
3974 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3976 dec(PByte(aMapData), 8);
3981 destructor TbmpColorTableFormat.Destroy;
3983 SetLength(fColorTable, 0);
3987 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3988 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3989 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3990 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
3994 for i := 0 to 3 do begin
3995 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
3996 if (aSourceFD.Range.arr[i] > 0) then
3997 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
3999 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
4004 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4005 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
4007 with aFuncRec do begin
4008 if (Source.Range.r > 0) then
4009 Dest.Data.r := Source.Data.r;
4010 if (Source.Range.g > 0) then
4011 Dest.Data.g := Source.Data.g;
4012 if (Source.Range.b > 0) then
4013 Dest.Data.b := Source.Data.b;
4014 if (Source.Range.a > 0) then
4015 Dest.Data.a := Source.Data.a;
4019 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4020 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4024 with aFuncRec do begin
4026 if (Source.Range.arr[i] > 0) then
4027 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4032 TShiftData = packed record
4034 0: (r, g, b, a: SmallInt);
4035 1: (arr: array[0..3] of SmallInt);
4037 PShiftData = ^TShiftData;
4039 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4040 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4046 if (Source.Range.arr[i] > 0) then
4047 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4050 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4051 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4053 with aFuncRec do begin
4054 Dest.Data := Source.Data;
4055 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4056 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4057 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4058 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4060 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4061 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4066 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4067 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4071 with aFuncRec do begin
4073 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4077 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4078 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4082 with FuncRec do begin
4083 if (FuncRec.Args = nil) then begin //source has no alpha
4085 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4086 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4087 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4088 Dest.Data.a := Round(Dest.Range.a * Temp);
4090 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4094 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4095 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4097 PglBitmapPixelData = ^TglBitmapPixelData;
4099 with FuncRec do begin
4100 Dest.Data.r := Source.Data.r;
4101 Dest.Data.g := Source.Data.g;
4102 Dest.Data.b := Source.Data.b;
4104 with PglBitmapPixelData(Args)^ do
4105 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4106 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4107 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4110 Dest.Data.a := Dest.Range.a;
4114 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4115 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4117 with FuncRec do begin
4118 Dest.Data.r := Source.Data.r;
4119 Dest.Data.g := Source.Data.g;
4120 Dest.Data.b := Source.Data.b;
4121 Dest.Data.a := PCardinal(Args)^;
4125 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4126 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4129 TRGBPix = array [0..2] of byte;
4133 while aWidth > 0 do begin
4134 Temp := PRGBPix(aData)^[0];
4135 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4136 PRGBPix(aData)^[2] := Temp;
4146 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4147 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4148 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4149 function TglBitmap.GetFormatDesc: TglBitmapFormatDescriptor;
4151 result := TFormatDescriptor.Get(Format);
4154 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4155 function TglBitmap.GetWidth: Integer;
4157 if (ffX in fDimension.Fields) then
4158 result := fDimension.X
4163 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4164 function TglBitmap.GetHeight: Integer;
4166 if (ffY in fDimension.Fields) then
4167 result := fDimension.Y
4172 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4173 function TglBitmap.GetFileWidth: Integer;
4175 result := Max(1, Width);
4178 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4179 function TglBitmap.GetFileHeight: Integer;
4181 result := Max(1, Height);
4184 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4185 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4187 if fCustomData = aValue then
4189 fCustomData := aValue;
4192 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4193 procedure TglBitmap.SetCustomName(const aValue: String);
4195 if fCustomName = aValue then
4197 fCustomName := aValue;
4200 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4201 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4203 if fCustomNameW = aValue then
4205 fCustomNameW := aValue;
4208 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4209 procedure TglBitmap.SetFreeDataOnDestroy(const aValue: Boolean);
4211 if fFreeDataOnDestroy = aValue then
4213 fFreeDataOnDestroy := aValue;
4216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4217 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4219 if fDeleteTextureOnFree = aValue then
4221 fDeleteTextureOnFree := aValue;
4224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4225 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4227 if fFormat = aValue then
4229 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4230 raise EglBitmapUnsupportedFormat.Create(Format);
4231 SetDataPointer(fData, aValue, Width, Height); //be careful, Data could be freed by this method
4234 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4235 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4237 if fFreeDataAfterGenTexture = aValue then
4239 fFreeDataAfterGenTexture := aValue;
4242 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4243 procedure TglBitmap.SetID(const aValue: Cardinal);
4245 if fID = aValue then
4250 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4251 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4253 if fMipMap = aValue then
4258 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4259 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4261 if fTarget = aValue then
4266 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4267 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4269 MaxAnisotropic: Integer;
4271 fAnisotropic := aValue;
4272 if (ID > 0) then begin
4273 if GL_EXT_texture_filter_anisotropic then begin
4274 if fAnisotropic > 0 then begin
4276 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4277 if aValue > MaxAnisotropic then
4278 fAnisotropic := MaxAnisotropic;
4279 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4287 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4288 procedure TglBitmap.CreateID;
4291 glDeleteTextures(1, @fID);
4292 glGenTextures(1, @fID);
4296 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4297 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4299 // Set Up Parameters
4300 SetWrap(fWrapS, fWrapT, fWrapR);
4301 SetFilter(fFilterMin, fFilterMag);
4302 SetAnisotropic(fAnisotropic);
4303 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4305 if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
4306 SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4308 // Mip Maps Generation Mode
4309 aBuildWithGlu := false;
4310 if (MipMap = mmMipmap) then begin
4311 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4312 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4314 aBuildWithGlu := true;
4315 end else if (MipMap = mmMipmapGlu) then
4316 aBuildWithGlu := true;
4319 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4320 procedure TglBitmap.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
4321 const aWidth: Integer; const aHeight: Integer);
4325 if (Data <> aData) then begin
4326 if (Assigned(Data)) then
4331 if not Assigned(fData) then begin
4335 FillChar(fDimension, SizeOf(fDimension), 0);
4336 if aWidth <> -1 then begin
4337 fDimension.Fields := fDimension.Fields + [ffX];
4338 fDimension.X := aWidth;
4341 if aHeight <> -1 then begin
4342 fDimension.Fields := fDimension.Fields + [ffY];
4343 fDimension.Y := aHeight;
4346 s := TFormatDescriptor.Get(aFormat).PixelSize;
4348 fPixelSize := Ceil(s);
4349 fRowSize := Ceil(s * aWidth);
4353 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4354 function TglBitmap.FlipHorz: Boolean;
4359 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4360 function TglBitmap.FlipVert: Boolean;
4365 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4366 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4367 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4368 procedure TglBitmap.AfterConstruction;
4370 inherited AfterConstruction;
4374 fIsResident := false;
4376 fMipMap := glBitmapDefaultMipmap;
4377 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4378 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4380 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4381 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4382 glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4385 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4386 procedure TglBitmap.BeforeDestruction;
4390 if fFreeDataOnDestroy then begin
4392 SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
4394 if (fID > 0) and fDeleteTextureOnFree then
4395 glDeleteTextures(1, @fID);
4396 inherited BeforeDestruction;
4399 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4400 procedure TglBitmap.PrepareResType(var aResource: String; var aResType: PChar);
4404 if not Assigned(aResType) then begin
4405 TempPos := Pos('.', aResource);
4406 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4407 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4411 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4412 procedure TglBitmap.LoadFromFile(const aFilename: String);
4416 if not FileExists(aFilename) then
4417 raise EglBitmap.Create('file does not exist: ' + aFilename);
4418 fFilename := aFilename;
4419 fs := TFileStream.Create(fFilename, fmOpenRead);
4428 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4429 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4431 {$IFDEF GLB_SUPPORT_PNG_READ}
4432 if not LoadPNG(aStream) then
4434 {$IFDEF GLB_SUPPORT_JPEG_READ}
4435 if not LoadJPEG(aStream) then
4437 if not LoadDDS(aStream) then
4438 if not LoadTGA(aStream) then
4439 if not LoadBMP(aStream) then
4440 raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4443 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4444 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4445 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4450 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4451 GetMem(tmpData, size);
4453 FillChar(tmpData^, size, #$FF);
4454 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
4456 if Assigned(tmpData) then
4460 AddFunc(Self, aFunc, false, aFormat, aArgs);
4463 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4464 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
4466 rs: TResourceStream;
4468 PrepareResType(aResource, aResType);
4469 rs := TResourceStream.Create(aInstance, aResource, aResType);
4477 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4478 procedure TglBitmap.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4480 rs: TResourceStream;
4482 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
4490 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4491 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4495 fs := TFileStream.Create(aFileName, fmCreate);
4498 SaveToStream(fs, aFileType);
4504 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4505 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4508 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4509 ftPNG: SavePNG(aStream);
4511 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4512 ftJPEG: SaveJPEG(aStream);
4514 ftDDS: SaveDDS(aStream);
4515 ftTGA: SaveTGA(aStream);
4516 ftBMP: SaveBMP(aStream);
4520 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4521 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4523 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4526 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4527 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4528 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4530 DestData, TmpData, SourceData: pByte;
4531 TempHeight, TempWidth: Integer;
4532 SourceFD, DestFD: TFormatDescriptor;
4533 SourceMD, DestMD: Pointer;
4535 FuncRec: TglBitmapFunctionRec;
4537 Assert(Assigned(Data));
4538 Assert(Assigned(aSource));
4539 Assert(Assigned(aSource.Data));
4542 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4543 SourceFD := TFormatDescriptor.Get(aSource.Format);
4544 DestFD := TFormatDescriptor.Get(aFormat);
4546 if (SourceFD.IsCompressed) then
4547 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
4548 if (DestFD.IsCompressed) then
4549 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
4551 // inkompatible Formats so CreateTemp
4552 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4553 aCreateTemp := true;
4556 TempHeight := Max(1, aSource.Height);
4557 TempWidth := Max(1, aSource.Width);
4559 FuncRec.Sender := Self;
4560 FuncRec.Args := aArgs;
4563 if aCreateTemp then begin
4564 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
4565 DestData := TmpData;
4570 SourceFD.PreparePixel(FuncRec.Source);
4571 DestFD.PreparePixel (FuncRec.Dest);
4573 SourceMD := SourceFD.CreateMappingData;
4574 DestMD := DestFD.CreateMappingData;
4576 FuncRec.Size := aSource.Dimension;
4577 FuncRec.Position.Fields := FuncRec.Size.Fields;
4580 SourceData := aSource.Data;
4581 FuncRec.Position.Y := 0;
4582 while FuncRec.Position.Y < TempHeight do begin
4583 FuncRec.Position.X := 0;
4584 while FuncRec.Position.X < TempWidth do begin
4585 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4587 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4588 inc(FuncRec.Position.X);
4590 inc(FuncRec.Position.Y);
4593 // Updating Image or InternalFormat
4595 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) //be careful, Data could be freed by this method
4596 else if (aFormat <> fFormat) then
4601 SourceFD.FreeMappingData(SourceMD);
4602 DestFD.FreeMappingData(DestMD);
4605 if aCreateTemp and Assigned(TmpData) then
4613 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4614 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4616 Row, RowSize: Integer;
4617 SourceData, TmpData: PByte;
4619 FormatDesc: TFormatDescriptor;
4621 function GetRowPointer(Row: Integer): pByte;
4623 result := aSurface.pixels;
4624 Inc(result, Row * RowSize);
4630 FormatDesc := TFormatDescriptor.Get(Format);
4631 if FormatDesc.IsCompressed then
4632 raise EglBitmapUnsupportedFormat.Create(Format);
4634 if Assigned(Data) then begin
4635 case Trunc(FormatDesc.PixelSize) of
4641 raise EglBitmapUnsupportedFormat.Create(Format);
4644 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4645 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4647 RowSize := FormatDesc.GetSize(FileWidth, 1);
4649 for Row := 0 to FileHeight-1 do begin
4650 TmpData := GetRowPointer(Row);
4651 if Assigned(TmpData) then begin
4652 Move(SourceData^, TmpData^, RowSize);
4653 inc(SourceData, RowSize);
4660 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4661 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4663 pSource, pData, pTempData: PByte;
4664 Row, RowSize, TempWidth, TempHeight: Integer;
4665 IntFormat: TglBitmapFormat;
4666 FormatDesc: TFormatDescriptor;
4668 function GetRowPointer(Row: Integer): pByte;
4670 result := aSurface^.pixels;
4671 Inc(result, Row * RowSize);
4676 if (Assigned(aSurface)) then begin
4677 with aSurface^.format^ do begin
4678 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4679 FormatDesc := TFormatDescriptor.Get(IntFormat);
4680 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4683 if (IntFormat = tfEmpty) then
4684 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4687 TempWidth := aSurface^.w;
4688 TempHeight := aSurface^.h;
4689 RowSize := FormatDesc.GetSize(TempWidth, 1);
4690 GetMem(pData, TempHeight * RowSize);
4693 for Row := 0 to TempHeight -1 do begin
4694 pSource := GetRowPointer(Row);
4695 if (Assigned(pSource)) then begin
4696 Move(pSource^, pTempData^, RowSize);
4697 Inc(pTempData, RowSize);
4700 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4703 if Assigned(pData) then
4710 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4711 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4713 Row, Col, AlphaInterleave: Integer;
4714 pSource, pDest: PByte;
4716 function GetRowPointer(Row: Integer): pByte;
4718 result := aSurface.pixels;
4719 Inc(result, Row * Width);
4724 if Assigned(Data) then begin
4725 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4726 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4728 AlphaInterleave := 0;
4731 AlphaInterleave := 1;
4733 AlphaInterleave := 3;
4737 for Row := 0 to Height -1 do begin
4738 pDest := GetRowPointer(Row);
4739 if Assigned(pDest) then begin
4740 for Col := 0 to Width -1 do begin
4741 Inc(pSource, AlphaInterleave);
4753 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4754 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4758 bmp := TglBitmap2D.Create;
4760 bmp.AssignFromSurface(aSurface);
4761 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4769 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4770 function CreateGrayPalette: HPALETTE;
4775 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
4777 Pal.palVersion := $300;
4778 Pal.palNumEntries := 256;
4780 for Idx := 0 to Pal.palNumEntries - 1 do begin
4781 Pal.palPalEntry[Idx].peRed := Idx;
4782 Pal.palPalEntry[Idx].peGreen := Idx;
4783 Pal.palPalEntry[Idx].peBlue := Idx;
4784 Pal.palPalEntry[Idx].peFlags := 0;
4786 Result := CreatePalette(Pal^);
4790 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4791 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4794 pSource, pData: PByte;
4797 if Assigned(Data) then begin
4798 if Assigned(aBitmap) then begin
4799 aBitmap.Width := Width;
4800 aBitmap.Height := Height;
4803 tfAlpha8, tfLuminance8: begin
4804 aBitmap.PixelFormat := pf8bit;
4805 aBitmap.Palette := CreateGrayPalette;
4808 aBitmap.PixelFormat := pf15bit;
4810 aBitmap.PixelFormat := pf16bit;
4812 aBitmap.PixelFormat := pf24bit;
4814 aBitmap.PixelFormat := pf32bit;
4816 raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.');
4820 for Row := 0 to FileHeight -1 do begin
4821 pData := aBitmap.Scanline[Row];
4822 Move(pSource^, pData^, fRowSize);
4823 Inc(pSource, fRowSize);
4824 if (Format in [tfRGB8, tfRGBA8]) then // swap RGB(A) to BGR(A)
4825 SwapRGB(pData, FileWidth, Format = tfRGBA8);
4832 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4833 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4835 pSource, pData, pTempData: PByte;
4836 Row, RowSize, TempWidth, TempHeight: Integer;
4837 IntFormat: TglBitmapFormat;
4841 if (Assigned(aBitmap)) then begin
4842 case aBitmap.PixelFormat of
4844 IntFormat := tfLuminance8;
4846 IntFormat := tfRGB5A1;
4848 IntFormat := tfR5G6B5;
4850 IntFormat := tfBGR8;
4852 IntFormat := tfBGRA8;
4854 raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.');
4857 TempWidth := aBitmap.Width;
4858 TempHeight := aBitmap.Height;
4859 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
4860 GetMem(pData, TempHeight * RowSize);
4863 for Row := 0 to TempHeight -1 do begin
4864 pSource := aBitmap.Scanline[Row];
4865 if (Assigned(pSource)) then begin
4866 Move(pSource^, pTempData^, RowSize);
4867 Inc(pTempData, RowSize);
4870 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4873 if Assigned(pData) then
4880 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4881 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4883 Row, Col, AlphaInterleave: Integer;
4884 pSource, pDest: PByte;
4888 if Assigned(Data) then begin
4889 if (Format in [tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8]) then begin
4890 if Assigned(aBitmap) then begin
4891 aBitmap.PixelFormat := pf8bit;
4892 aBitmap.Palette := CreateGrayPalette;
4893 aBitmap.Width := Width;
4894 aBitmap.Height := Height;
4898 AlphaInterleave := 1;
4900 AlphaInterleave := 3;
4902 AlphaInterleave := 0;
4908 for Row := 0 to Height -1 do begin
4909 pDest := aBitmap.Scanline[Row];
4910 if Assigned(pDest) then begin
4911 for Col := 0 to Width -1 do begin
4912 Inc(pSource, AlphaInterleave);
4925 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4926 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4930 tex := TglBitmap2D.Create;
4932 tex.AssignFromBitmap(ABitmap);
4933 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4940 {$IFDEF GLB_LAZARUS}
4941 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4942 function TglBitmap.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4944 rid: TRawImageDescription;
4945 FormatDesc: TFormatDescriptor;
4948 if not Assigned(aImage) or (Format = tfEmpty) then
4950 FormatDesc := TFormatDescriptor.Get(Format);
4951 if FormatDesc.IsCompressed then
4954 FillChar(rid{%H-}, SizeOf(rid), 0);
4956 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
4957 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
4958 tfLuminance4Alpha4, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16]) then
4959 rid.Format := ricfGray
4961 rid.Format := ricfRGBA;
4964 rid.Height := Height;
4965 rid.Depth := CountSetBits(FormatDesc.RedMask or FormatDesc.GreenMask or FormatDesc.BlueMask or FormatDesc.AlphaMask);
4966 rid.BitOrder := riboBitsInOrder;
4967 rid.ByteOrder := riboLSBFirst;
4968 rid.LineOrder := riloTopToBottom;
4969 rid.LineEnd := rileTight;
4970 rid.BitsPerPixel := Round(8 * FormatDesc.PixelSize);
4971 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
4972 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
4973 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
4974 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
4975 rid.RedShift := FormatDesc.Shift.r;
4976 rid.GreenShift := FormatDesc.Shift.g;
4977 rid.BlueShift := FormatDesc.Shift.b;
4978 rid.AlphaShift := FormatDesc.Shift.a;
4980 rid.MaskBitsPerPixel := 0;
4981 rid.PaletteColorCount := 0;
4983 aImage.DataDescription := rid;
4986 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
4991 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4992 function TglBitmap.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
4995 FormatDesc: TFormatDescriptor;
5000 procedure CopyConvert;
5002 bfFormat: TbmpBitfieldFormat;
5003 pSourceLine, pDestLine: PByte;
5004 pSourceMD, pDestMD: Pointer;
5006 pixel: TglBitmapPixelData;
5008 bfFormat := TbmpBitfieldFormat.Create;
5009 with aImage.DataDescription do begin
5010 bfFormat.RedMask := ((1 shl RedPrec) - 1) shl RedShift;
5011 bfFormat.GreenMask := ((1 shl GreenPrec) - 1) shl GreenShift;
5012 bfFormat.BlueMask := ((1 shl BluePrec) - 1) shl BlueShift;
5013 bfFormat.AlphaMask := ((1 shl AlphaPrec) - 1) shl AlphaShift;
5014 bfFormat.PixelSize := BitsPerPixel / 8;
5016 pSourceMD := bfFormat.CreateMappingData;
5017 pDestMD := FormatDesc.CreateMappingData;
5019 for y := 0 to aImage.Height-1 do begin
5020 pSourceLine := aImage.PixelData + y * aImage.DataDescription.BytesPerLine;
5021 pDestLine := ImageData + y * Round(FormatDesc.PixelSize * aImage.Width);
5022 for x := 0 to aImage.Width-1 do begin
5023 bfFormat.Unmap(pSourceLine, pixel, pSourceMD);
5024 FormatDesc.Map(pixel, pDestLine, pDestMD);
5028 FormatDesc.FreeMappingData(pDestMD);
5029 bfFormat.FreeMappingData(pSourceMD);
5036 if not Assigned(aImage) then
5038 for f := High(f) downto Low(f) do begin
5039 FormatDesc := TFormatDescriptor.Get(f);
5040 with aImage.DataDescription do
5041 if FormatDesc.MaskMatch(
5042 (QWord(1 shl RedPrec )-1) shl RedShift,
5043 (QWord(1 shl GreenPrec)-1) shl GreenShift,
5044 (QWord(1 shl BluePrec )-1) shl BlueShift,
5045 (QWord(1 shl AlphaPrec)-1) shl AlphaShift) then
5049 if (f = tfEmpty) then
5053 (Round(FormatDesc.PixelSize * 8) = aImage.DataDescription.Depth) and
5054 (aImage.DataDescription.BitsPerPixel = aImage.DataDescription.Depth);
5056 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
5057 ImageData := GetMem(ImageSize);
5060 Move(aImage.PixelData^, ImageData^, ImageSize)
5063 SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method
5065 if Assigned(ImageData) then
5073 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5074 function TglBitmap.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
5076 rid: TRawImageDescription;
5077 FormatDesc: TFormatDescriptor;
5078 Pixel: TglBitmapPixelData;
5084 if not Assigned(aImage) or (Format = tfEmpty) then
5086 FormatDesc := TFormatDescriptor.Get(Format);
5087 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5090 FillChar(rid{%H-}, SizeOf(rid), 0);
5091 rid.Format := ricfGray;
5093 rid.Height := Height;
5094 rid.Depth := CountSetBits(FormatDesc.Range.a);
5095 rid.BitOrder := riboBitsInOrder;
5096 rid.ByteOrder := riboLSBFirst;
5097 rid.LineOrder := riloTopToBottom;
5098 rid.LineEnd := rileTight;
5099 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
5100 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
5105 rid.GreenShift := 0;
5107 rid.AlphaShift := 0;
5109 rid.MaskBitsPerPixel := 0;
5110 rid.PaletteColorCount := 0;
5112 aImage.DataDescription := rid;
5115 srcMD := FormatDesc.CreateMappingData;
5117 FormatDesc.PreparePixel(Pixel);
5119 dst := aImage.PixelData;
5120 for y := 0 to Height-1 do
5121 for x := 0 to Width-1 do begin
5122 FormatDesc.Unmap(src, Pixel, srcMD);
5123 case rid.BitsPerPixel of
5125 dst^ := Pixel.Data.a;
5129 PWord(dst)^ := Pixel.Data.a;
5133 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
5134 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
5135 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
5139 PCardinal(dst)^ := Pixel.Data.a;
5143 raise EglBitmapUnsupportedFormat.Create(Format);
5147 FormatDesc.FreeMappingData(srcMD);
5152 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5153 function TglBitmap.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5157 tex := TglBitmap2D.Create;
5159 tex.AssignFromLazIntfImage(aImage);
5160 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5167 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5168 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
5169 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5171 rs: TResourceStream;
5173 PrepareResType(aResource, aResType);
5174 rs := TResourceStream.Create(aInstance, aResource, aResType);
5176 result := AddAlphaFromStream(rs, aFunc, aArgs);
5182 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5183 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
5184 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5186 rs: TResourceStream;
5188 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
5190 result := AddAlphaFromStream(rs, aFunc, aArgs);
5196 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5197 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5199 if TFormatDescriptor.Get(Format).IsCompressed then
5200 raise EglBitmapUnsupportedFormat.Create(Format);
5201 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
5204 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5205 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5209 FS := TFileStream.Create(aFileName, fmOpenRead);
5211 result := AddAlphaFromStream(FS, aFunc, aArgs);
5217 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5218 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5222 tex := TglBitmap2D.Create(aStream);
5224 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5230 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5231 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5233 DestData, DestData2, SourceData: pByte;
5234 TempHeight, TempWidth: Integer;
5235 SourceFD, DestFD: TFormatDescriptor;
5236 SourceMD, DestMD, DestMD2: Pointer;
5238 FuncRec: TglBitmapFunctionRec;
5242 Assert(Assigned(Data));
5243 Assert(Assigned(aBitmap));
5244 Assert(Assigned(aBitmap.Data));
5246 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
5247 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
5249 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
5250 DestFD := TFormatDescriptor.Get(Format);
5252 if not Assigned(aFunc) then begin
5253 aFunc := glBitmapAlphaFunc;
5254 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5256 FuncRec.Args := aArgs;
5259 TempHeight := aBitmap.FileHeight;
5260 TempWidth := aBitmap.FileWidth;
5262 FuncRec.Sender := Self;
5263 FuncRec.Size := Dimension;
5264 FuncRec.Position.Fields := FuncRec.Size.Fields;
5268 SourceData := aBitmap.Data;
5271 SourceFD.PreparePixel(FuncRec.Source);
5272 DestFD.PreparePixel (FuncRec.Dest);
5274 SourceMD := SourceFD.CreateMappingData;
5275 DestMD := DestFD.CreateMappingData;
5276 DestMD2 := DestFD.CreateMappingData;
5278 FuncRec.Position.Y := 0;
5279 while FuncRec.Position.Y < TempHeight do begin
5280 FuncRec.Position.X := 0;
5281 while FuncRec.Position.X < TempWidth do begin
5282 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5283 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5285 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5286 inc(FuncRec.Position.X);
5288 inc(FuncRec.Position.Y);
5291 SourceFD.FreeMappingData(SourceMD);
5292 DestFD.FreeMappingData(DestMD);
5293 DestFD.FreeMappingData(DestMD2);
5298 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5299 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5301 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5304 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5305 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5307 PixelData: TglBitmapPixelData;
5309 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5310 result := AddAlphaFromColorKeyFloat(
5311 aRed / PixelData.Range.r,
5312 aGreen / PixelData.Range.g,
5313 aBlue / PixelData.Range.b,
5314 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5317 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5318 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5320 values: array[0..2] of Single;
5323 PixelData: TglBitmapPixelData;
5325 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5326 with PixelData do begin
5328 values[1] := aGreen;
5331 for i := 0 to 2 do begin
5332 tmp := Trunc(Range.arr[i] * aDeviation);
5333 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5334 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5339 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5342 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5343 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5345 result := AddAlphaFromValueFloat(aAlpha / $FF);
5348 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5349 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5351 PixelData: TglBitmapPixelData;
5353 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5354 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5357 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5358 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5360 PixelData: TglBitmapPixelData;
5362 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5364 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5365 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5368 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5369 function TglBitmap.RemoveAlpha: Boolean;
5371 FormatDesc: TFormatDescriptor;
5374 FormatDesc := TFormatDescriptor.Get(Format);
5375 if Assigned(Data) then begin
5376 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5377 raise EglBitmapUnsupportedFormat.Create(Format);
5378 result := ConvertTo(FormatDesc.WithoutAlpha);
5382 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5383 function TglBitmap.Clone: TglBitmap;
5389 Temp := (ClassType.Create as TglBitmap);
5391 // copy texture data if assigned
5392 if Assigned(Data) then begin
5393 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5394 GetMem(TempPtr, Size);
5396 Move(Data^, TempPtr^, Size);
5397 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5399 if Assigned(TempPtr) then
5405 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5410 Temp.fTarget := Target;
5411 Temp.fFormat := Format;
5412 Temp.fMipMap := MipMap;
5413 Temp.fAnisotropic := Anisotropic;
5414 Temp.fBorderColor := fBorderColor;
5415 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5416 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5417 Temp.fFilterMin := fFilterMin;
5418 Temp.fFilterMag := fFilterMag;
5419 Temp.fWrapS := fWrapS;
5420 Temp.fWrapT := fWrapT;
5421 Temp.fWrapR := fWrapR;
5422 Temp.fFilename := fFilename;
5423 Temp.fCustomName := fCustomName;
5424 Temp.fCustomNameW := fCustomNameW;
5425 Temp.fCustomData := fCustomData;
5434 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5435 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5437 SourceFD, DestFD: TFormatDescriptor;
5438 SourcePD, DestPD: TglBitmapPixelData;
5439 ShiftData: TShiftData;
5441 function CanCopyDirect: Boolean;
5444 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5445 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5446 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5447 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5450 function CanShift: Boolean;
5453 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5454 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5455 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5456 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5459 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5462 while (aSource > aDest) and (aSource > 0) do begin
5464 aSource := aSource shr 1;
5469 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5470 SourceFD := TFormatDescriptor.Get(Format);
5471 DestFD := TFormatDescriptor.Get(aFormat);
5473 SourceFD.PreparePixel(SourcePD);
5474 DestFD.PreparePixel (DestPD);
5476 if CanCopyDirect then
5477 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5478 else if CanShift then begin
5479 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5480 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5481 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5482 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5483 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5485 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5490 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5491 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5493 if aUseRGB or aUseAlpha then
5494 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5495 ((Byte(aUseAlpha) and 1) shl 1) or
5496 (Byte(aUseRGB) and 1) ));
5499 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5500 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5502 fBorderColor[0] := aRed;
5503 fBorderColor[1] := aGreen;
5504 fBorderColor[2] := aBlue;
5505 fBorderColor[3] := aAlpha;
5506 if (ID > 0) then begin
5508 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5512 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5513 procedure TglBitmap.FreeData;
5518 SetDataPointer(TempPtr, tfEmpty); //be careful, Data could be freed by this method
5521 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5522 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5523 const aAlpha: Byte);
5525 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5528 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5529 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5531 PixelData: TglBitmapPixelData;
5533 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5535 aRed / PixelData.Range.r,
5536 aGreen / PixelData.Range.g,
5537 aBlue / PixelData.Range.b,
5538 aAlpha / PixelData.Range.a);
5541 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5542 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5544 PixelData: TglBitmapPixelData;
5546 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5547 with PixelData do begin
5548 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5549 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5550 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5551 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5553 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5556 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5557 procedure TglBitmap.SetFilter(const aMin, aMag: GLenum);
5562 fFilterMin := GL_NEAREST;
5564 fFilterMin := GL_LINEAR;
5565 GL_NEAREST_MIPMAP_NEAREST:
5566 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5567 GL_LINEAR_MIPMAP_NEAREST:
5568 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5569 GL_NEAREST_MIPMAP_LINEAR:
5570 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5571 GL_LINEAR_MIPMAP_LINEAR:
5572 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5574 raise EglBitmap.Create('SetFilter - Unknow MIN filter.');
5580 fFilterMag := GL_NEAREST;
5582 fFilterMag := GL_LINEAR;
5584 raise EglBitmap.Create('SetFilter - Unknow MAG filter.');
5588 if (ID > 0) then begin
5590 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5592 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5594 GL_NEAREST, GL_LINEAR:
5595 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5596 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5597 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5598 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5599 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5602 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5606 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5607 procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum);
5609 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5613 aTarget := GL_CLAMP;
5616 aTarget := GL_REPEAT;
5618 GL_CLAMP_TO_EDGE: begin
5619 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5620 aTarget := GL_CLAMP_TO_EDGE
5622 aTarget := GL_CLAMP;
5625 GL_CLAMP_TO_BORDER: begin
5626 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5627 aTarget := GL_CLAMP_TO_BORDER
5629 aTarget := GL_CLAMP;
5632 GL_MIRRORED_REPEAT: begin
5633 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5634 aTarget := GL_MIRRORED_REPEAT
5636 raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5639 raise EglBitmap.Create('SetWrap - Unknow Texturewrap');
5644 CheckAndSetWrap(S, fWrapS);
5645 CheckAndSetWrap(T, fWrapT);
5646 CheckAndSetWrap(R, fWrapR);
5648 if (ID > 0) then begin
5650 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5651 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5652 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5656 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5657 procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum);
5659 procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer);
5661 if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or
5662 (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then
5663 fSwizzle[aIndex] := aValue
5665 raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value');
5669 if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
5670 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
5671 CheckAndSetValue(r, 0);
5672 CheckAndSetValue(g, 1);
5673 CheckAndSetValue(b, 2);
5674 CheckAndSetValue(a, 3);
5676 if (ID > 0) then begin
5678 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, PGLint(@fSwizzle[0]));
5682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5683 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5685 if aEnableTextureUnit then
5688 glBindTexture(Target, ID);
5691 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5692 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5694 if aDisableTextureUnit then
5696 glBindTexture(Target, 0);
5699 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5700 constructor TglBitmap.Create;
5702 if (ClassType = TglBitmap) then
5703 raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5704 {$IFDEF GLB_NATIVE_OGL}
5705 glbReadOpenGLExtensions;
5708 fFormat := glBitmapGetDefaultFormat;
5709 fFreeDataOnDestroy := true;
5712 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5713 constructor TglBitmap.Create(const aFileName: String);
5716 LoadFromFile(aFileName);
5719 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5720 constructor TglBitmap.Create(const aStream: TStream);
5723 LoadFromStream(aStream);
5726 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5727 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte);
5732 if not Assigned(aData) then begin
5733 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5734 GetMem(aData, ImageSize);
5736 FillChar(aData^, ImageSize, #$FF);
5737 SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5739 if Assigned(aData) then
5744 SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5745 fFreeDataOnDestroy := false;
5749 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5750 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer);
5753 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5756 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5757 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5760 LoadFromResource(aInstance, aResource, aResType);
5763 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5764 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5767 LoadFromResourceID(aInstance, aResourceID, aResType);
5770 {$IFDEF GLB_SUPPORT_PNG_READ}
5771 {$IF DEFINED(GLB_LAZ_PNG)}
5772 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5773 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5774 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5775 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5778 PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A;
5780 reader: TLazReaderPNG;
5781 intf: TLazIntfImage;
5783 magic: String[MAGIC_LEN];
5786 StreamPos := aStream.Position;
5788 SetLength(magic, MAGIC_LEN);
5789 aStream.Read(magic[1], MAGIC_LEN);
5790 aStream.Position := StreamPos;
5791 if (magic <> PNG_MAGIC) then begin
5796 intf := TLazIntfImage.Create(0, 0);
5797 reader := TLazReaderPNG.Create;
5799 reader.UpdateDescription := true;
5800 reader.ImageRead(aStream, intf);
5801 AssignFromLazIntfImage(intf);
5804 aStream.Position := StreamPos;
5813 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
5814 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5815 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5817 Surface: PSDL_Surface;
5821 RWops := glBitmapCreateRWops(aStream);
5823 if IMG_isPNG(RWops) > 0 then begin
5824 Surface := IMG_LoadPNG_RW(RWops);
5826 AssignFromSurface(Surface);
5829 SDL_FreeSurface(Surface);
5837 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5838 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5839 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5841 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5844 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5845 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5848 signature: array [0..7] of byte;
5850 png_info: png_infop;
5852 TempHeight, TempWidth: Integer;
5853 Format: TglBitmapFormat;
5856 png_rows: array of pByte;
5857 Row, LineSize: Integer;
5861 if not init_libPNG then
5862 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5866 StreamPos := aStream.Position;
5867 aStream.Read(signature{%H-}, 8);
5868 aStream.Position := StreamPos;
5870 if png_check_sig(@signature, 8) <> 0 then begin
5872 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5874 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5877 png_info := png_create_info_struct(png);
5878 if png_info = nil then begin
5879 png_destroy_read_struct(@png, nil, nil);
5880 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5883 // set read callback
5884 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5886 // read informations
5887 png_read_info(png, png_info);
5890 TempHeight := png_get_image_height(png, png_info);
5891 TempWidth := png_get_image_width(png, png_info);
5894 case png_get_color_type(png, png_info) of
5895 PNG_COLOR_TYPE_GRAY:
5896 Format := tfLuminance8;
5897 PNG_COLOR_TYPE_GRAY_ALPHA:
5898 Format := tfLuminance8Alpha8;
5901 PNG_COLOR_TYPE_RGB_ALPHA:
5904 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5907 // cut upper 8 bit from 16 bit formats
5908 if png_get_bit_depth(png, png_info) > 8 then
5909 png_set_strip_16(png);
5911 // expand bitdepth smaller than 8
5912 if png_get_bit_depth(png, png_info) < 8 then
5913 png_set_expand(png);
5915 // allocating mem for scanlines
5916 LineSize := png_get_rowbytes(png, png_info);
5917 GetMem(png_data, TempHeight * LineSize);
5919 SetLength(png_rows, TempHeight);
5920 for Row := Low(png_rows) to High(png_rows) do begin
5921 png_rows[Row] := png_data;
5922 Inc(png_rows[Row], Row * LineSize);
5925 // read complete image into scanlines
5926 png_read_image(png, @png_rows[0]);
5929 png_read_end(png, png_info);
5931 // destroy read struct
5932 png_destroy_read_struct(@png, @png_info, nil);
5934 SetLength(png_rows, 0);
5937 SetDataPointer(png_data, Format, TempWidth, TempHeight); //be careful, Data could be freed by this method
5941 if Assigned(png_data) then
5951 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5952 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5953 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5958 Row, Col, PixSize, LineSize: Integer;
5959 NewImage, pSource, pDest, pAlpha: pByte;
5960 PngFormat: TglBitmapFormat;
5961 FormatDesc: TFormatDescriptor;
5964 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
5969 StreamPos := aStream.Position;
5970 aStream.Read(Header[0], SizeOf(Header));
5971 aStream.Position := StreamPos;
5973 {Test if the header matches}
5974 if Header = PngHeader then begin
5975 Png := TPNGObject.Create;
5977 Png.LoadFromStream(aStream);
5979 case Png.Header.ColorType of
5981 PngFormat := tfLuminance8;
5982 COLOR_GRAYSCALEALPHA:
5983 PngFormat := tfLuminance8Alpha8;
5985 PngFormat := tfBGR8;
5987 PngFormat := tfBGRA8;
5989 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5992 FormatDesc := TFormatDescriptor.Get(PngFormat);
5993 PixSize := Round(FormatDesc.PixelSize);
5994 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
5996 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
6000 case Png.Header.ColorType of
6001 COLOR_RGB, COLOR_GRAYSCALE:
6003 for Row := 0 to Png.Height -1 do begin
6004 Move (Png.Scanline[Row]^, pDest^, LineSize);
6005 Inc(pDest, LineSize);
6008 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
6010 PixSize := PixSize -1;
6012 for Row := 0 to Png.Height -1 do begin
6013 pSource := Png.Scanline[Row];
6014 pAlpha := pByte(Png.AlphaScanline[Row]);
6016 for Col := 0 to Png.Width -1 do begin
6017 Move (pSource^, pDest^, PixSize);
6018 Inc(pSource, PixSize);
6019 Inc(pDest, PixSize);
6028 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
6031 SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); //be careful, Data could be freed by this method
6035 if Assigned(NewImage) then
6047 {$IFDEF GLB_SUPPORT_PNG_WRITE}
6048 {$IFDEF GLB_LIB_PNG}
6049 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6050 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
6052 TStream(png_get_io_ptr(png)).Write(buffer^, size);
6056 {$IF DEFINED(GLB_LAZ_PNG)}
6057 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6058 procedure TglBitmap.SavePNG(const aStream: TStream);
6060 png: TPortableNetworkGraphic;
6061 intf: TLazIntfImage;
6064 png := TPortableNetworkGraphic.Create;
6065 intf := TLazIntfImage.Create(0, 0);
6067 if not AssignToLazIntfImage(intf) then
6068 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6069 intf.GetRawImage(raw);
6070 png.LoadFromRawImage(raw, false);
6071 png.SaveToStream(aStream);
6078 {$ELSEIF DEFINED(GLB_LIB_PNG)}
6079 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6080 procedure TglBitmap.SavePNG(const aStream: TStream);
6083 png_info: png_infop;
6084 png_rows: array of pByte;
6088 FormatDesc: TFormatDescriptor;
6090 if not (ftPNG in FormatGetSupportedFiles(Format)) then
6091 raise EglBitmapUnsupportedFormat.Create(Format);
6093 if not init_libPNG then
6094 raise Exception.Create('unable to initialize libPNG.');
6098 tfAlpha8, tfLuminance8:
6099 ColorType := PNG_COLOR_TYPE_GRAY;
6101 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
6103 ColorType := PNG_COLOR_TYPE_RGB;
6105 ColorType := PNG_COLOR_TYPE_RGBA;
6107 raise EglBitmapUnsupportedFormat.Create(Format);
6110 FormatDesc := TFormatDescriptor.Get(Format);
6111 LineSize := FormatDesc.GetSize(Width, 1);
6113 // creating array for scanline
6114 SetLength(png_rows, Height);
6116 for Row := 0 to Height - 1 do begin
6117 png_rows[Row] := Data;
6118 Inc(png_rows[Row], Row * LineSize)
6122 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
6124 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
6127 png_info := png_create_info_struct(png);
6128 if png_info = nil then begin
6129 png_destroy_write_struct(@png, nil);
6130 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
6133 // set read callback
6134 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
6137 png_set_compression_level(png, 6);
6139 if Format in [tfBGR8, tfBGRA8] then
6142 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
6143 png_write_info(png, png_info);
6144 png_write_image(png, @png_rows[0]);
6145 png_write_end(png, png_info);
6146 png_destroy_write_struct(@png, @png_info);
6148 SetLength(png_rows, 0);
6155 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
6156 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6157 procedure TglBitmap.SavePNG(const aStream: TStream);
6161 pSource, pDest: pByte;
6162 X, Y, PixSize: Integer;
6163 ColorType: Cardinal;
6169 if not (ftPNG in FormatGetSupportedFiles (Format)) then
6170 raise EglBitmapUnsupportedFormat.Create(Format);
6173 tfAlpha8, tfLuminance8: begin
6174 ColorType := COLOR_GRAYSCALE;
6178 tfLuminance8Alpha8: begin
6179 ColorType := COLOR_GRAYSCALEALPHA;
6183 tfBGR8, tfRGB8: begin
6184 ColorType := COLOR_RGB;
6188 tfBGRA8, tfRGBA8: begin
6189 ColorType := COLOR_RGBALPHA;
6194 raise EglBitmapUnsupportedFormat.Create(Format);
6197 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
6201 for Y := 0 to Height -1 do begin
6202 pDest := png.ScanLine[Y];
6203 for X := 0 to Width -1 do begin
6204 Move(pSource^, pDest^, PixSize);
6205 Inc(pDest, PixSize);
6206 Inc(pSource, PixSize);
6208 png.AlphaScanline[Y]^[X] := pSource^;
6213 // convert RGB line to BGR
6214 if Format in [tfRGB8, tfRGBA8] then begin
6215 pTemp := png.ScanLine[Y];
6216 for X := 0 to Width -1 do begin
6217 Temp := pByteArray(pTemp)^[0];
6218 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
6219 pByteArray(pTemp)^[2] := Temp;
6226 Png.CompressionLevel := 6;
6227 Png.SaveToStream(aStream);
6235 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6236 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6237 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6238 {$IFDEF GLB_LIB_JPEG}
6240 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
6241 glBitmap_libJPEG_source_mgr = record
6242 pub: jpeg_source_mgr;
6245 SrcBuffer: array [1..4096] of byte;
6248 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
6249 glBitmap_libJPEG_dest_mgr = record
6250 pub: jpeg_destination_mgr;
6252 DestStream: TStream;
6253 DestBuffer: array [1..4096] of byte;
6256 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
6262 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
6268 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
6273 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
6279 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
6285 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6286 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
6288 src: glBitmap_libJPEG_source_mgr_ptr;
6291 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6293 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
6294 if (bytes <= 0) then begin
6295 src^.SrcBuffer[1] := $FF;
6296 src^.SrcBuffer[2] := JPEG_EOI;
6300 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
6301 src^.pub.bytes_in_buffer := bytes;
6306 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6307 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
6309 src: glBitmap_libJPEG_source_mgr_ptr;
6311 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6313 if num_bytes > 0 then begin
6314 // wanted byte isn't in buffer so set stream position and read buffer
6315 if num_bytes > src^.pub.bytes_in_buffer then begin
6316 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
6317 src^.pub.fill_input_buffer(cinfo);
6319 // wanted byte is in buffer so only skip
6320 inc(src^.pub.next_input_byte, num_bytes);
6321 dec(src^.pub.bytes_in_buffer, num_bytes);
6326 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6327 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
6329 dest: glBitmap_libJPEG_dest_mgr_ptr;
6331 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6333 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
6334 // write complete buffer
6335 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
6338 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
6339 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
6345 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6346 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
6349 dest: glBitmap_libJPEG_dest_mgr_ptr;
6351 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6353 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6354 // check for endblock
6355 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6357 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6362 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6367 {$IFDEF GLB_SUPPORT_JPEG_READ}
6368 {$IF DEFINED(GLB_LAZ_JPEG)}
6369 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6370 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6373 JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
6375 intf: TLazIntfImage;
6376 reader: TFPReaderJPEG;
6378 magic: String[MAGIC_LEN];
6381 StreamPos := aStream.Position;
6383 SetLength(magic, MAGIC_LEN);
6384 aStream.Read(magic[1], MAGIC_LEN);
6385 aStream.Position := StreamPos;
6386 if (magic <> JPEG_MAGIC) then begin
6391 reader := TFPReaderJPEG.Create;
6392 intf := TLazIntfImage.Create(0, 0);
6394 intf.DataDescription := GetDescriptionFromDevice(0, 0, 0);
6395 reader.ImageRead(aStream, intf);
6396 AssignFromLazIntfImage(intf);
6399 aStream.Position := StreamPos;
6408 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
6409 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6410 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6412 Surface: PSDL_Surface;
6417 RWops := glBitmapCreateRWops(aStream);
6419 if IMG_isJPG(RWops) > 0 then begin
6420 Surface := IMG_LoadJPG_RW(RWops);
6422 AssignFromSurface(Surface);
6425 SDL_FreeSurface(Surface);
6433 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6434 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6435 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6438 Temp: array[0..1]of Byte;
6440 jpeg: jpeg_decompress_struct;
6441 jpeg_err: jpeg_error_mgr;
6443 IntFormat: TglBitmapFormat;
6445 TempHeight, TempWidth: Integer;
6450 FormatDesc: TFormatDescriptor;
6454 if not init_libJPEG then
6455 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6458 // reading first two bytes to test file and set cursor back to begin
6459 StreamPos := aStream.Position;
6460 aStream.Read({%H-}Temp[0], 2);
6461 aStream.Position := StreamPos;
6463 // if Bitmap then read file.
6464 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6465 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6466 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6469 jpeg.err := jpeg_std_error(@jpeg_err);
6470 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6471 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6473 // decompression struct
6474 jpeg_create_decompress(@jpeg);
6476 // allocation space for streaming methods
6477 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6479 // seeting up custom functions
6480 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6481 pub.init_source := glBitmap_libJPEG_init_source;
6482 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6483 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6484 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6485 pub.term_source := glBitmap_libJPEG_term_source;
6487 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6488 pub.next_input_byte := nil; // until buffer loaded
6490 SrcStream := aStream;
6493 // set global decoding state
6494 jpeg.global_state := DSTATE_START;
6496 // read header of jpeg
6497 jpeg_read_header(@jpeg, false);
6499 // setting output parameter
6500 case jpeg.jpeg_color_space of
6503 jpeg.out_color_space := JCS_GRAYSCALE;
6504 IntFormat := tfLuminance8;
6507 jpeg.out_color_space := JCS_RGB;
6508 IntFormat := tfRGB8;
6512 jpeg_start_decompress(@jpeg);
6514 TempHeight := jpeg.output_height;
6515 TempWidth := jpeg.output_width;
6517 FormatDesc := TFormatDescriptor.Get(IntFormat);
6519 // creating new image
6520 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6524 for Row := 0 to TempHeight -1 do begin
6525 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6526 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6529 // finish decompression
6530 jpeg_finish_decompress(@jpeg);
6532 // destroy decompression
6533 jpeg_destroy_decompress(@jpeg);
6535 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
6539 if Assigned(pImage) then
6549 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6550 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6551 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6556 Temp: array[0..1]of Byte;
6560 // reading first two bytes to test file and set cursor back to begin
6561 StreamPos := aStream.Position;
6562 aStream.Read(Temp[0], 2);
6563 aStream.Position := StreamPos;
6565 // if Bitmap then read file.
6566 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6567 bmp := TBitmap.Create;
6569 jpg := TJPEGImage.Create;
6571 jpg.LoadFromStream(aStream);
6573 result := AssignFromBitmap(bmp);
6585 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6586 {$IF DEFINED(GLB_LAZ_JPEG)}
6587 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6588 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6591 intf: TLazIntfImage;
6594 jpeg := TJPEGImage.Create;
6595 intf := TLazIntfImage.Create(0, 0);
6597 if not AssignToLazIntfImage(intf) then
6598 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6599 intf.GetRawImage(raw);
6600 jpeg.LoadFromRawImage(raw, false);
6601 jpeg.SaveToStream(aStream);
6608 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6609 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6610 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6612 jpeg: jpeg_compress_struct;
6613 jpeg_err: jpeg_error_mgr;
6615 pTemp, pTemp2: pByte;
6617 procedure CopyRow(pDest, pSource: pByte);
6621 for X := 0 to Width - 1 do begin
6622 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6623 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6624 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6631 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6632 raise EglBitmapUnsupportedFormat.Create(Format);
6634 if not init_libJPEG then
6635 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6638 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6639 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6642 jpeg.err := jpeg_std_error(@jpeg_err);
6643 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6644 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6646 // compression struct
6647 jpeg_create_compress(@jpeg);
6649 // allocation space for streaming methods
6650 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6652 // seeting up custom functions
6653 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6654 pub.init_destination := glBitmap_libJPEG_init_destination;
6655 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6656 pub.term_destination := glBitmap_libJPEG_term_destination;
6658 pub.next_output_byte := @DestBuffer[1];
6659 pub.free_in_buffer := Length(DestBuffer);
6661 DestStream := aStream;
6664 // very important state
6665 jpeg.global_state := CSTATE_START;
6666 jpeg.image_width := Width;
6667 jpeg.image_height := Height;
6669 tfAlpha8, tfLuminance8: begin
6670 jpeg.input_components := 1;
6671 jpeg.in_color_space := JCS_GRAYSCALE;
6673 tfRGB8, tfBGR8: begin
6674 jpeg.input_components := 3;
6675 jpeg.in_color_space := JCS_RGB;
6679 jpeg_set_defaults(@jpeg);
6680 jpeg_set_quality(@jpeg, 95, true);
6681 jpeg_start_compress(@jpeg, true);
6684 if Format = tfBGR8 then
6685 GetMem(pTemp2, fRowSize)
6690 for Row := 0 to jpeg.image_height -1 do begin
6692 if Format = tfBGR8 then
6693 CopyRow(pTemp2, pTemp)
6698 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6699 inc(pTemp, fRowSize);
6703 if Format = tfBGR8 then
6706 jpeg_finish_compress(@jpeg);
6707 jpeg_destroy_compress(@jpeg);
6713 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6714 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6715 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6720 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6721 raise EglBitmapUnsupportedFormat.Create(Format);
6723 Bmp := TBitmap.Create;
6725 Jpg := TJPEGImage.Create;
6727 AssignToBitmap(Bmp);
6728 if (Format in [tfAlpha8, tfLuminance8]) then begin
6729 Jpg.Grayscale := true;
6730 Jpg.PixelFormat := jf8Bit;
6733 Jpg.SaveToStream(aStream);
6744 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6745 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6746 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6753 BMP_COMP_BITFIELDS = 3;
6756 TBMPHeader = packed record
6761 bfOffBits: Cardinal;
6764 TBMPInfo = packed record
6770 biCompression: Cardinal;
6771 biSizeImage: Cardinal;
6772 biXPelsPerMeter: Longint;
6773 biYPelsPerMeter: Longint;
6774 biClrUsed: Cardinal;
6775 biClrImportant: Cardinal;
6778 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6779 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6781 //////////////////////////////////////////////////////////////////////////////////////////////////
6782 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6785 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6786 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6789 case aInfo.biCompression of
6791 BMP_COMP_RLE8: begin
6792 raise EglBitmap.Create('RLE compression is not supported');
6794 BMP_COMP_BITFIELDS: begin
6795 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6796 aStream.Read(aMask.r, SizeOf(aMask.r));
6797 aStream.Read(aMask.g, SizeOf(aMask.g));
6798 aStream.Read(aMask.b, SizeOf(aMask.b));
6799 aStream.Read(aMask.a, SizeOf(aMask.a));
6801 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
6805 //get suitable format
6806 case aInfo.biBitCount of
6807 8: result := tfLuminance8;
6808 16: result := tfBGR5;
6809 24: result := tfBGR8;
6810 32: result := tfBGRA8;
6814 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6817 ColorTable: TbmpColorTable;
6820 if (aInfo.biBitCount >= 16) then
6822 aFormat := tfLuminance8;
6823 c := aInfo.biClrUsed;
6825 c := 1 shl aInfo.biBitCount;
6826 SetLength(ColorTable, c);
6827 for i := 0 to c-1 do begin
6828 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6829 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6833 result := TbmpColorTableFormat.Create;
6834 result.PixelSize := aInfo.biBitCount / 8;
6835 result.ColorTable := ColorTable;
6836 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6839 //////////////////////////////////////////////////////////////////////////////////////////////////
6840 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6841 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6843 TmpFormat: TglBitmapFormat;
6844 FormatDesc: TFormatDescriptor;
6847 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6848 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6849 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6850 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6851 aFormat := FormatDesc.Format;
6856 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6857 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6858 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6859 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6861 result := TbmpBitfieldFormat.Create;
6862 result.PixelSize := aInfo.biBitCount / 8;
6863 result.RedMask := aMask.r;
6864 result.GreenMask := aMask.g;
6865 result.BlueMask := aMask.b;
6866 result.AlphaMask := aMask.a;
6873 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6874 PaddingBuff: Cardinal;
6875 LineBuf, ImageData, TmpData: PByte;
6876 SourceMD, DestMD: Pointer;
6877 BmpFormat: TglBitmapFormat;
6880 Mask: TglBitmapColorRec;
6885 SpecialFormat: TFormatDescriptor;
6886 FormatDesc: TFormatDescriptor;
6888 //////////////////////////////////////////////////////////////////////////////////////////////////
6889 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6892 Pixel: TglBitmapPixelData;
6894 aStream.Read(aLineBuf^, rbLineSize);
6895 SpecialFormat.PreparePixel(Pixel);
6896 for i := 0 to Info.biWidth-1 do begin
6897 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6898 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6899 FormatDesc.Map(Pixel, aData, DestMD);
6905 BmpFormat := tfEmpty;
6906 SpecialFormat := nil;
6912 StartPos := aStream.Position;
6913 aStream.Read(Header{%H-}, SizeOf(Header));
6915 if Header.bfType = BMP_MAGIC then begin
6917 BmpFormat := ReadInfo(Info, Mask);
6918 SpecialFormat := ReadColorTable(BmpFormat, Info);
6919 if not Assigned(SpecialFormat) then
6920 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6921 aStream.Position := StartPos + Header.bfOffBits;
6923 if (BmpFormat <> tfEmpty) then begin
6924 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6925 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6926 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6927 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6930 DestMD := FormatDesc.CreateMappingData;
6931 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6932 GetMem(ImageData, ImageSize);
6933 if Assigned(SpecialFormat) then begin
6934 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6935 SourceMD := SpecialFormat.CreateMappingData;
6940 FillChar(ImageData^, ImageSize, $FF);
6941 TmpData := ImageData;
6942 if (Info.biHeight > 0) then
6943 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6944 for i := 0 to Abs(Info.biHeight)-1 do begin
6945 if Assigned(SpecialFormat) then
6946 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6948 aStream.Read(TmpData^, wbLineSize); //else only read data
6949 if (Info.biHeight > 0) then
6950 dec(TmpData, wbLineSize)
6952 inc(TmpData, wbLineSize);
6953 aStream.Read(PaddingBuff{%H-}, Padding);
6955 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method
6958 if Assigned(LineBuf) then
6960 if Assigned(SourceMD) then
6961 SpecialFormat.FreeMappingData(SourceMD);
6962 FormatDesc.FreeMappingData(DestMD);
6965 if Assigned(ImageData) then
6970 raise EglBitmap.Create('LoadBMP - No suitable format found');
6972 aStream.Position := StartPos;
6976 FreeAndNil(SpecialFormat);
6979 else aStream.Position := StartPos;
6982 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6983 procedure TglBitmap.SaveBMP(const aStream: TStream);
6987 Converter: TFormatDescriptor;
6988 FormatDesc: TFormatDescriptor;
6989 SourceFD, DestFD: Pointer;
6990 pData, srcData, dstData, ConvertBuffer: pByte;
6992 Pixel: TglBitmapPixelData;
6993 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6994 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6996 PaddingBuff: Cardinal;
6998 function GetLineWidth : Integer;
7000 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
7004 if not (ftBMP in FormatGetSupportedFiles(Format)) then
7005 raise EglBitmapUnsupportedFormat.Create(Format);
7008 FormatDesc := TFormatDescriptor.Get(Format);
7009 ImageSize := FormatDesc.GetSize(Dimension);
7011 FillChar(Header{%H-}, SizeOf(Header), 0);
7012 Header.bfType := BMP_MAGIC;
7013 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
7014 Header.bfReserved1 := 0;
7015 Header.bfReserved2 := 0;
7016 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
7018 FillChar(Info{%H-}, SizeOf(Info), 0);
7019 Info.biSize := SizeOf(Info);
7020 Info.biWidth := Width;
7021 Info.biHeight := Height;
7023 Info.biCompression := BMP_COMP_RGB;
7024 Info.biSizeImage := ImageSize;
7029 Info.biBitCount := 4;
7030 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
7031 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
7032 Converter := TbmpColorTableFormat.Create;
7033 with (Converter as TbmpColorTableFormat) do begin
7036 Range := glBitmapColorRec($F, $F, $F, $0);
7041 tfR3G3B2, tfLuminance8: begin
7042 Info.biBitCount := 8;
7043 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
7044 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
7045 Converter := TbmpColorTableFormat.Create;
7046 with (Converter as TbmpColorTableFormat) do begin
7049 if (Format = tfR3G3B2) then begin
7050 Range := glBitmapColorRec($7, $7, $3, $0);
7051 Shift := glBitmapShiftRec(0, 3, 6, 0);
7053 Range := glBitmapColorRec($FF, $FF, $FF, $0);
7058 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
7059 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
7060 Info.biBitCount := 16;
7061 Info.biCompression := BMP_COMP_BITFIELDS;
7064 tfBGR8, tfRGB8: begin
7065 Info.biBitCount := 24;
7066 if (Format = tfRGB8) then
7067 Converter := TfdBGR8.Create; //use BGR8 Format Descriptor to Swap RGB Values
7070 tfRGB10, tfRGB10A2, tfRGBA8,
7071 tfBGR10, tfBGR10A2, tfBGRA8: begin
7072 Info.biBitCount := 32;
7073 Info.biCompression := BMP_COMP_BITFIELDS;
7076 raise EglBitmapUnsupportedFormat.Create(Format);
7078 Info.biXPelsPerMeter := 2835;
7079 Info.biYPelsPerMeter := 2835;
7082 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7083 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
7084 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
7086 RedMask := FormatDesc.RedMask;
7087 GreenMask := FormatDesc.GreenMask;
7088 BlueMask := FormatDesc.BlueMask;
7089 AlphaMask := FormatDesc.AlphaMask;
7093 aStream.Write(Header, SizeOf(Header));
7094 aStream.Write(Info, SizeOf(Info));
7097 if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
7098 with (Converter as TbmpColorTableFormat) do
7099 aStream.Write(ColorTable[0].b,
7100 SizeOf(TbmpColorTableEnty) * Length(ColorTable));
7103 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7104 aStream.Write(RedMask, SizeOf(Cardinal));
7105 aStream.Write(GreenMask, SizeOf(Cardinal));
7106 aStream.Write(BlueMask, SizeOf(Cardinal));
7107 aStream.Write(AlphaMask, SizeOf(Cardinal));
7111 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
7112 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
7113 Padding := GetLineWidth - wbLineSize;
7117 inc(pData, (Height-1) * rbLineSize);
7119 // prepare row buffer. But only for RGB because RGBA supports color masks
7120 // so it's possible to change color within the image.
7121 if Assigned(Converter) then begin
7122 FormatDesc.PreparePixel(Pixel);
7123 GetMem(ConvertBuffer, wbLineSize);
7124 SourceFD := FormatDesc.CreateMappingData;
7125 DestFD := Converter.CreateMappingData;
7127 ConvertBuffer := nil;
7130 for LineIdx := 0 to Height - 1 do begin
7132 if Assigned(Converter) then begin
7134 dstData := ConvertBuffer;
7135 for PixelIdx := 0 to Info.biWidth-1 do begin
7136 FormatDesc.Unmap(srcData, Pixel, SourceFD);
7137 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
7138 Converter.Map(Pixel, dstData, DestFD);
7140 aStream.Write(ConvertBuffer^, wbLineSize);
7142 aStream.Write(pData^, rbLineSize);
7144 dec(pData, rbLineSize);
7145 if (Padding > 0) then
7146 aStream.Write(PaddingBuff, Padding);
7149 // destroy row buffer
7150 if Assigned(ConvertBuffer) then begin
7151 FormatDesc.FreeMappingData(SourceFD);
7152 Converter.FreeMappingData(DestFD);
7153 FreeMem(ConvertBuffer);
7157 if Assigned(Converter) then
7162 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7163 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7164 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7166 TTGAHeader = packed record
7170 //ColorMapSpec: Array[0..4] of Byte;
7171 ColorMapStart: Word;
7172 ColorMapLength: Word;
7173 ColorMapEntrySize: Byte;
7183 TGA_UNCOMPRESSED_RGB = 2;
7184 TGA_UNCOMPRESSED_GRAY = 3;
7185 TGA_COMPRESSED_RGB = 10;
7186 TGA_COMPRESSED_GRAY = 11;
7188 TGA_NONE_COLOR_TABLE = 0;
7190 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7191 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
7194 ImageData: System.PByte;
7195 StartPosition: Int64;
7196 PixelSize, LineSize: Integer;
7197 tgaFormat: TglBitmapFormat;
7198 FormatDesc: TFormatDescriptor;
7199 Counter: packed record
7201 low, high, dir: Integer;
7208 ////////////////////////////////////////////////////////////////////////////////////////
7209 procedure ReadUncompressed;
7212 buf, tmp1, tmp2: System.PByte;
7215 if (Counter.X.dir < 0) then
7216 GetMem(buf, LineSize);
7218 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
7220 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
7221 if (Counter.X.dir < 0) then begin //flip X
7222 aStream.Read(buf^, LineSize);
7224 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
7225 for i := 0 to Header.Width-1 do begin //for all pixels in line
7226 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
7231 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
7234 aStream.Read(tmp1^, LineSize);
7235 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
7238 if Assigned(buf) then
7243 ////////////////////////////////////////////////////////////////////////////////////////
7244 procedure ReadCompressed;
7246 /////////////////////////////////////////////////////////////////
7248 TmpData: System.PByte;
7249 LinePixelsRead: Integer;
7250 procedure CheckLine;
7252 if (LinePixelsRead >= Header.Width) then begin
7253 LinePixelsRead := 0;
7254 inc(Counter.Y.low, Counter.Y.dir); //next line index
7255 TmpData := ImageData;
7256 inc(TmpData, Counter.Y.low * LineSize); //set line
7257 if (Counter.X.dir < 0) then //if x flipped then
7258 inc(TmpData, LineSize - PixelSize); //set last pixel
7262 /////////////////////////////////////////////////////////////////
7265 CacheSize, CachePos: Integer;
7266 procedure CachedRead(out Buffer; Count: Integer);
7270 if (CachePos + Count > CacheSize) then begin
7271 //if buffer overflow save non read bytes
7273 if (CacheSize - CachePos > 0) then begin
7274 BytesRead := CacheSize - CachePos;
7275 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
7276 inc(CachePos, BytesRead);
7279 //load cache from file
7280 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
7281 aStream.Read(Cache^, CacheSize);
7284 //read rest of requested bytes
7285 if (Count - BytesRead > 0) then begin
7286 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
7287 inc(CachePos, Count - BytesRead);
7290 //if no buffer overflow just read the data
7291 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
7292 inc(CachePos, Count);
7296 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
7301 inc(aBuffer, Counter.X.dir);
7304 PWord(aBuffer)^ := PWord(aData)^;
7305 inc(aBuffer, 2 * Counter.X.dir);
7308 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
7309 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
7310 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
7311 inc(aBuffer, 3 * Counter.X.dir);
7314 PCardinal(aBuffer)^ := PCardinal(aData)^;
7315 inc(aBuffer, 4 * Counter.X.dir);
7321 TotalPixelsToRead, TotalPixelsRead: Integer;
7323 buf: array [0..3] of Byte; //1 pixel is max 32bit long
7324 PixelRepeat: Boolean;
7325 PixelsToRead, PixelCount: Integer;
7330 TotalPixelsToRead := Header.Width * Header.Height;
7331 TotalPixelsRead := 0;
7332 LinePixelsRead := 0;
7334 GetMem(Cache, CACHE_SIZE);
7336 TmpData := ImageData;
7337 inc(TmpData, Counter.Y.low * LineSize); //set line
7338 if (Counter.X.dir < 0) then //if x flipped then
7339 inc(TmpData, LineSize - PixelSize); //set last pixel
7343 CachedRead(Temp, 1);
7344 PixelRepeat := (Temp and $80) > 0;
7345 PixelsToRead := (Temp and $7F) + 1;
7346 inc(TotalPixelsRead, PixelsToRead);
7349 CachedRead(buf[0], PixelSize);
7350 while (PixelsToRead > 0) do begin
7352 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
7353 while (PixelCount > 0) do begin
7354 if not PixelRepeat then
7355 CachedRead(buf[0], PixelSize);
7356 PixelToBuffer(@buf[0], TmpData);
7357 inc(LinePixelsRead);
7362 until (TotalPixelsRead >= TotalPixelsToRead);
7368 function IsGrayFormat: Boolean;
7370 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
7376 // reading header to test file and set cursor back to begin
7377 StartPosition := aStream.Position;
7378 aStream.Read(Header{%H-}, SizeOf(Header));
7380 // no colormapped files
7381 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
7382 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
7385 if Header.ImageID <> 0 then // skip image ID
7386 aStream.Position := aStream.Position + Header.ImageID;
7388 tgaFormat := tfEmpty;
7390 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
7391 0: tgaFormat := tfLuminance8;
7392 8: tgaFormat := tfAlpha8;
7395 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
7396 0: tgaFormat := tfLuminance16;
7397 8: tgaFormat := tfLuminance8Alpha8;
7398 end else case (Header.ImageDesc and $F) of
7399 0: tgaFormat := tfBGR5;
7400 1: tgaFormat := tfBGR5A1;
7401 4: tgaFormat := tfBGRA4;
7404 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7405 0: tgaFormat := tfBGR8;
7408 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7409 2: tgaFormat := tfBGR10A2;
7410 8: tgaFormat := tfBGRA8;
7414 if (tgaFormat = tfEmpty) then
7415 raise EglBitmap.Create('LoadTga - unsupported format');
7417 FormatDesc := TFormatDescriptor.Get(tgaFormat);
7418 PixelSize := FormatDesc.GetSize(1, 1);
7419 LineSize := FormatDesc.GetSize(Header.Width, 1);
7421 GetMem(ImageData, LineSize * Header.Height);
7424 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7425 Counter.X.low := Header.Height-1;;
7426 Counter.X.high := 0;
7427 Counter.X.dir := -1;
7430 Counter.X.high := Header.Height-1;
7435 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7437 Counter.Y.high := Header.Height-1;
7440 Counter.Y.low := Header.Height-1;;
7441 Counter.Y.high := 0;
7442 Counter.Y.dir := -1;
7446 case Header.ImageType of
7447 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7449 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7453 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method
7456 if Assigned(ImageData) then
7461 aStream.Position := StartPosition;
7464 else aStream.Position := StartPosition;
7467 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7468 procedure TglBitmap.SaveTGA(const aStream: TStream);
7471 LineSize, Size, x, y: Integer;
7472 Pixel: TglBitmapPixelData;
7473 LineBuf, SourceData, DestData: PByte;
7474 SourceMD, DestMD: Pointer;
7475 FormatDesc: TFormatDescriptor;
7476 Converter: TFormatDescriptor;
7478 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7479 raise EglBitmapUnsupportedFormat.Create(Format);
7482 FillChar(Header{%H-}, SizeOf(Header), 0);
7485 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7486 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7487 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7489 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7492 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7494 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7495 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7497 else if (Format in [tfBGR8, tfRGB8]) then
7505 Header.ImageDesc := 1 and $F;
7506 tfRGB10A2, tfBGR10A2:
7507 Header.ImageDesc := 2 and $F;
7509 Header.ImageDesc := 4 and $F;
7510 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7511 Header.ImageDesc := 8 and $F;
7514 Header.Width := Width;
7515 Header.Height := Height;
7516 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7517 aStream.Write(Header, SizeOf(Header));
7519 // convert RGB(A) to BGR(A)
7521 FormatDesc := TFormatDescriptor.Get(Format);
7522 Size := FormatDesc.GetSize(Dimension);
7523 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7524 if (FormatDesc.RGBInverted = tfEmpty) then
7525 raise EglBitmap.Create('inverted RGB format is empty');
7526 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7527 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7528 (Converter.PixelSize <> FormatDesc.PixelSize) then
7529 raise EglBitmap.Create('invalid inverted RGB format');
7532 if Assigned(Converter) then begin
7533 LineSize := FormatDesc.GetSize(Width, 1);
7534 GetMem(LineBuf, LineSize);
7535 SourceMD := FormatDesc.CreateMappingData;
7536 DestMD := Converter.CreateMappingData;
7539 for y := 0 to Height-1 do begin
7540 DestData := LineBuf;
7541 for x := 0 to Width-1 do begin
7542 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7543 Converter.Map(Pixel, DestData, DestMD);
7545 aStream.Write(LineBuf^, LineSize);
7549 FormatDesc.FreeMappingData(SourceMD);
7550 FormatDesc.FreeMappingData(DestMD);
7553 aStream.Write(Data^, Size);
7556 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7557 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7558 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7560 DDS_MAGIC: Cardinal = $20534444;
7562 // DDS_header.dwFlags
7563 DDSD_CAPS = $00000001;
7564 DDSD_HEIGHT = $00000002;
7565 DDSD_WIDTH = $00000004;
7566 DDSD_PIXELFORMAT = $00001000;
7568 // DDS_header.sPixelFormat.dwFlags
7569 DDPF_ALPHAPIXELS = $00000001;
7570 DDPF_ALPHA = $00000002;
7571 DDPF_FOURCC = $00000004;
7572 DDPF_RGB = $00000040;
7573 DDPF_LUMINANCE = $00020000;
7575 // DDS_header.sCaps.dwCaps1
7576 DDSCAPS_TEXTURE = $00001000;
7578 // DDS_header.sCaps.dwCaps2
7579 DDSCAPS2_CUBEMAP = $00000200;
7581 D3DFMT_DXT1 = $31545844;
7582 D3DFMT_DXT3 = $33545844;
7583 D3DFMT_DXT5 = $35545844;
7586 TDDSPixelFormat = packed record
7590 dwRGBBitCount: Cardinal;
7591 dwRBitMask: Cardinal;
7592 dwGBitMask: Cardinal;
7593 dwBBitMask: Cardinal;
7594 dwABitMask: Cardinal;
7597 TDDSCaps = packed record
7601 dwReserved: Cardinal;
7604 TDDSHeader = packed record
7609 dwPitchOrLinearSize: Cardinal;
7611 dwMipMapCount: Cardinal;
7612 dwReserved: array[0..10] of Cardinal;
7613 PixelFormat: TDDSPixelFormat;
7615 dwReserved2: Cardinal;
7618 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7619 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7622 Converter: TbmpBitfieldFormat;
7624 function GetDDSFormat: TglBitmapFormat;
7626 fd: TFormatDescriptor;
7628 Range: TglBitmapColorRec;
7632 with Header.PixelFormat do begin
7634 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7635 case Header.PixelFormat.dwFourCC of
7636 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7637 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7638 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7640 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7642 //find matching format
7643 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7644 fd := TFormatDescriptor.Get(result);
7645 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7646 (8 * fd.PixelSize = dwRGBBitCount) then
7650 //find format with same Range
7651 Range.r := dwRBitMask;
7652 Range.g := dwGBitMask;
7653 Range.b := dwBBitMask;
7654 Range.a := dwABitMask;
7655 for i := 0 to 3 do begin
7656 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7657 Range.arr[i] := Range.arr[i] shr 1;
7659 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7660 fd := TFormatDescriptor.Get(result);
7663 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7671 //no format with same range found -> use default
7672 if (result = tfEmpty) then begin
7673 if (dwABitMask > 0) then
7679 Converter := TbmpBitfieldFormat.Create;
7680 Converter.RedMask := dwRBitMask;
7681 Converter.GreenMask := dwGBitMask;
7682 Converter.BlueMask := dwBBitMask;
7683 Converter.AlphaMask := dwABitMask;
7684 Converter.PixelSize := dwRGBBitCount / 8;
7691 x, y, LineSize, RowSize, Magic: Cardinal;
7692 NewImage, TmpData, RowData, SrcData: System.PByte;
7693 SourceMD, DestMD: Pointer;
7694 Pixel: TglBitmapPixelData;
7695 ddsFormat: TglBitmapFormat;
7696 FormatDesc: TFormatDescriptor;
7701 StreamPos := aStream.Position;
7704 aStream.Read(Magic{%H-}, sizeof(Magic));
7705 if (Magic <> DDS_MAGIC) then begin
7706 aStream.Position := StreamPos;
7711 aStream.Read(Header{%H-}, sizeof(Header));
7712 if (Header.dwSize <> SizeOf(Header)) or
7713 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7714 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7716 aStream.Position := StreamPos;
7720 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7721 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
7723 ddsFormat := GetDDSFormat;
7725 if (ddsFormat = tfEmpty) then
7726 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7728 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7729 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7730 GetMem(NewImage, Header.dwHeight * LineSize);
7732 TmpData := NewImage;
7735 if Assigned(Converter) then begin
7736 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7737 GetMem(RowData, RowSize);
7738 SourceMD := Converter.CreateMappingData;
7739 DestMD := FormatDesc.CreateMappingData;
7741 for y := 0 to Header.dwHeight-1 do begin
7742 TmpData := NewImage;
7743 inc(TmpData, y * LineSize);
7745 aStream.Read(SrcData^, RowSize);
7746 for x := 0 to Header.dwWidth-1 do begin
7747 Converter.Unmap(SrcData, Pixel, SourceMD);
7748 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7749 FormatDesc.Map(Pixel, TmpData, DestMD);
7753 Converter.FreeMappingData(SourceMD);
7754 FormatDesc.FreeMappingData(DestMD);
7760 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7761 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7762 for Y := 0 to Header.dwHeight-1 do begin
7763 aStream.Read(TmpData^, RowSize);
7764 Inc(TmpData, LineSize);
7769 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7770 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7771 for Y := 0 to Header.dwHeight-1 do begin
7772 aStream.Read(TmpData^, RowSize);
7773 Inc(TmpData, LineSize);
7776 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7778 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method
7781 if Assigned(NewImage) then
7786 FreeAndNil(Converter);
7790 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7791 procedure TglBitmap.SaveDDS(const aStream: TStream);
7794 FormatDesc: TFormatDescriptor;
7796 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7797 raise EglBitmapUnsupportedFormat.Create(Format);
7799 FormatDesc := TFormatDescriptor.Get(Format);
7802 FillChar(Header{%H-}, SizeOf(Header), 0);
7803 Header.dwSize := SizeOf(Header);
7804 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7806 Header.dwWidth := Max(1, Width);
7807 Header.dwHeight := Max(1, Height);
7810 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7813 Header.PixelFormat.dwSize := sizeof(Header);
7814 if (FormatDesc.IsCompressed) then begin
7815 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7817 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7818 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7819 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7821 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7822 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7823 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7824 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7825 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7826 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7827 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7828 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7829 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7831 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7832 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7833 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7834 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7835 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7836 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7839 if (FormatDesc.HasAlpha) then
7840 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7842 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7843 aStream.Write(Header, SizeOf(Header));
7844 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7847 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7848 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7849 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7850 procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7851 const aWidth: Integer; const aHeight: Integer);
7856 if (aHeight > 1) then begin
7857 Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1);
7858 GetMem(pTemp, Size);
7860 Move(aData^, pTemp^, Size);
7869 inherited SetDataPointer(pTemp, aFormat, aWidth);
7872 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7873 function TglBitmap1D.FlipHorz: Boolean;
7876 pTempDest, pDest, pSource: PByte;
7878 result := inherited FlipHorz;
7879 if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin
7881 GetMem(pDest, fRowSize);
7884 Inc(pTempDest, fRowSize);
7885 for Col := 0 to Width-1 do begin
7886 dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data
7887 Move(pSource^, pTempDest^, fPixelSize);
7888 Inc(pSource, fPixelSize);
7890 SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method
7893 if Assigned(pDest) then
7900 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7901 procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean);
7903 FormatDesc: TFormatDescriptor;
7906 FormatDesc := TFormatDescriptor.Get(Format);
7907 if FormatDesc.IsCompressed then begin
7908 if not Assigned(glCompressedTexImage1D) then
7909 raise EglBitmap.Create('compressed formats not supported by video adapter');
7910 glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
7911 end else if aBuildWithGlu then
7912 gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7914 glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7917 if (FreeDataAfterGenTexture) then
7921 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7922 procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean);
7924 BuildWithGlu, TexRec: Boolean;
7927 if Assigned(Data) then begin
7928 // Check Texture Size
7929 if (aTestTextureSize) then begin
7930 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7932 if (Width > TexSize) then
7933 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7935 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7936 (Target = GL_TEXTURE_RECTANGLE);
7937 if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7938 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7942 SetupParameters(BuildWithGlu);
7943 UploadData(BuildWithGlu);
7944 glAreTexturesResident(1, @fID, @fIsResident);
7948 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7949 procedure TglBitmap1D.AfterConstruction;
7952 Target := GL_TEXTURE_1D;
7955 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7956 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7957 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7958 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7960 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7961 result := fLines[aIndex]
7966 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7967 procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7968 const aWidth: Integer; const aHeight: Integer);
7970 Idx, LineWidth: Integer;
7972 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7974 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7976 if Assigned(Data) then begin
7977 SetLength(fLines, GetHeight);
7978 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7980 for Idx := 0 to GetHeight-1 do begin
7981 fLines[Idx] := Data;
7982 Inc(fLines[Idx], Idx * LineWidth);
7985 else SetLength(fLines, 0);
7987 SetLength(fLines, 0);
7991 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7992 procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
7994 FormatDesc: TFormatDescriptor;
7996 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7998 FormatDesc := TFormatDescriptor.Get(Format);
7999 if FormatDesc.IsCompressed then begin
8000 if not Assigned(glCompressedTexImage2D) then
8001 raise EglBitmap.Create('compressed formats not supported by video adapter');
8002 glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
8003 end else if aBuildWithGlu then begin
8004 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
8005 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
8007 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
8008 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
8012 if (FreeDataAfterGenTexture) then
8016 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8017 procedure TglBitmap2D.AfterConstruction;
8020 Target := GL_TEXTURE_2D;
8023 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8024 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
8027 Size, w, h: Integer;
8028 FormatDesc: TFormatDescriptor;
8030 FormatDesc := TFormatDescriptor.Get(aFormat);
8031 if FormatDesc.IsCompressed then
8032 raise EglBitmapUnsupportedFormat.Create(aFormat);
8034 w := aRight - aLeft;
8035 h := aBottom - aTop;
8036 Size := FormatDesc.GetSize(w, h);
8039 glPixelStorei(GL_PACK_ALIGNMENT, 1);
8040 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8041 SetDataPointer(Temp, aFormat, w, h); //be careful, Data could be freed by this method
8044 if Assigned(Temp) then
8050 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8051 procedure TglBitmap2D.GetDataFromTexture;
8054 TempWidth, TempHeight: GLint;
8055 TempIntFormat: GLenum;
8056 IntFormat, f: TglBitmapFormat;
8057 FormatDesc: TFormatDescriptor;
8062 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
8063 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
8064 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, PGLint(@TempIntFormat));
8066 IntFormat := tfEmpty;
8067 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
8068 FormatDesc := TFormatDescriptor.Get(f);
8069 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
8070 IntFormat := FormatDesc.Format;
8075 // Getting data from OpenGL
8076 FormatDesc := TFormatDescriptor.Get(IntFormat);
8077 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
8079 if FormatDesc.IsCompressed then begin
8080 if not Assigned(glGetCompressedTexImage) then
8081 raise EglBitmap.Create('compressed formats not supported by video adapter');
8082 glGetCompressedTexImage(Target, 0, Temp)
8084 glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8085 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
8087 if Assigned(Temp) then
8093 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8094 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
8096 BuildWithGlu, PotTex, TexRec: Boolean;
8099 if Assigned(Data) then begin
8100 // Check Texture Size
8101 if (aTestTextureSize) then begin
8102 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8104 if ((Height > TexSize) or (Width > TexSize)) then
8105 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8107 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
8108 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
8109 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8110 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8114 SetupParameters(BuildWithGlu);
8115 UploadData(Target, BuildWithGlu);
8116 glAreTexturesResident(1, @fID, @fIsResident);
8120 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8121 function TglBitmap2D.FlipHorz: Boolean;
8124 TempDestData, DestData, SourceData: PByte;
8127 result := inherited FlipHorz;
8128 if Assigned(Data) then begin
8130 ImgSize := Height * fRowSize;
8131 GetMem(DestData, ImgSize);
8133 TempDestData := DestData;
8134 Dec(TempDestData, fRowSize + fPixelSize);
8135 for Row := 0 to Height -1 do begin
8136 Inc(TempDestData, fRowSize * 2);
8137 for Col := 0 to Width -1 do begin
8138 Move(SourceData^, TempDestData^, fPixelSize);
8139 Inc(SourceData, fPixelSize);
8140 Dec(TempDestData, fPixelSize);
8143 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8146 if Assigned(DestData) then
8153 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8154 function TglBitmap2D.FlipVert: Boolean;
8157 TempDestData, DestData, SourceData: PByte;
8159 result := inherited FlipVert;
8160 if Assigned(Data) then begin
8162 GetMem(DestData, Height * fRowSize);
8164 TempDestData := DestData;
8165 Inc(TempDestData, Width * (Height -1) * fPixelSize);
8166 for Row := 0 to Height -1 do begin
8167 Move(SourceData^, TempDestData^, fRowSize);
8168 Dec(TempDestData, fRowSize);
8169 Inc(SourceData, fRowSize);
8171 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8174 if Assigned(DestData) then
8181 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8182 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8183 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8185 TMatrixItem = record
8190 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
8191 TglBitmapToNormalMapRec = Record
8193 Heights: array of Single;
8194 MatrixU : array of TMatrixItem;
8195 MatrixV : array of TMatrixItem;
8199 ONE_OVER_255 = 1 / 255;
8201 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8202 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
8206 with FuncRec do begin
8208 Source.Data.r * LUMINANCE_WEIGHT_R +
8209 Source.Data.g * LUMINANCE_WEIGHT_G +
8210 Source.Data.b * LUMINANCE_WEIGHT_B;
8211 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
8215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8216 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
8219 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
8222 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8223 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
8225 TVec = Array[0..2] of Single;
8232 function GetHeight(X, Y: Integer): Single;
8234 with FuncRec do begin
8235 X := Max(0, Min(Size.X -1, X));
8236 Y := Max(0, Min(Size.Y -1, Y));
8237 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
8242 with FuncRec do begin
8243 with PglBitmapToNormalMapRec(Args)^ do begin
8245 for Idx := Low(MatrixU) to High(MatrixU) do
8246 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
8249 for Idx := Low(MatrixU) to High(MatrixU) do
8250 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
8252 Vec[0] := -du * Scale;
8253 Vec[1] := -dv * Scale;
8258 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8259 if Len <> 0 then begin
8260 Vec[0] := Vec[0] * Len;
8261 Vec[1] := Vec[1] * Len;
8262 Vec[2] := Vec[2] * Len;
8266 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
8267 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
8268 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
8272 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8273 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
8275 Rec: TglBitmapToNormalMapRec;
8277 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
8279 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
8280 Matrix[Index].X := X;
8281 Matrix[Index].Y := Y;
8282 Matrix[Index].W := W;
8287 if TFormatDescriptor.Get(Format).IsCompressed then
8288 raise EglBitmapUnsupportedFormat.Create(Format);
8290 if aScale > 100 then
8292 else if aScale < -100 then
8295 Rec.Scale := aScale;
8297 SetLength(Rec.Heights, Width * Height);
8301 SetLength(Rec.MatrixU, 2);
8302 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
8303 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
8305 SetLength(Rec.MatrixV, 2);
8306 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
8307 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
8311 SetLength(Rec.MatrixU, 6);
8312 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
8313 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
8314 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
8315 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
8316 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
8317 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
8319 SetLength(Rec.MatrixV, 6);
8320 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
8321 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
8322 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
8323 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
8324 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
8325 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
8329 SetLength(Rec.MatrixU, 6);
8330 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
8331 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
8332 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
8333 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
8334 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
8335 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
8337 SetLength(Rec.MatrixV, 6);
8338 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
8339 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
8340 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
8341 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
8342 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
8343 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
8347 SetLength(Rec.MatrixU, 20);
8348 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
8349 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
8350 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
8351 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
8352 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
8353 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
8354 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
8355 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
8356 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
8357 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
8358 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
8359 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
8360 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
8361 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
8362 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
8363 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
8364 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
8365 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
8366 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
8367 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
8369 SetLength(Rec.MatrixV, 20);
8370 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
8371 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
8372 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
8373 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
8374 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
8375 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
8376 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
8377 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
8378 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
8379 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
8380 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
8381 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
8382 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
8383 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
8384 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
8385 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
8386 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
8387 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
8388 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
8389 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
8394 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
8395 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
8397 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
8398 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
8400 SetLength(Rec.Heights, 0);
8404 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8405 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8406 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8407 procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean);
8409 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8412 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8413 procedure TglBitmapCubeMap.AfterConstruction;
8417 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8418 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8421 Target := GL_TEXTURE_CUBE_MAP;
8422 fGenMode := GL_REFLECTION_MAP;
8425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8426 procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean);
8428 BuildWithGlu: Boolean;
8431 if (aTestTextureSize) then begin
8432 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8434 if (Height > TexSize) or (Width > TexSize) then
8435 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8437 if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8438 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8443 SetupParameters(BuildWithGlu);
8444 UploadData(aCubeTarget, BuildWithGlu);
8447 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8448 procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean);
8450 inherited Bind (aEnableTextureUnit);
8451 if aEnableTexCoordsGen then begin
8452 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8453 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8454 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8455 glEnable(GL_TEXTURE_GEN_S);
8456 glEnable(GL_TEXTURE_GEN_T);
8457 glEnable(GL_TEXTURE_GEN_R);
8461 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8462 procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean);
8464 inherited Unbind(aDisableTextureUnit);
8465 if aDisableTexCoordsGen then begin
8466 glDisable(GL_TEXTURE_GEN_S);
8467 glDisable(GL_TEXTURE_GEN_T);
8468 glDisable(GL_TEXTURE_GEN_R);
8472 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8473 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8474 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8476 TVec = Array[0..2] of Single;
8477 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8479 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8480 TglBitmapNormalMapRec = record
8482 Func: TglBitmapNormalMapGetVectorFunc;
8485 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8486 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8488 aVec[0] := aHalfSize;
8489 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8490 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8493 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8494 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8496 aVec[0] := - aHalfSize;
8497 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8498 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8501 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8502 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8504 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8505 aVec[1] := aHalfSize;
8506 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8509 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8510 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8512 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8513 aVec[1] := - aHalfSize;
8514 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8517 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8518 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8520 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8521 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8522 aVec[2] := aHalfSize;
8525 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8526 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8528 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8529 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8530 aVec[2] := - aHalfSize;
8533 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8534 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8540 with FuncRec do begin
8541 with PglBitmapNormalMapRec(Args)^ do begin
8542 Func(Vec, Position, HalfSize);
8545 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8546 if Len <> 0 then begin
8547 Vec[0] := Vec[0] * Len;
8548 Vec[1] := Vec[1] * Len;
8549 Vec[2] := Vec[2] * Len;
8552 // Scale Vector and AddVectro
8553 Vec[0] := Vec[0] * 0.5 + 0.5;
8554 Vec[1] := Vec[1] * 0.5 + 0.5;
8555 Vec[2] := Vec[2] * 0.5 + 0.5;
8560 Dest.Data.arr[i] := Round(Vec[i] * 255);
8564 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8565 procedure TglBitmapNormalMap.AfterConstruction;
8568 fGenMode := GL_NORMAL_MAP;
8571 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8572 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean);
8574 Rec: TglBitmapNormalMapRec;
8575 SizeRec: TglBitmapPixelPosition;
8577 Rec.HalfSize := aSize div 2;
8578 FreeDataAfterGenTexture := false;
8580 SizeRec.Fields := [ffX, ffY];
8585 Rec.Func := glBitmapNormalMapPosX;
8586 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8587 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize);
8590 Rec.Func := glBitmapNormalMapNegX;
8591 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8592 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize);
8595 Rec.Func := glBitmapNormalMapPosY;
8596 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8597 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize);
8600 Rec.Func := glBitmapNormalMapNegY;
8601 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8602 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize);
8605 Rec.Func := glBitmapNormalMapPosZ;
8606 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8607 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize);
8610 Rec.Func := glBitmapNormalMapNegZ;
8611 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8612 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize);
8617 glBitmapSetDefaultFormat (tfEmpty);
8618 glBitmapSetDefaultMipmap (mmMipmap);
8619 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8620 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8621 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8623 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8624 glBitmapSetDefaultDeleteTextureOnFree (true);
8626 TFormatDescriptor.Init;
8628 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8629 OpenGLInitialized := false;
8630 InitOpenGLCS := TCriticalSection.Create;
8634 TFormatDescriptor.Finalize;
8636 {$IFDEF GLB_NATIVE_OGL}
8637 if Assigned(GL_LibHandle) then
8638 glbFreeLibrary(GL_LibHandle);
8640 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8641 if Assigned(GLU_LibHandle) then
8642 glbFreeLibrary(GLU_LibHandle);
8643 FreeAndNil(InitOpenGLCS);