1 {***********************************************************
2 glBitmap by Steffen Xonna aka Lossy eX (2003-2008)
3 http://www.opengl24.de/index.php?cat=header&file=glbitmap
5 modified by Delphi OpenGL Community (http://delphigl.com/) (2013)
7 ------------------------------------------------------------
8 The contents of this file are used with permission, subject to
9 the Mozilla Public License Version 1.1 (the "License"); you may
10 not use this file except in compliance with the License. You may
11 obtain a copy of the License at
12 http://www.mozilla.org/MPL/MPL-1.1.html
13 ------------------------------------------------------------
14 Version 3.0.0 unstable
15 ------------------------------------------------------------
18 - refactoring of the complete library
20 - The define GLB_DELPHI dosn't check versions anymore. If you say you are using delphi
21 then it's your problem if that isn't true. This prevents the unit for incompatibility
22 with newer versions of Delphi.
23 - Problems with D2009+ resolved (Thanks noeska and all i forgot)
24 - GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson)
26 - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson)
27 - Additional Datapointer for functioninterface now has the name CustomData
29 - AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson)
30 - If you load an texture from an file the property Filename will be set to the name of the file
31 - Three new properties to attach custom data to the Texture objects
32 - CustomName (free for use string)
33 - CustomNameW (free for use widestring)
34 - CustomDataPointer (free for use pointer to attach other objects or complex structures)
36 - RLE TGAs loaded much faster
38 - fixed some problem with reading RLE TGAs.
40 - function clone now only copys data if it's assigned and now it also copies the ID
41 - it seems that lazarus dont like comments in comments.
43 - It's possible to set the id of the texture
44 - define GLB_NO_NATIVE_GL deactivated by default
46 - Now supports the following libraries
50 - Linux compatibillity via free pascal compatibility (delphi sources optional)
51 - BMPs now loaded manuel
53 - Property DataPtr now has the name Data
54 - Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR
55 - Unused Depth removed
56 - Function FreeData to freeing image data added
58 - ImageID flag of TGAs was ignored. (Thanks Zwoetzen)
60 - Function SetBorderColor implemented (only used by opengl if wrap is set to GL_CLAMP_TO_BORDER)
61 - Function AddAlphaFromValue implemented to use an fixed Value as Alphachannel
62 - Function ReadOpenGLExtension is now only intern
64 - pngimage now disabled by default like all other versions.
66 - Setting up an anisotropic filter of 0 isnt allowed by nvidia (Thanks Ogridi)
68 - Fixed some Problem with Delphi 5
69 - Now uses the newest version of pngimage. Makes saving pngs much easier.
71 - Property IsCompressed and Size removed. Not really supported by Spec (Thanks Ogridi)
73 - Internal Format ifDepth8 added
74 - function GrabScreen now supports all uncompressed formats
76 - AddAlphaFromglBitmap implemented
78 - LoadFromResource and LoadFromResourceId now needs an Instance and an ResourceType (for ID)
80 - Width, Height and Depth internal changed to TglBitmapPixelPosition.
81 property Width, Height, Depth are still existing and new property Dimension are avail
83 - Added native OpenGL Support. Breaking the dglOpenGL "barrier".
85 - Added function GrabScreen to class TglBitmap2D
87 - Added support to Save images
88 - Added function Clone to Clone Instance
90 - Functions now works with Cardinals for each channel. Up to 32 Bits per channel.
92 - Several speed optimizations
94 - Internal structure change. Loading of TGA, PNG and DDS improved.
95 Data, format and size will now set directly with SetDataPtr.
96 - AddFunc now works with all Types of Images and Formats
97 - Some Funtions moved to Baseclass TglBitmap
99 - Added Support to decompress DXT3 and DXT5 compressed Images.
100 - Added Mapping to convert data from one format into an other.
102 - Added method ConvertTo in Class TglBitmap2D. Method allows to convert every
103 supported Input format (supported by GetPixel) into any uncompresed Format
104 - Added Support to decompress DXT1 compressed Images.
105 - SwapColors replaced by ConvertTo
107 - Added Support for compressed DDSs
108 - Added new internal formats (DXT1, DXT3, DXT5)
110 - Parameter Components renamed to InternalFormat
112 - Some AllocMem replaced with GetMem (little speed change)
113 - better exception handling. Better protection from memory leaks.
115 - Added support for Direct Draw Surfaces (.DDS) (uncompressed images only)
116 - Added new internal formats (RGB8, RGBA8, RGBA4, RGB5A1, RGB10A2, R5G6B5)
118 - Added support for Grayscale textures
119 - Added internal formats (Alpha, Luminance, LuminanceAlpha, BGR8, BGRA8)
121 - Added support for GL_VERSION_2_0
122 - Added support for GL_EXT_texture_filter_anisotropic
124 - Function FillWithColor fills the Image with one Color
125 - Function LoadNormalMap added
127 - ToNormalMap allows to Create an NormalMap from the Alphachannel
128 - ToNormalMap now supports Sobel (nmSobel) function.
130 - support for RLE Compressed RGB TGAs added
132 - Class TglBitmapNormalMap added to support Normalmap generation
133 - Added function ToNormalMap in class TglBitmap2D to genereate normal maps from textures.
134 3 Filters are supported. (4 Samples, 3x3 and 5x5)
136 - Method LoadCubeMapClass removed
137 - LoadCubeMap returnvalue is now the Texture paramter. Such as LoadTextures
138 - virtual abstract method GenTexture in class TglBitmap now is protected
140 - now support DescriptionFlag in LoadTga. Allows vertical flipped images to be loaded as normal
142 - little enhancement for IsPowerOfTwo
143 - TglBitmap1D.GenTexture now tests NPOT Textures
145 - some little name changes. All properties or function with Texture in name are
146 now without texture in name. We have allways texture so we dosn't name it.
148 - GenTexture now tests if texture is NPOT and NPOT-Texture are supported or
149 TextureTarget is GL_TEXTURE_RECTANGLE. Else it raised an exception.
151 - added support for GL_ARB_texture_rectangle, GL_EXT_texture_rectangle and GL_NV_texture_rectangle
153 - Function Unbind added
154 - call of SetFilter or SetTextureWrap if TextureID exists results in setting properties to opengl texture.
156 - class TglBitmapCubeMap added (allows to Create Cubemaps)
158 - Added Support for PNG Images. (http://pngdelphi.sourceforge.net/)
159 To Enable png's use the define pngimage
161 - New Functioninterface added
162 - Function GetPixel added
164 - Property BuildMipMaps renamed to MipMap
166 - property Name removed.
167 - BuildMipMaps is now a set of 3 values. None, GluBuildMipmaps and SGIS_generate_mipmap
169 - property name added. Only used in glForms!
171 - property FreeDataAfterGenTexture is now available as default (default = true)
172 - BuildMipmaps now implemented in TglBitmap1D (i've forgotten it)
173 - function MoveMemory replaced with function Move (little speed change)
174 - several calculations stored in variables (little speed change)
176 - property BuildMipsMaps added (default = true)
177 if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps
178 - property FreeDataAfterGenTexture added (default = true)
179 if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated.
180 - parameter DisableOtherTextureUnits of Bind removed
181 - parameter FreeDataAfterGeneration of GenTextures removed
183 - TglBitmap dosn't delete data if class was destroyed (fixed)
185 - Bind now enables TextureUnits (by params)
186 - GenTextures can leave data (by param)
187 - LoadTextures now optimal
189 - Performance optimization in AddFunc
190 - procedure Bind moved to subclasses
191 - Added new Class TglBitmap1D to support real OpenGL 1D Textures
193 - Texturefilter and texturewrap now also as defaults
194 Minfilter = GL_LINEAR_MIPMAP_LINEAR
195 Magfilter = GL_LINEAR
196 Wrap(str) = GL_CLAMP_TO_EDGE
197 - Added new format tfCompressed to create a compressed texture.
198 - propertys IsCompressed, TextureSize and IsResident added
199 IsCompressed and TextureSize only contains data from level 0
201 - Added function AddFunc to add PerPixelEffects to Image
202 - LoadFromFunc now based on AddFunc
203 - Invert now based on AddFunc
204 - SwapColors now based on AddFunc
206 - Added function FlipHorz
208 - Added function LaodFromFunc to create images with function
209 - Added function FlipVert
210 - Added internal format RGB(A) if GL_EXT_bgra or OpenGL 1.2 isn't supported
212 - Added Alphafunctions to calculate alpha per function
213 - Added Alpha from ColorKey using alphafunctions
215 - First full functionally Version of glBitmap
216 - Support for 24Bit and 32Bit TGA Pictures added
218 - begin of programming
219 ***********************************************************}
222 // Please uncomment the defines below to configure the glBitmap to your preferences.
223 // If you have configured the unit you can uncomment the warning above.
224 {$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
227 // Preferences ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
229 // activate to enable build-in OpenGL support with statically linked methods
230 // use dglOpenGL.pas if not enabled
231 {.$DEFINE GLB_NATIVE_OGL_STATIC}
233 // activate to enable build-in OpenGL support with dynamically linked methods
234 // use dglOpenGL.pas if not enabled
235 {.$DEFINE GLB_NATIVE_OGL_DYNAMIC}
238 // activate to enable the support for SDL_surfaces
241 // activate to enable the support for TBitmap from Delphi (not lazarus)
242 {.$DEFINE GLB_DELPHI}
244 // activate to enable the support for TLazIntfImage from Lazarus
245 {.$DEFINE GLB_LAZARUS}
249 // activate to enable the support of SDL_image to load files. (READ ONLY)
250 // If you enable SDL_image all other libraries will be ignored!
251 {.$DEFINE GLB_SDL_IMAGE}
255 // activate to enable Lazarus TPortableNetworkGraphic support
256 // if you enable this pngImage and libPNG will be ignored
257 {.$DEFINE GLB_LAZ_PNG}
259 // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/
260 // if you enable pngimage the libPNG will be ignored
261 {.$DEFINE GLB_PNGIMAGE}
263 // activate to use the libPNG -> http://www.libpng.org/
264 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libpng
265 {.$DEFINE GLB_LIB_PNG}
269 // activate to enable Lazarus TJPEGImage support
270 // if you enable this delphi jpegs and libJPEG will be ignored
271 {.$DEFINE GLB_LAZ_JPEG}
273 // if you enable delphi jpegs the libJPEG will be ignored
274 {.$DEFINE GLB_DELPHI_JPEG}
276 // activate to use the libJPEG -> http://www.ijg.org/
277 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libjpeg
278 {.$DEFINE GLB_LIB_JPEG}
281 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
282 // PRIVATE: do not change anything! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299 {$IF DEFINED(WIN32) or DEFINED(WIN64) or DEFINED(WINDOWS)}
301 {$ELSEIF DEFINED(LINUX)}
305 // native OpenGL Support
306 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) OR DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
307 {$DEFINE GLB_NATIVE_OGL}
310 // checking define combinations
312 {$IFDEF GLB_SDL_IMAGE}
314 {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
319 {$MESSAGE warn 'The Lazarus TPortableNetworkGraphics will be ignored because you are using SDL_image.'}
323 {$IFDEF GLB_PNGIMAGE}
324 {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
325 {$undef GLB_PNGIMAGE}
328 {$IFDEF GLB_LAZ_JPEG}
329 {$MESSAGE warn 'The Lazarus TJPEGImage will be ignored because you are using SDL_image.'}
330 {$undef GLB_LAZ_JPEG}
333 {$IFDEF GLB_DELPHI_JPEG}
334 {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
335 {$undef GLB_DELPHI_JPEG}
339 {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
343 {$IFDEF GLB_LIB_JPEG}
344 {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
345 {$undef GLB_LIB_JPEG}
348 {$DEFINE GLB_SUPPORT_PNG_READ}
349 {$DEFINE GLB_SUPPORT_JPEG_READ}
352 // Lazarus TPortableNetworkGraphic
354 {$IFNDEF GLB_LAZARUS}
355 {$MESSAGE warn 'Lazarus TPortableNetworkGraphic won''t work without Lazarus. Lazarus will be activated.'}
356 {$DEFINE GLB_LAZARUS}
359 {$IFDEF GLB_PNGIMAGE}
360 {$MESSAGE warn 'The pngimage will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
361 {$undef GLB_PNGIMAGE}
365 {$MESSAGE warn 'The library libPNG will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
369 {$DEFINE GLB_SUPPORT_PNG_READ}
370 {$DEFINE GLB_SUPPORT_PNG_WRITE}
374 {$IFDEF GLB_PNGIMAGE}
376 {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'}
380 {$DEFINE GLB_SUPPORT_PNG_READ}
381 {$DEFINE GLB_SUPPORT_PNG_WRITE}
386 {$DEFINE GLB_SUPPORT_PNG_READ}
387 {$DEFINE GLB_SUPPORT_PNG_WRITE}
390 // Lazarus TJPEGImage
391 {$IFDEF GLB_LAZ_JPEG}
392 {$IFNDEF GLB_LAZARUS}
393 {$MESSAGE warn 'Lazarus TJPEGImage won''t work without Lazarus. Lazarus will be activated.'}
394 {$DEFINE GLB_LAZARUS}
397 {$IFDEF GLB_DELPHI_JPEG}
398 {$MESSAGE warn 'The Delphi JPEGImage will be ignored if you are using the Lazarus TJPEGImage.'}
399 {$undef GLB_DELPHI_JPEG}
402 {$IFDEF GLB_LIB_JPEG}
403 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the Lazarus TJPEGImage.'}
404 {$undef GLB_LIB_JPEG}
407 {$DEFINE GLB_SUPPORT_JPEG_READ}
408 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
412 {$IFDEF GLB_DELPHI_JPEG}
413 {$IFDEF GLB_LIB_JPEG}
414 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
415 {$undef GLB_LIB_JPEG}
418 {$DEFINE GLB_SUPPORT_JPEG_READ}
419 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
423 {$IFDEF GLB_LIB_JPEG}
424 {$DEFINE GLB_SUPPORT_JPEG_READ}
425 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
429 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) AND DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
430 {$MESSAGE warn 'GLB_NATIVE_OGL_STATIC will be ignored because you enabled GLB_NATIVE_OGL_DYNAMIC'}
444 {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF}
445 {$IF DEFINED(GLB_WIN) AND
446 (DEFINED(GLB_NATIVE_OGL) OR
447 DEFINED(GLB_DELPHI))} windows, {$IFEND}
449 {$IFDEF GLB_SDL} SDL, {$ENDIF}
450 {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, Graphics, {$ENDIF}
451 {$IFDEF GLB_DELPHI} Dialogs, Graphics, Types, {$ENDIF}
453 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
454 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
455 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
456 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
457 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
461 {$IFDEF GLB_NATIVE_OGL}
470 GL_EXTENSIONS = $1F03;
472 GL_TEXTURE_1D = $0DE0;
473 GL_TEXTURE_2D = $0DE1;
474 GL_TEXTURE_RECTANGLE = $84F5;
476 GL_NORMAL_MAP = $8511;
477 GL_TEXTURE_CUBE_MAP = $8513;
478 GL_REFLECTION_MAP = $8512;
479 GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515;
480 GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516;
481 GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517;
482 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518;
483 GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519;
484 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A;
486 GL_TEXTURE_WIDTH = $1000;
487 GL_TEXTURE_HEIGHT = $1001;
488 GL_TEXTURE_INTERNAL_FORMAT = $1003;
489 GL_TEXTURE_SWIZZLE_RGBA = $8E46;
496 GL_TEXTURE_GEN_S = $0C60;
497 GL_TEXTURE_GEN_T = $0C61;
498 GL_TEXTURE_GEN_R = $0C62;
499 GL_TEXTURE_GEN_Q = $0C63;
511 GL_LUMINANCE = $1909;
512 GL_LUMINANCE4 = $803F;
513 GL_LUMINANCE8 = $8040;
514 GL_LUMINANCE12 = $8041;
515 GL_LUMINANCE16 = $8042;
517 GL_LUMINANCE_ALPHA = $190A;
518 GL_LUMINANCE4_ALPHA4 = $8043;
519 GL_LUMINANCE6_ALPHA2 = $8044;
520 GL_LUMINANCE8_ALPHA8 = $8045;
521 GL_LUMINANCE12_ALPHA4 = $8046;
522 GL_LUMINANCE12_ALPHA12 = $8047;
523 GL_LUMINANCE16_ALPHA16 = $8048;
546 GL_DEPTH_COMPONENT = $1902;
547 GL_DEPTH_COMPONENT16 = $81A5;
548 GL_DEPTH_COMPONENT24 = $81A6;
549 GL_DEPTH_COMPONENT32 = $81A7;
551 GL_COMPRESSED_RGB = $84ED;
552 GL_COMPRESSED_RGBA = $84EE;
553 GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
554 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
555 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
556 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
558 GL_UNSIGNED_BYTE = $1401;
559 GL_UNSIGNED_BYTE_3_3_2 = $8032;
560 GL_UNSIGNED_BYTE_2_3_3_REV = $8362;
562 GL_UNSIGNED_SHORT = $1403;
563 GL_UNSIGNED_SHORT_5_6_5 = $8363;
564 GL_UNSIGNED_SHORT_4_4_4_4 = $8033;
565 GL_UNSIGNED_SHORT_5_5_5_1 = $8034;
566 GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
567 GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
568 GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
570 GL_UNSIGNED_INT = $1405;
571 GL_UNSIGNED_INT_8_8_8_8 = $8035;
572 GL_UNSIGNED_INT_10_10_10_2 = $8036;
573 GL_UNSIGNED_INT_8_8_8_8_REV = $8367;
574 GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
577 GL_TEXTURE_MAG_FILTER = $2800;
578 GL_TEXTURE_MIN_FILTER = $2801;
580 GL_NEAREST_MIPMAP_NEAREST = $2700;
581 GL_NEAREST_MIPMAP_LINEAR = $2702;
583 GL_LINEAR_MIPMAP_NEAREST = $2701;
584 GL_LINEAR_MIPMAP_LINEAR = $2703;
587 GL_TEXTURE_WRAP_S = $2802;
588 GL_TEXTURE_WRAP_T = $2803;
589 GL_TEXTURE_WRAP_R = $8072;
592 GL_CLAMP_TO_EDGE = $812F;
593 GL_CLAMP_TO_BORDER = $812D;
594 GL_MIRRORED_REPEAT = $8370;
597 GL_GENERATE_MIPMAP = $8191;
598 GL_TEXTURE_BORDER_COLOR = $1004;
599 GL_MAX_TEXTURE_SIZE = $0D33;
600 GL_PACK_ALIGNMENT = $0D05;
601 GL_UNPACK_ALIGNMENT = $0CF5;
603 GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
604 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
605 GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C;
606 GL_TEXTURE_GEN_MODE = $2500;
608 {$IF DEFINED(GLB_WIN)}
609 libglu = 'glu32.dll';
610 libopengl = 'opengl32.dll';
611 {$ELSEIF DEFINED(GLB_LINUX)}
612 libglu = 'libGLU.so.1';
613 libopengl = 'libGL.so.1';
617 GLboolean = BYTEBOOL;
625 PGLboolean = ^GLboolean;
630 TglCompressedTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
631 TglCompressedTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
632 TglGetCompressedTexImage = procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
634 {$IF DEFINED(GLB_WIN)}
635 TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall;
636 {$ELSEIF DEFINED(GLB_LINUX)}
637 TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl;
638 TglXGetProcAddressARB = function(const name: PAnsiChar): pointer; cdecl;
641 {$IF DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
642 TglEnable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
643 TglDisable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
645 TglGetString = function(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
646 TglGetIntegerv = procedure(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
648 TglTexParameteri = procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
649 TglTexParameteriv = procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
650 TglTexParameterfv = procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
651 TglGetTexParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
652 TglGetTexParameterfv = procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
653 TglGetTexLevelParameteriv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
654 TglGetTexLevelParameterfv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
656 TglTexGeni = procedure(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
657 TglGenTextures = procedure(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
658 TglBindTexture = procedure(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
659 TglDeleteTextures = procedure(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
661 TglAreTexturesResident = function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
662 TglReadPixels = procedure(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
663 TglPixelStorei = procedure(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
665 TglTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
666 TglTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
667 TglGetTexImage = procedure(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
669 TgluBuild1DMipmaps = function(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
670 TgluBuild2DMipmaps = function(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
672 {$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)}
673 procedure glEnable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
674 procedure glDisable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
676 function glGetString(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
677 procedure glGetIntegerv(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
679 procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
680 procedure glTexParameteriv(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
681 procedure glTexParameterfv(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
682 procedure glGetTexParameteriv(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
683 procedure glGetTexParameterfv(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
684 procedure glGetTexLevelParameteriv(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
685 procedure glGetTexLevelParameterfv(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
687 procedure glTexGeni(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
688 procedure glGenTextures(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
689 procedure glBindTexture(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
690 procedure glDeleteTextures(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
692 function glAreTexturesResident(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
693 procedure glReadPixels(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
694 procedure glPixelStorei(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
696 procedure glTexImage1D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
697 procedure glTexImage2D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
698 procedure glGetTexImage(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
700 function gluBuild1DMipmaps(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
701 function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
711 GL_SGIS_generate_mipmap,
713 GL_ARB_texture_border_clamp,
714 GL_ARB_texture_mirrored_repeat,
715 GL_ARB_texture_rectangle,
716 GL_ARB_texture_non_power_of_two,
717 GL_ARB_texture_swizzle,
718 GL_ARB_texture_cube_map,
720 GL_IBM_texture_mirrored_repeat,
722 GL_NV_texture_rectangle,
724 GL_EXT_texture_edge_clamp,
725 GL_EXT_texture_rectangle,
726 GL_EXT_texture_swizzle,
727 GL_EXT_texture_cube_map,
728 GL_EXT_texture_filter_anisotropic: Boolean;
730 glCompressedTexImage1D: TglCompressedTexImage1D;
731 glCompressedTexImage2D: TglCompressedTexImage2D;
732 glGetCompressedTexImage: TglGetCompressedTexImage;
734 {$IF DEFINED(GLB_WIN)}
735 wglGetProcAddress: TwglGetProcAddress;
736 {$ELSEIF DEFINED(GLB_LINUX)}
737 glXGetProcAddress: TglXGetProcAddress;
738 glXGetProcAddressARB: TglXGetProcAddress;
741 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
743 glDisable: TglDisable;
745 glGetString: TglGetString;
746 glGetIntegerv: TglGetIntegerv;
748 glTexParameteri: TglTexParameteri;
749 glTexParameteriv: TglTexParameteriv;
750 glTexParameterfv: TglTexParameterfv;
751 glGetTexParameteriv: TglGetTexParameteriv;
752 glGetTexParameterfv: TglGetTexParameterfv;
753 glGetTexLevelParameteriv: TglGetTexLevelParameteriv;
754 glGetTexLevelParameterfv: TglGetTexLevelParameterfv;
756 glTexGeni: TglTexGeni;
757 glGenTextures: TglGenTextures;
758 glBindTexture: TglBindTexture;
759 glDeleteTextures: TglDeleteTextures;
761 glAreTexturesResident: TglAreTexturesResident;
762 glReadPixels: TglReadPixels;
763 glPixelStorei: TglPixelStorei;
765 glTexImage1D: TglTexImage1D;
766 glTexImage2D: TglTexImage2D;
767 glGetTexImage: TglGetTexImage;
769 gluBuild1DMipmaps: TgluBuild1DMipmaps;
770 gluBuild2DMipmaps: TgluBuild2DMipmaps;
775 ////////////////////////////////////////////////////////////////////////////////////////////////////
777 tfEmpty = 0, //must be smallest value!
793 tfLuminance12Alpha12,
794 tfLuminance16Alpha16,
838 TglBitmapFileType = (
839 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
840 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
844 TglBitmapFileTypes = set of TglBitmapFileType;
851 TglBitmapNormalMapFunc = (
857 ////////////////////////////////////////////////////////////////////////////////////////////////////
858 EglBitmap = class(Exception);
859 EglBitmapNotSupported = class(Exception);
860 EglBitmapSizeToLarge = class(EglBitmap);
861 EglBitmapNonPowerOfTwo = class(EglBitmap);
862 EglBitmapUnsupportedFormat = class(EglBitmap)
864 constructor Create(const aFormat: TglBitmapFormat); overload;
865 constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload;
868 ////////////////////////////////////////////////////////////////////////////////////////////////////
869 TglBitmapColorRec = packed record
871 0: (r, g, b, a: Cardinal);
872 1: (arr: array[0..3] of Cardinal);
875 TglBitmapPixelData = packed record
876 Data, Range: TglBitmapColorRec;
877 Format: TglBitmapFormat;
879 PglBitmapPixelData = ^TglBitmapPixelData;
881 ////////////////////////////////////////////////////////////////////////////////////////////////////
882 TglBitmapPixelPositionFields = set of (ffX, ffY);
883 TglBitmapPixelPosition = record
884 Fields : TglBitmapPixelPositionFields;
889 TglBitmapFormatDescriptor = class(TObject)
891 function GetIsCompressed: Boolean; virtual; abstract;
892 function GetHasAlpha: Boolean; virtual; abstract;
894 function GetglDataFormat: GLenum; virtual; abstract;
895 function GetglFormat: GLenum; virtual; abstract;
896 function GetglInternalFormat: GLenum; virtual; abstract;
898 property IsCompressed: Boolean read GetIsCompressed;
899 property HasAlpha: Boolean read GetHasAlpha;
901 property glFormat: GLenum read GetglFormat;
902 property glInternalFormat: GLenum read GetglInternalFormat;
903 property glDataFormat: GLenum read GetglDataFormat;
906 ////////////////////////////////////////////////////////////////////////////////////////////////////
908 TglBitmapFunctionRec = record
910 Size: TglBitmapPixelPosition;
911 Position: TglBitmapPixelPosition;
912 Source: TglBitmapPixelData;
913 Dest: TglBitmapPixelData;
916 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
918 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
921 function GetFormatDesc: TglBitmapFormatDescriptor;
925 fAnisotropic: Integer;
926 fDeleteTextureOnFree: Boolean;
927 fFreeDataOnDestroy: Boolean;
928 fFreeDataAfterGenTexture: Boolean;
930 fIsResident: Boolean;
931 fBorderColor: array[0..3] of Single;
933 fDimension: TglBitmapPixelPosition;
934 fMipMap: TglBitmapMipMap;
935 fFormat: TglBitmapFormat;
951 fSwizzle: array[0..3] of GLenum;
956 fCustomNameW: WideString;
957 fCustomData: Pointer;
960 function GetWidth: Integer; virtual;
961 function GetHeight: Integer; virtual;
963 function GetFileWidth: Integer; virtual;
964 function GetFileHeight: Integer; virtual;
967 procedure SetCustomData(const aValue: Pointer);
968 procedure SetCustomName(const aValue: String);
969 procedure SetCustomNameW(const aValue: WideString);
970 procedure SetFreeDataOnDestroy(const aValue: Boolean);
971 procedure SetDeleteTextureOnFree(const aValue: Boolean);
972 procedure SetFormat(const aValue: TglBitmapFormat);
973 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
974 procedure SetID(const aValue: Cardinal);
975 procedure SetMipMap(const aValue: TglBitmapMipMap);
976 procedure SetTarget(const aValue: Cardinal);
977 procedure SetAnisotropic(const aValue: Integer);
980 procedure SetupParameters(out aBuildWithGlu: Boolean);
981 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
982 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; //be careful, aData could be freed by this method
983 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
985 function FlipHorz: Boolean; virtual;
986 function FlipVert: Boolean; virtual;
988 property Width: Integer read GetWidth;
989 property Height: Integer read GetHeight;
991 property FileWidth: Integer read GetFileWidth;
992 property FileHeight: Integer read GetFileHeight;
995 property ID: Cardinal read fID write SetID;
996 property Target: Cardinal read fTarget write SetTarget;
997 property Format: TglBitmapFormat read fFormat write SetFormat;
998 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
999 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
1001 property FormatDesc: TglBitmapFormatDescriptor read GetFormatDesc;
1003 property Filename: String read fFilename;
1004 property CustomName: String read fCustomName write SetCustomName;
1005 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
1006 property CustomData: Pointer read fCustomData write SetCustomData;
1008 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
1009 property FreeDataOnDestroy: Boolean read fFreeDataOnDestroy write SetFreeDataOnDestroy;
1010 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
1012 property Dimension: TglBitmapPixelPosition read fDimension;
1013 property Data: PByte read fData;
1014 property IsResident: Boolean read fIsResident;
1016 procedure AfterConstruction; override;
1017 procedure BeforeDestruction; override;
1019 procedure PrepareResType(var aResource: String; var aResType: PChar);
1022 procedure LoadFromFile(const aFilename: String);
1023 procedure LoadFromStream(const aStream: TStream); virtual;
1024 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
1025 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil);
1026 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil);
1027 procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
1030 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
1031 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
1034 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
1035 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
1036 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
1040 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
1041 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
1042 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
1043 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
1044 const aArgs: Pointer = nil): Boolean;
1048 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
1049 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
1050 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
1051 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
1052 const aArgs: Pointer = nil): Boolean;
1055 {$IFDEF GLB_LAZARUS}
1056 function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1057 function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
1058 function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1059 function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil;
1060 const aArgs: Pointer = nil): Boolean;
1063 function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil;
1064 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1065 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
1066 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1068 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
1069 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1070 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1071 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1073 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
1074 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
1075 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
1077 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
1078 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
1079 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
1081 function RemoveAlpha: Boolean; virtual;
1084 function Clone: TglBitmap;
1085 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
1086 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
1087 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
1091 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
1092 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
1093 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
1096 procedure SetFilter(const aMin, aMag: GLenum);
1098 const S: GLenum = GL_CLAMP_TO_EDGE;
1099 const T: GLenum = GL_CLAMP_TO_EDGE;
1100 const R: GLenum = GL_CLAMP_TO_EDGE);
1101 procedure SetSwizzle(const r, g, b, a: GLenum);
1103 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
1104 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
1107 constructor Create; overload;
1108 constructor Create(const aFileName: String); overload;
1109 constructor Create(const aStream: TStream); overload;
1110 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte = nil); overload;
1111 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
1112 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
1113 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
1115 {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1116 {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF}
1118 {$IFDEF GLB_SUPPORT_JPEG_READ} function LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1119 {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF}
1121 function LoadBMP(const aStream: TStream): Boolean; virtual;
1122 procedure SaveBMP(const aStream: TStream); virtual;
1124 function LoadTGA(const aStream: TStream): Boolean; virtual;
1125 procedure SaveTGA(const aStream: TStream); virtual;
1127 function LoadDDS(const aStream: TStream): Boolean; virtual;
1128 procedure SaveDDS(const aStream: TStream); virtual;
1131 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1132 TglBitmap1D = class(TglBitmap)
1134 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1135 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1136 procedure UploadData(const aBuildWithGlu: Boolean);
1139 procedure AfterConstruction; override;
1140 function FlipHorz: Boolean; override;
1141 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1144 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1145 TglBitmap2D = class(TglBitmap)
1147 fLines: array of PByte;
1148 function GetScanline(const aIndex: Integer): Pointer;
1149 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1150 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1151 procedure UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
1155 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
1157 procedure AfterConstruction; override;
1159 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
1160 procedure GetDataFromTexture;
1161 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1163 function FlipHorz: Boolean; override;
1164 function FlipVert: Boolean; override;
1166 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
1167 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1170 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1171 TglBitmapCubeMap = class(TglBitmap2D)
1174 procedure GenTexture(const aTestTextureSize: Boolean = true); reintroduce;
1176 procedure AfterConstruction; override;
1177 procedure GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean = true);
1178 procedure Bind(const aEnableTexCoordsGen: Boolean = true; const aEnableTextureUnit: Boolean = true); reintroduce; virtual;
1179 procedure Unbind(const aDisableTexCoordsGen: Boolean = true; const aDisableTextureUnit: Boolean = true); reintroduce; virtual;
1182 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1183 TglBitmapNormalMap = class(TglBitmapCubeMap)
1185 procedure AfterConstruction; override;
1186 procedure GenerateNormalMap(const aSize: Integer = 32; const aTestTextureSize: Boolean = true);
1190 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1192 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1193 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1194 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1195 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1196 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1197 procedure glBitmapSetDefaultWrap(
1198 const S: Cardinal = GL_CLAMP_TO_EDGE;
1199 const T: Cardinal = GL_CLAMP_TO_EDGE;
1200 const R: Cardinal = GL_CLAMP_TO_EDGE);
1202 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1203 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1204 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1205 function glBitmapGetDefaultFormat: TglBitmapFormat;
1206 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1207 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1209 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1210 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1211 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1214 glBitmapDefaultDeleteTextureOnFree: Boolean;
1215 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1216 glBitmapDefaultFormat: TglBitmapFormat;
1217 glBitmapDefaultMipmap: TglBitmapMipMap;
1218 glBitmapDefaultFilterMin: Cardinal;
1219 glBitmapDefaultFilterMag: Cardinal;
1220 glBitmapDefaultWrapS: Cardinal;
1221 glBitmapDefaultWrapT: Cardinal;
1222 glBitmapDefaultWrapR: Cardinal;
1223 glDefaultSwizzle: array[0..3] of GLenum;
1226 function CreateGrayPalette: HPALETTE;
1232 Math, syncobjs, typinfo
1233 {$IFDEF GLB_DELPHI}, Types{$ENDIF};
1237 QWord = System.UInt64;
1244 ////////////////////////////////////////////////////////////////////////////////////////////////////
1245 TShiftRec = packed record
1247 0: (r, g, b, a: Byte);
1248 1: (arr: array[0..3] of Byte);
1251 TFormatDescriptor = class(TglBitmapFormatDescriptor)
1253 function GetRedMask: QWord;
1254 function GetGreenMask: QWord;
1255 function GetBlueMask: QWord;
1256 function GetAlphaMask: QWord;
1258 fFormat: TglBitmapFormat;
1259 fWithAlpha: TglBitmapFormat;
1260 fWithoutAlpha: TglBitmapFormat;
1261 fRGBInverted: TglBitmapFormat;
1262 fUncompressed: TglBitmapFormat;
1264 fIsCompressed: Boolean;
1266 fRange: TglBitmapColorRec;
1270 fglInternalFormat: GLenum;
1271 fglDataFormat: GLenum;
1273 function GetIsCompressed: Boolean; override;
1274 function GetHasAlpha: Boolean; override;
1276 function GetglFormat: GLenum; override;
1277 function GetglInternalFormat: GLenum; override;
1278 function GetglDataFormat: GLenum; override;
1280 function GetComponents: Integer; virtual;
1282 property Format: TglBitmapFormat read fFormat;
1283 property WithAlpha: TglBitmapFormat read fWithAlpha;
1284 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1285 property RGBInverted: TglBitmapFormat read fRGBInverted;
1286 property Components: Integer read GetComponents;
1287 property PixelSize: Single read fPixelSize;
1289 property Range: TglBitmapColorRec read fRange;
1290 property Shift: TShiftRec read fShift;
1292 property RedMask: QWord read GetRedMask;
1293 property GreenMask: QWord read GetGreenMask;
1294 property BlueMask: QWord read GetBlueMask;
1295 property AlphaMask: QWord read GetAlphaMask;
1297 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1298 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1300 function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual;
1301 function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
1303 function CreateMappingData: Pointer; virtual;
1304 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1306 function IsEmpty: Boolean; virtual;
1307 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual;
1309 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1311 constructor Create; virtual;
1313 class procedure Init;
1314 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1315 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1316 class procedure Clear;
1317 class procedure Finalize;
1319 TFormatDescriptorClass = class of TFormatDescriptor;
1321 TfdEmpty = class(TFormatDescriptor);
1323 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1324 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1325 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1326 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1327 constructor Create; override;
1330 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1331 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1332 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1333 constructor Create; override;
1336 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1337 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1338 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1339 constructor Create; override;
1342 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1343 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1344 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1345 constructor Create; override;
1348 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1349 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1350 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1351 constructor Create; override;
1354 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1355 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1356 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1357 constructor Create; override;
1360 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1361 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1362 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1363 constructor Create; override;
1366 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1367 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1368 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1369 constructor Create; override;
1372 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1373 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1374 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1375 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1376 constructor Create; override;
1379 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1380 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1381 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1382 constructor Create; override;
1385 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1386 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1387 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1388 constructor Create; override;
1391 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1392 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1393 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1394 constructor Create; override;
1397 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1398 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1399 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1400 constructor Create; override;
1403 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1404 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1405 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1406 constructor Create; override;
1409 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1410 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1411 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1412 constructor Create; override;
1415 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1416 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1417 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1418 constructor Create; override;
1421 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1422 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1423 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1424 constructor Create; override;
1427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1428 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1429 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1430 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1431 constructor Create; override;
1434 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1435 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1436 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1437 constructor Create; override;
1440 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1441 TfdAlpha4 = class(TfdAlpha_UB1)
1442 constructor Create; override;
1445 TfdAlpha8 = class(TfdAlpha_UB1)
1446 constructor Create; override;
1449 TfdAlpha12 = class(TfdAlpha_US1)
1450 constructor Create; override;
1453 TfdAlpha16 = class(TfdAlpha_US1)
1454 constructor Create; override;
1457 TfdLuminance4 = class(TfdLuminance_UB1)
1458 constructor Create; override;
1461 TfdLuminance8 = class(TfdLuminance_UB1)
1462 constructor Create; override;
1465 TfdLuminance12 = class(TfdLuminance_US1)
1466 constructor Create; override;
1469 TfdLuminance16 = class(TfdLuminance_US1)
1470 constructor Create; override;
1473 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1474 constructor Create; override;
1477 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1478 constructor Create; override;
1481 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1482 constructor Create; override;
1485 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1486 constructor Create; override;
1489 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1490 constructor Create; override;
1493 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1494 constructor Create; override;
1497 TfdR3G3B2 = class(TfdUniversal_UB1)
1498 constructor Create; override;
1501 TfdRGB4 = class(TfdUniversal_US1)
1502 constructor Create; override;
1505 TfdR5G6B5 = class(TfdUniversal_US1)
1506 constructor Create; override;
1509 TfdRGB5 = class(TfdUniversal_US1)
1510 constructor Create; override;
1513 TfdRGB8 = class(TfdRGB_UB3)
1514 constructor Create; override;
1517 TfdRGB10 = class(TfdUniversal_UI1)
1518 constructor Create; override;
1521 TfdRGB12 = class(TfdRGB_US3)
1522 constructor Create; override;
1525 TfdRGB16 = class(TfdRGB_US3)
1526 constructor Create; override;
1529 TfdRGBA2 = class(TfdRGBA_UB4)
1530 constructor Create; override;
1533 TfdRGBA4 = class(TfdUniversal_US1)
1534 constructor Create; override;
1537 TfdRGB5A1 = class(TfdUniversal_US1)
1538 constructor Create; override;
1541 TfdRGBA8 = class(TfdRGBA_UB4)
1542 constructor Create; override;
1545 TfdRGB10A2 = class(TfdUniversal_UI1)
1546 constructor Create; override;
1549 TfdRGBA12 = class(TfdRGBA_US4)
1550 constructor Create; override;
1553 TfdRGBA16 = class(TfdRGBA_US4)
1554 constructor Create; override;
1557 TfdBGR4 = class(TfdUniversal_US1)
1558 constructor Create; override;
1561 TfdB5G6R5 = class(TfdUniversal_US1)
1562 constructor Create; override;
1565 TfdBGR5 = class(TfdUniversal_US1)
1566 constructor Create; override;
1569 TfdBGR8 = class(TfdBGR_UB3)
1570 constructor Create; override;
1573 TfdBGR10 = class(TfdUniversal_UI1)
1574 constructor Create; override;
1577 TfdBGR12 = class(TfdBGR_US3)
1578 constructor Create; override;
1581 TfdBGR16 = class(TfdBGR_US3)
1582 constructor Create; override;
1585 TfdBGRA2 = class(TfdBGRA_UB4)
1586 constructor Create; override;
1589 TfdBGRA4 = class(TfdUniversal_US1)
1590 constructor Create; override;
1593 TfdBGR5A1 = class(TfdUniversal_US1)
1594 constructor Create; override;
1597 TfdBGRA8 = class(TfdBGRA_UB4)
1598 constructor Create; override;
1601 TfdBGR10A2 = class(TfdUniversal_UI1)
1602 constructor Create; override;
1605 TfdBGRA12 = class(TfdBGRA_US4)
1606 constructor Create; override;
1609 TfdBGRA16 = class(TfdBGRA_US4)
1610 constructor Create; override;
1613 TfdDepth16 = class(TfdDepth_US1)
1614 constructor Create; override;
1617 TfdDepth24 = class(TfdDepth_UI1)
1618 constructor Create; override;
1621 TfdDepth32 = class(TfdDepth_UI1)
1622 constructor Create; override;
1625 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1626 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1627 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1628 constructor Create; override;
1631 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1632 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1633 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1634 constructor Create; override;
1637 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1638 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1639 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1640 constructor Create; override;
1643 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1644 TbmpBitfieldFormat = class(TFormatDescriptor)
1646 procedure SetRedMask (const aValue: QWord);
1647 procedure SetGreenMask(const aValue: QWord);
1648 procedure SetBlueMask (const aValue: QWord);
1649 procedure SetAlphaMask(const aValue: QWord);
1651 procedure Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte);
1653 property RedMask: QWord read GetRedMask write SetRedMask;
1654 property GreenMask: QWord read GetGreenMask write SetGreenMask;
1655 property BlueMask: QWord read GetBlueMask write SetBlueMask;
1656 property AlphaMask: QWord read GetAlphaMask write SetAlphaMask;
1658 property PixelSize: Single read fPixelSize write fPixelSize;
1660 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1661 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1664 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1665 TbmpColorTableEnty = packed record
1668 TbmpColorTable = array of TbmpColorTableEnty;
1669 TbmpColorTableFormat = class(TFormatDescriptor)
1671 fColorTable: TbmpColorTable;
1673 property PixelSize: Single read fPixelSize write fPixelSize;
1674 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1675 property Range: TglBitmapColorRec read fRange write fRange;
1676 property Shift: TShiftRec read fShift write fShift;
1677 property Format: TglBitmapFormat read fFormat write fFormat;
1679 procedure CreateColorTable;
1681 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1682 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1683 destructor Destroy; override;
1687 LUMINANCE_WEIGHT_R = 0.30;
1688 LUMINANCE_WEIGHT_G = 0.59;
1689 LUMINANCE_WEIGHT_B = 0.11;
1691 ALPHA_WEIGHT_R = 0.30;
1692 ALPHA_WEIGHT_G = 0.59;
1693 ALPHA_WEIGHT_B = 0.11;
1695 DEPTH_WEIGHT_R = 0.333333333;
1696 DEPTH_WEIGHT_G = 0.333333333;
1697 DEPTH_WEIGHT_B = 0.333333333;
1699 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1701 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1714 TfdLuminance4Alpha4,
1715 TfdLuminance6Alpha2,
1716 TfdLuminance8Alpha8,
1717 TfdLuminance12Alpha4,
1718 TfdLuminance12Alpha12,
1719 TfdLuminance16Alpha16,
1764 FormatDescriptorCS: TCriticalSection;
1765 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1767 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1768 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1770 inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1773 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1774 constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat);
1776 inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1779 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1780 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1782 result.Fields := [];
1785 result.Fields := result.Fields + [ffX];
1787 result.Fields := result.Fields + [ffY];
1789 result.X := Max(0, X);
1790 result.Y := Max(0, Y);
1793 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1794 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1802 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1803 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1808 for i := 0 to high(r1.arr) do
1809 if (r1.arr[i] <> r2.arr[i]) then
1814 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1815 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1823 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1824 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1833 tfR3G3B2, tfLuminance8,
1836 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1837 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1843 tfRGB10, tfRGB10A2, tfRGBA8,
1844 tfBGR10, tfBGR10A2, tfBGRA8]) then
1845 result := result + [ftBMP];
1849 tfLuminance8, tfAlpha8,
1852 tfLuminance16, tfLuminance8Alpha8,
1853 tfRGB5, tfRGB5A1, tfRGBA4,
1854 tfBGR5, tfBGR5A1, tfBGRA4,
1860 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1861 result := result + [ftTGA];
1865 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1866 tfR3G3B2, tfRGBA2, tfBGRA2,
1869 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1870 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1871 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1877 tfLuminance16Alpha16,
1882 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1883 result := result + [ftDDS];
1885 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1887 tfAlpha8, tfLuminance8, tfLuminance8Alpha8,
1889 tfBGR8, tfBGRA8] then
1890 result := result + [ftPNG];
1893 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1894 if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then
1895 result := result + [ftJPEG];
1899 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1900 function IsPowerOfTwo(aNumber: Integer): Boolean;
1902 while (aNumber and 1) = 0 do
1903 aNumber := aNumber shr 1;
1904 result := aNumber = 1;
1907 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1908 function GetTopMostBit(aBitSet: QWord): Integer;
1911 while aBitSet > 0 do begin
1913 aBitSet := aBitSet shr 1;
1917 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1918 function CountSetBits(aBitSet: QWord): Integer;
1921 while aBitSet > 0 do begin
1922 if (aBitSet and 1) = 1 then
1924 aBitSet := aBitSet shr 1;
1928 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1929 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1932 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1933 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1934 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1937 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1938 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1941 DEPTH_WEIGHT_R * aPixel.Data.r +
1942 DEPTH_WEIGHT_G * aPixel.Data.g +
1943 DEPTH_WEIGHT_B * aPixel.Data.b);
1946 {$IFDEF GLB_NATIVE_OGL}
1947 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1948 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1949 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1951 GL_LibHandle: Pointer = nil;
1953 function glbGetProcAddress(aProcName: PAnsiChar; aLibHandle: Pointer = nil; const aRaiseOnErr: Boolean = true): Pointer;
1955 if not Assigned(aLibHandle) then
1956 aLibHandle := GL_LibHandle;
1958 {$IF DEFINED(GLB_WIN)}
1959 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1960 if Assigned(result) then
1963 if Assigned(wglGetProcAddress) then
1964 result := wglGetProcAddress(aProcName);
1965 {$ELSEIF DEFINED(GLB_LINUX)}
1966 if Assigned(glXGetProcAddress) then begin
1967 result := glXGetProcAddress(aProcName);
1968 if Assigned(result) then
1972 if Assigned(glXGetProcAddressARB) then begin
1973 result := glXGetProcAddressARB(aProcName);
1974 if Assigned(result) then
1978 result := dlsym(aLibHandle, aProcName);
1980 if not Assigned(result) and aRaiseOnErr then
1981 raise EglBitmap.Create('unable to load procedure form library: ' + aProcName);
1984 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1986 GLU_LibHandle: Pointer = nil;
1987 OpenGLInitialized: Boolean;
1988 InitOpenGLCS: TCriticalSection;
1990 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1991 procedure glbInitOpenGL;
1993 ////////////////////////////////////////////////////////////////////////////////
1994 function glbLoadLibrary(const aName: PChar): Pointer;
1996 {$IF DEFINED(GLB_WIN)}
1997 result := {%H-}Pointer(LoadLibrary(aName));
1998 {$ELSEIF DEFINED(GLB_LINUX)}
1999 result := dlopen(Name, RTLD_LAZY);
2005 ////////////////////////////////////////////////////////////////////////////////
2006 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
2009 if not Assigned(aLibHandle) then
2012 {$IF DEFINED(GLB_WIN)}
2013 Result := FreeLibrary({%H-}HINST(aLibHandle));
2014 {$ELSEIF DEFINED(GLB_LINUX)}
2015 Result := dlclose(aLibHandle) = 0;
2020 if Assigned(GL_LibHandle) then
2021 glbFreeLibrary(GL_LibHandle);
2023 if Assigned(GLU_LibHandle) then
2024 glbFreeLibrary(GLU_LibHandle);
2026 GL_LibHandle := glbLoadLibrary(libopengl);
2027 if not Assigned(GL_LibHandle) then
2028 raise EglBitmap.Create('unable to load library: ' + libopengl);
2030 GLU_LibHandle := glbLoadLibrary(libglu);
2031 if not Assigned(GLU_LibHandle) then
2032 raise EglBitmap.Create('unable to load library: ' + libglu);
2034 {$IF DEFINED(GLB_WIN)}
2035 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
2036 {$ELSEIF DEFINED(GLB_LINUX)}
2037 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
2038 glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
2041 glEnable := glbGetProcAddress('glEnable');
2042 glDisable := glbGetProcAddress('glDisable');
2043 glGetString := glbGetProcAddress('glGetString');
2044 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
2045 glTexParameteri := glbGetProcAddress('glTexParameteri');
2046 glTexParameteriv := glbGetProcAddress('glTexParameteriv');
2047 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
2048 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
2049 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
2050 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
2051 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
2052 glTexGeni := glbGetProcAddress('glTexGeni');
2053 glGenTextures := glbGetProcAddress('glGenTextures');
2054 glBindTexture := glbGetProcAddress('glBindTexture');
2055 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
2056 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
2057 glReadPixels := glbGetProcAddress('glReadPixels');
2058 glPixelStorei := glbGetProcAddress('glPixelStorei');
2059 glTexImage1D := glbGetProcAddress('glTexImage1D');
2060 glTexImage2D := glbGetProcAddress('glTexImage2D');
2061 glGetTexImage := glbGetProcAddress('glGetTexImage');
2063 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
2064 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
2068 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2069 procedure glbReadOpenGLExtensions;
2072 MajorVersion, MinorVersion: Integer;
2074 ///////////////////////////////////////////////////////////////////////////////////////////
2075 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
2082 Separator := Pos(AnsiString('.'), aBuffer);
2083 if (Separator > 1) and (Separator < Length(aBuffer)) and
2084 (aBuffer[Separator - 1] in ['0'..'9']) and
2085 (aBuffer[Separator + 1] in ['0'..'9']) then begin
2088 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
2091 Delete(aBuffer, 1, Separator);
2092 Separator := Pos(AnsiString('.'), aBuffer) + 1;
2094 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
2097 Delete(aBuffer, Separator, 255);
2098 Separator := Pos(AnsiString('.'), aBuffer);
2100 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
2101 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2105 ///////////////////////////////////////////////////////////////////////////////////////////
2106 function CheckExtension(const Extension: AnsiString): Boolean;
2110 ExtPos := Pos(Extension, Buffer);
2111 result := ExtPos > 0;
2113 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2116 ///////////////////////////////////////////////////////////////////////////////////////////
2117 function CheckVersion(const aMajor, aMinor: Integer): Boolean;
2119 result := (MajorVersion > aMajor) or ((MajorVersion = aMajor) and (MinorVersion >= aMinor));
2123 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2126 if not OpenGLInitialized then begin
2128 OpenGLInitialized := true;
2136 Buffer := glGetString(GL_VERSION);
2137 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2139 GL_VERSION_1_2 := CheckVersion(1, 2);
2140 GL_VERSION_1_3 := CheckVersion(1, 3);
2141 GL_VERSION_1_4 := CheckVersion(1, 4);
2142 GL_VERSION_2_0 := CheckVersion(2, 0);
2143 GL_VERSION_3_3 := CheckVersion(3, 3);
2146 Buffer := glGetString(GL_EXTENSIONS);
2147 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2148 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2149 GL_ARB_texture_swizzle := CheckExtension('GL_ARB_texture_swizzle');
2150 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
2151 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2152 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2153 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2154 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2155 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2156 GL_EXT_texture_swizzle := CheckExtension('GL_EXT_texture_swizzle');
2157 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
2158 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2159 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2160 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2162 if GL_VERSION_1_3 then begin
2163 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2164 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2165 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2167 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB', nil, false);
2168 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB', nil, false);
2169 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB', nil, false);
2174 {$IFDEF GLB_SDL_IMAGE}
2175 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2176 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2177 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2178 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2180 result := TStream(context^.unknown.data1).Seek(offset, whence);
2183 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2185 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2188 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2190 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2193 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2198 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2200 result := SDL_AllocRW;
2202 if result = nil then
2203 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2205 result^.seek := glBitmapRWseek;
2206 result^.read := glBitmapRWread;
2207 result^.write := glBitmapRWwrite;
2208 result^.close := glBitmapRWclose;
2209 result^.unknown.data1 := Stream;
2213 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2214 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2216 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2219 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2220 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2222 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2226 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2228 glBitmapDefaultMipmap := aValue;
2231 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2232 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2234 glBitmapDefaultFormat := aFormat;
2237 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2238 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2240 glBitmapDefaultFilterMin := aMin;
2241 glBitmapDefaultFilterMag := aMag;
2244 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2245 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2247 glBitmapDefaultWrapS := S;
2248 glBitmapDefaultWrapT := T;
2249 glBitmapDefaultWrapR := R;
2252 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2253 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
2255 glDefaultSwizzle[0] := r;
2256 glDefaultSwizzle[1] := g;
2257 glDefaultSwizzle[2] := b;
2258 glDefaultSwizzle[3] := a;
2261 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2262 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2264 result := glBitmapDefaultDeleteTextureOnFree;
2267 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2268 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2270 result := glBitmapDefaultFreeDataAfterGenTextures;
2273 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2274 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2276 result := glBitmapDefaultMipmap;
2279 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2280 function glBitmapGetDefaultFormat: TglBitmapFormat;
2282 result := glBitmapDefaultFormat;
2285 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2286 procedure glBitmapGetDefaultFilter(var aMin, aMag: GLenum);
2288 aMin := glBitmapDefaultFilterMin;
2289 aMag := glBitmapDefaultFilterMag;
2292 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2293 procedure glBitmapGetDefaultTextureWrap(var S, T, R: GLenum);
2295 S := glBitmapDefaultWrapS;
2296 T := glBitmapDefaultWrapT;
2297 R := glBitmapDefaultWrapR;
2300 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2301 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
2303 r := glDefaultSwizzle[0];
2304 g := glDefaultSwizzle[1];
2305 b := glDefaultSwizzle[2];
2306 a := glDefaultSwizzle[3];
2309 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2310 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2311 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2312 function TFormatDescriptor.GetRedMask: QWord;
2314 result := fRange.r shl fShift.r;
2317 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2318 function TFormatDescriptor.GetGreenMask: QWord;
2320 result := fRange.g shl fShift.g;
2323 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2324 function TFormatDescriptor.GetBlueMask: QWord;
2326 result := fRange.b shl fShift.b;
2329 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2330 function TFormatDescriptor.GetAlphaMask: QWord;
2332 result := fRange.a shl fShift.a;
2335 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2336 function TFormatDescriptor.GetIsCompressed: Boolean;
2338 result := fIsCompressed;
2341 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2342 function TFormatDescriptor.GetHasAlpha: Boolean;
2344 result := (fRange.a > 0);
2347 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2348 function TFormatDescriptor.GetglFormat: GLenum;
2350 result := fglFormat;
2353 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2354 function TFormatDescriptor.GetglInternalFormat: GLenum;
2356 result := fglInternalFormat;
2359 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2360 function TFormatDescriptor.GetglDataFormat: GLenum;
2362 result := fglDataFormat;
2365 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2366 function TFormatDescriptor.GetComponents: Integer;
2372 if (fRange.arr[i] > 0) then
2376 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2377 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2381 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2382 w := Max(1, aSize.X);
2383 h := Max(1, aSize.Y);
2384 result := GetSize(w, h);
2389 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2390 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2393 if (aWidth <= 0) or (aHeight <= 0) then
2395 result := Ceil(aWidth * aHeight * fPixelSize);
2398 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2399 function TFormatDescriptor.CreateMappingData: Pointer;
2404 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2405 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2410 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2411 function TFormatDescriptor.IsEmpty: Boolean;
2413 result := (fFormat = tfEmpty);
2416 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2417 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2420 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2421 raise EglBitmap.Create('FormatCheckFormat - All Masks are 0');
2422 if (aRedMask <> RedMask) then
2424 if (aGreenMask <> GreenMask) then
2426 if (aBlueMask <> BlueMask) then
2428 if (aAlphaMask <> AlphaMask) then
2433 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2434 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2436 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2437 aPixel.Data := fRange;
2438 aPixel.Range := fRange;
2439 aPixel.Format := fFormat;
2442 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2443 constructor TFormatDescriptor.Create;
2448 fWithAlpha := tfEmpty;
2449 fWithoutAlpha := tfEmpty;
2450 fRGBInverted := tfEmpty;
2451 fUncompressed := tfEmpty;
2453 fIsCompressed := false;
2456 fglInternalFormat := 0;
2459 FillChar(fRange, 0, SizeOf(fRange));
2460 FillChar(fShift, 0, SizeOf(fShift));
2463 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2464 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2465 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2466 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2468 aData^ := aPixel.Data.a;
2472 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2477 aPixel.Data.a := aData^;
2481 constructor TfdAlpha_UB1.Create;
2486 fglFormat := GL_ALPHA;
2487 fglDataFormat := GL_UNSIGNED_BYTE;
2490 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2491 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2492 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2493 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2495 aData^ := LuminanceWeight(aPixel);
2499 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2501 aPixel.Data.r := aData^;
2502 aPixel.Data.g := aData^;
2503 aPixel.Data.b := aData^;
2508 constructor TfdLuminance_UB1.Create;
2515 fglFormat := GL_LUMINANCE;
2516 fglDataFormat := GL_UNSIGNED_BYTE;
2519 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2520 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2521 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2522 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2528 if (fRange.arr[i] > 0) then
2529 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2533 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2538 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2542 constructor TfdUniversal_UB1.Create;
2548 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2549 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2550 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2551 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2553 inherited Map(aPixel, aData, aMapData);
2554 aData^ := aPixel.Data.a;
2558 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2560 inherited Unmap(aData, aPixel, aMapData);
2561 aPixel.Data.a := aData^;
2565 constructor TfdLuminanceAlpha_UB2.Create;
2571 fglFormat := GL_LUMINANCE_ALPHA;
2572 fglDataFormat := GL_UNSIGNED_BYTE;
2575 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2576 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2577 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2578 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2580 aData^ := aPixel.Data.r;
2582 aData^ := aPixel.Data.g;
2584 aData^ := aPixel.Data.b;
2588 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2590 aPixel.Data.r := aData^;
2592 aPixel.Data.g := aData^;
2594 aPixel.Data.b := aData^;
2599 constructor TfdRGB_UB3.Create;
2609 fglFormat := GL_RGB;
2610 fglDataFormat := GL_UNSIGNED_BYTE;
2613 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2614 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2616 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2618 aData^ := aPixel.Data.b;
2620 aData^ := aPixel.Data.g;
2622 aData^ := aPixel.Data.r;
2626 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2628 aPixel.Data.b := aData^;
2630 aPixel.Data.g := aData^;
2632 aPixel.Data.r := aData^;
2637 constructor TfdBGR_UB3.Create;
2646 fglFormat := GL_BGR;
2647 fglDataFormat := GL_UNSIGNED_BYTE;
2650 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2651 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2652 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2653 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2655 inherited Map(aPixel, aData, aMapData);
2656 aData^ := aPixel.Data.a;
2660 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2662 inherited Unmap(aData, aPixel, aMapData);
2663 aPixel.Data.a := aData^;
2667 constructor TfdRGBA_UB4.Create;
2673 fglFormat := GL_RGBA;
2674 fglDataFormat := GL_UNSIGNED_BYTE;
2677 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2678 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2679 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2680 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2682 inherited Map(aPixel, aData, aMapData);
2683 aData^ := aPixel.Data.a;
2687 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2689 inherited Unmap(aData, aPixel, aMapData);
2690 aPixel.Data.a := aData^;
2694 constructor TfdBGRA_UB4.Create;
2700 fglFormat := GL_BGRA;
2701 fglDataFormat := GL_UNSIGNED_BYTE;
2704 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2705 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2706 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2707 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2709 PWord(aData)^ := aPixel.Data.a;
2713 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2718 aPixel.Data.a := PWord(aData)^;
2722 constructor TfdAlpha_US1.Create;
2727 fglFormat := GL_ALPHA;
2728 fglDataFormat := GL_UNSIGNED_SHORT;
2731 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2732 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2733 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2734 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2736 PWord(aData)^ := LuminanceWeight(aPixel);
2740 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2742 aPixel.Data.r := PWord(aData)^;
2743 aPixel.Data.g := PWord(aData)^;
2744 aPixel.Data.b := PWord(aData)^;
2749 constructor TfdLuminance_US1.Create;
2756 fglFormat := GL_LUMINANCE;
2757 fglDataFormat := GL_UNSIGNED_SHORT;
2760 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2761 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2762 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2763 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2769 if (fRange.arr[i] > 0) then
2770 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2774 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2779 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2783 constructor TfdUniversal_US1.Create;
2789 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2790 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2791 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2792 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2794 PWord(aData)^ := DepthWeight(aPixel);
2798 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2800 aPixel.Data.r := PWord(aData)^;
2801 aPixel.Data.g := PWord(aData)^;
2802 aPixel.Data.b := PWord(aData)^;
2807 constructor TfdDepth_US1.Create;
2814 fglFormat := GL_DEPTH_COMPONENT;
2815 fglDataFormat := GL_UNSIGNED_SHORT;
2818 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2819 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2820 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2821 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2823 inherited Map(aPixel, aData, aMapData);
2824 PWord(aData)^ := aPixel.Data.a;
2828 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2830 inherited Unmap(aData, aPixel, aMapData);
2831 aPixel.Data.a := PWord(aData)^;
2835 constructor TfdLuminanceAlpha_US2.Create;
2841 fglFormat := GL_LUMINANCE_ALPHA;
2842 fglDataFormat := GL_UNSIGNED_SHORT;
2845 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2846 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2847 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2848 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2850 PWord(aData)^ := aPixel.Data.r;
2852 PWord(aData)^ := aPixel.Data.g;
2854 PWord(aData)^ := aPixel.Data.b;
2858 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2860 aPixel.Data.r := PWord(aData)^;
2862 aPixel.Data.g := PWord(aData)^;
2864 aPixel.Data.b := PWord(aData)^;
2869 constructor TfdRGB_US3.Create;
2879 fglFormat := GL_RGB;
2880 fglDataFormat := GL_UNSIGNED_SHORT;
2883 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2884 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2885 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2886 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2888 PWord(aData)^ := aPixel.Data.b;
2890 PWord(aData)^ := aPixel.Data.g;
2892 PWord(aData)^ := aPixel.Data.r;
2896 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2898 aPixel.Data.b := PWord(aData)^;
2900 aPixel.Data.g := PWord(aData)^;
2902 aPixel.Data.r := PWord(aData)^;
2907 constructor TfdBGR_US3.Create;
2917 fglFormat := GL_BGR;
2918 fglDataFormat := GL_UNSIGNED_SHORT;
2921 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2922 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2923 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2924 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2926 inherited Map(aPixel, aData, aMapData);
2927 PWord(aData)^ := aPixel.Data.a;
2931 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2933 inherited Unmap(aData, aPixel, aMapData);
2934 aPixel.Data.a := PWord(aData)^;
2938 constructor TfdRGBA_US4.Create;
2944 fglFormat := GL_RGBA;
2945 fglDataFormat := GL_UNSIGNED_SHORT;
2948 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2949 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2950 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2951 procedure TfdBGRA_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 TfdBGRA_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 TfdBGRA_US4.Create;
2971 fglFormat := GL_BGRA;
2972 fglDataFormat := GL_UNSIGNED_SHORT;
2975 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2976 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2977 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2978 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2982 PCardinal(aData)^ := 0;
2984 if (fRange.arr[i] > 0) then
2985 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2989 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2994 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2998 constructor TfdUniversal_UI1.Create;
3004 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3005 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3006 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3007 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3009 PCardinal(aData)^ := DepthWeight(aPixel);
3013 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3015 aPixel.Data.r := PCardinal(aData)^;
3016 aPixel.Data.g := PCardinal(aData)^;
3017 aPixel.Data.b := PCardinal(aData)^;
3022 constructor TfdDepth_UI1.Create;
3026 fRange.r := $FFFFFFFF;
3027 fRange.g := $FFFFFFFF;
3028 fRange.b := $FFFFFFFF;
3029 fglFormat := GL_DEPTH_COMPONENT;
3030 fglDataFormat := GL_UNSIGNED_INT;
3033 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3034 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3035 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3036 constructor TfdAlpha4.Create;
3039 fFormat := tfAlpha4;
3040 fWithAlpha := tfAlpha4;
3041 fglInternalFormat := GL_ALPHA4;
3044 constructor TfdAlpha8.Create;
3047 fFormat := tfAlpha8;
3048 fWithAlpha := tfAlpha8;
3049 fglInternalFormat := GL_ALPHA8;
3052 constructor TfdAlpha12.Create;
3055 fFormat := tfAlpha12;
3056 fWithAlpha := tfAlpha12;
3057 fglInternalFormat := GL_ALPHA12;
3060 constructor TfdAlpha16.Create;
3063 fFormat := tfAlpha16;
3064 fWithAlpha := tfAlpha16;
3065 fglInternalFormat := GL_ALPHA16;
3068 constructor TfdLuminance4.Create;
3071 fFormat := tfLuminance4;
3072 fWithAlpha := tfLuminance4Alpha4;
3073 fWithoutAlpha := tfLuminance4;
3074 fglInternalFormat := GL_LUMINANCE4;
3077 constructor TfdLuminance8.Create;
3080 fFormat := tfLuminance8;
3081 fWithAlpha := tfLuminance8Alpha8;
3082 fWithoutAlpha := tfLuminance8;
3083 fglInternalFormat := GL_LUMINANCE8;
3086 constructor TfdLuminance12.Create;
3089 fFormat := tfLuminance12;
3090 fWithAlpha := tfLuminance12Alpha12;
3091 fWithoutAlpha := tfLuminance12;
3092 fglInternalFormat := GL_LUMINANCE12;
3095 constructor TfdLuminance16.Create;
3098 fFormat := tfLuminance16;
3099 fWithAlpha := tfLuminance16Alpha16;
3100 fWithoutAlpha := tfLuminance16;
3101 fglInternalFormat := GL_LUMINANCE16;
3104 constructor TfdLuminance4Alpha4.Create;
3107 fFormat := tfLuminance4Alpha4;
3108 fWithAlpha := tfLuminance4Alpha4;
3109 fWithoutAlpha := tfLuminance4;
3110 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3113 constructor TfdLuminance6Alpha2.Create;
3116 fFormat := tfLuminance6Alpha2;
3117 fWithAlpha := tfLuminance6Alpha2;
3118 fWithoutAlpha := tfLuminance8;
3119 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3122 constructor TfdLuminance8Alpha8.Create;
3125 fFormat := tfLuminance8Alpha8;
3126 fWithAlpha := tfLuminance8Alpha8;
3127 fWithoutAlpha := tfLuminance8;
3128 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3131 constructor TfdLuminance12Alpha4.Create;
3134 fFormat := tfLuminance12Alpha4;
3135 fWithAlpha := tfLuminance12Alpha4;
3136 fWithoutAlpha := tfLuminance12;
3137 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3140 constructor TfdLuminance12Alpha12.Create;
3143 fFormat := tfLuminance12Alpha12;
3144 fWithAlpha := tfLuminance12Alpha12;
3145 fWithoutAlpha := tfLuminance12;
3146 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3149 constructor TfdLuminance16Alpha16.Create;
3152 fFormat := tfLuminance16Alpha16;
3153 fWithAlpha := tfLuminance16Alpha16;
3154 fWithoutAlpha := tfLuminance16;
3155 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3158 constructor TfdR3G3B2.Create;
3161 fFormat := tfR3G3B2;
3162 fWithAlpha := tfRGBA2;
3163 fWithoutAlpha := tfR3G3B2;
3170 fglFormat := GL_RGB;
3171 fglInternalFormat := GL_R3_G3_B2;
3172 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3175 constructor TfdRGB4.Create;
3179 fWithAlpha := tfRGBA4;
3180 fWithoutAlpha := tfRGB4;
3181 fRGBInverted := tfBGR4;
3188 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3189 fglInternalFormat := GL_RGB4;
3190 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3193 constructor TfdR5G6B5.Create;
3196 fFormat := tfR5G6B5;
3197 fWithAlpha := tfRGBA4;
3198 fWithoutAlpha := tfR5G6B5;
3199 fRGBInverted := tfB5G6R5;
3206 fglFormat := GL_RGB;
3207 fglInternalFormat := GL_RGB565;
3208 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3211 constructor TfdRGB5.Create;
3215 fWithAlpha := tfRGB5A1;
3216 fWithoutAlpha := tfRGB5;
3217 fRGBInverted := tfBGR5;
3224 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3225 fglInternalFormat := GL_RGB5;
3226 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3229 constructor TfdRGB8.Create;
3233 fWithAlpha := tfRGBA8;
3234 fWithoutAlpha := tfRGB8;
3235 fRGBInverted := tfBGR8;
3236 fglInternalFormat := GL_RGB8;
3239 constructor TfdRGB10.Create;
3243 fWithAlpha := tfRGB10A2;
3244 fWithoutAlpha := tfRGB10;
3245 fRGBInverted := tfBGR10;
3252 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3253 fglInternalFormat := GL_RGB10;
3254 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3257 constructor TfdRGB12.Create;
3261 fWithAlpha := tfRGBA12;
3262 fWithoutAlpha := tfRGB12;
3263 fRGBInverted := tfBGR12;
3264 fglInternalFormat := GL_RGB12;
3267 constructor TfdRGB16.Create;
3271 fWithAlpha := tfRGBA16;
3272 fWithoutAlpha := tfRGB16;
3273 fRGBInverted := tfBGR16;
3274 fglInternalFormat := GL_RGB16;
3277 constructor TfdRGBA2.Create;
3281 fWithAlpha := tfRGBA2;
3282 fWithoutAlpha := tfR3G3B2;
3283 fRGBInverted := tfBGRA2;
3284 fglInternalFormat := GL_RGBA2;
3287 constructor TfdRGBA4.Create;
3291 fWithAlpha := tfRGBA4;
3292 fWithoutAlpha := tfRGB4;
3293 fRGBInverted := tfBGRA4;
3302 fglFormat := GL_RGBA;
3303 fglInternalFormat := GL_RGBA4;
3304 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3307 constructor TfdRGB5A1.Create;
3310 fFormat := tfRGB5A1;
3311 fWithAlpha := tfRGB5A1;
3312 fWithoutAlpha := tfRGB5;
3313 fRGBInverted := tfBGR5A1;
3322 fglFormat := GL_RGBA;
3323 fglInternalFormat := GL_RGB5_A1;
3324 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3327 constructor TfdRGBA8.Create;
3331 fWithAlpha := tfRGBA8;
3332 fWithoutAlpha := tfRGB8;
3333 fRGBInverted := tfBGRA8;
3334 fglInternalFormat := GL_RGBA8;
3337 constructor TfdRGB10A2.Create;
3340 fFormat := tfRGB10A2;
3341 fWithAlpha := tfRGB10A2;
3342 fWithoutAlpha := tfRGB10;
3343 fRGBInverted := tfBGR10A2;
3352 fglFormat := GL_RGBA;
3353 fglInternalFormat := GL_RGB10_A2;
3354 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3357 constructor TfdRGBA12.Create;
3360 fFormat := tfRGBA12;
3361 fWithAlpha := tfRGBA12;
3362 fWithoutAlpha := tfRGB12;
3363 fRGBInverted := tfBGRA12;
3364 fglInternalFormat := GL_RGBA12;
3367 constructor TfdRGBA16.Create;
3370 fFormat := tfRGBA16;
3371 fWithAlpha := tfRGBA16;
3372 fWithoutAlpha := tfRGB16;
3373 fRGBInverted := tfBGRA16;
3374 fglInternalFormat := GL_RGBA16;
3377 constructor TfdBGR4.Create;
3382 fWithAlpha := tfBGRA4;
3383 fWithoutAlpha := tfBGR4;
3384 fRGBInverted := tfRGB4;
3393 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3394 fglInternalFormat := GL_RGB4;
3395 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3398 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3399 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3400 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3401 constructor TfdB5G6R5.Create;
3404 fFormat := tfB5G6R5;
3405 fWithAlpha := tfBGRA4;
3406 fWithoutAlpha := tfB5G6R5;
3407 fRGBInverted := tfR5G6B5;
3414 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3415 fglInternalFormat := GL_RGB8;
3416 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3419 constructor TfdBGR5.Create;
3424 fWithAlpha := tfBGR5A1;
3425 fWithoutAlpha := tfBGR5;
3426 fRGBInverted := tfRGB5;
3435 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3436 fglInternalFormat := GL_RGB5;
3437 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3440 constructor TfdBGR8.Create;
3444 fWithAlpha := tfBGRA8;
3445 fWithoutAlpha := tfBGR8;
3446 fRGBInverted := tfRGB8;
3447 fglInternalFormat := GL_RGB8;
3450 constructor TfdBGR10.Create;
3454 fWithAlpha := tfBGR10A2;
3455 fWithoutAlpha := tfBGR10;
3456 fRGBInverted := tfRGB10;
3465 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3466 fglInternalFormat := GL_RGB10;
3467 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3470 constructor TfdBGR12.Create;
3474 fWithAlpha := tfBGRA12;
3475 fWithoutAlpha := tfBGR12;
3476 fRGBInverted := tfRGB12;
3477 fglInternalFormat := GL_RGB12;
3480 constructor TfdBGR16.Create;
3484 fWithAlpha := tfBGRA16;
3485 fWithoutAlpha := tfBGR16;
3486 fRGBInverted := tfRGB16;
3487 fglInternalFormat := GL_RGB16;
3490 constructor TfdBGRA2.Create;
3494 fWithAlpha := tfBGRA4;
3495 fWithoutAlpha := tfBGR4;
3496 fRGBInverted := tfRGBA2;
3497 fglInternalFormat := GL_RGBA2;
3500 constructor TfdBGRA4.Create;
3504 fWithAlpha := tfBGRA4;
3505 fWithoutAlpha := tfBGR4;
3506 fRGBInverted := tfRGBA4;
3515 fglFormat := GL_BGRA;
3516 fglInternalFormat := GL_RGBA4;
3517 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3520 constructor TfdBGR5A1.Create;
3523 fFormat := tfBGR5A1;
3524 fWithAlpha := tfBGR5A1;
3525 fWithoutAlpha := tfBGR5;
3526 fRGBInverted := tfRGB5A1;
3535 fglFormat := GL_BGRA;
3536 fglInternalFormat := GL_RGB5_A1;
3537 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3540 constructor TfdBGRA8.Create;
3544 fWithAlpha := tfBGRA8;
3545 fWithoutAlpha := tfBGR8;
3546 fRGBInverted := tfRGBA8;
3547 fglInternalFormat := GL_RGBA8;
3550 constructor TfdBGR10A2.Create;
3553 fFormat := tfBGR10A2;
3554 fWithAlpha := tfBGR10A2;
3555 fWithoutAlpha := tfBGR10;
3556 fRGBInverted := tfRGB10A2;
3565 fglFormat := GL_BGRA;
3566 fglInternalFormat := GL_RGB10_A2;
3567 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3570 constructor TfdBGRA12.Create;
3573 fFormat := tfBGRA12;
3574 fWithAlpha := tfBGRA12;
3575 fWithoutAlpha := tfBGR12;
3576 fRGBInverted := tfRGBA12;
3577 fglInternalFormat := GL_RGBA12;
3580 constructor TfdBGRA16.Create;
3583 fFormat := tfBGRA16;
3584 fWithAlpha := tfBGRA16;
3585 fWithoutAlpha := tfBGR16;
3586 fRGBInverted := tfRGBA16;
3587 fglInternalFormat := GL_RGBA16;
3590 constructor TfdDepth16.Create;
3593 fFormat := tfDepth16;
3594 fWithAlpha := tfEmpty;
3595 fWithoutAlpha := tfDepth16;
3596 fglInternalFormat := GL_DEPTH_COMPONENT16;
3599 constructor TfdDepth24.Create;
3602 fFormat := tfDepth24;
3603 fWithAlpha := tfEmpty;
3604 fWithoutAlpha := tfDepth24;
3605 fglInternalFormat := GL_DEPTH_COMPONENT24;
3608 constructor TfdDepth32.Create;
3611 fFormat := tfDepth32;
3612 fWithAlpha := tfEmpty;
3613 fWithoutAlpha := tfDepth32;
3614 fglInternalFormat := GL_DEPTH_COMPONENT32;
3617 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3618 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3619 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3620 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3622 raise EglBitmap.Create('mapping for compressed formats is not supported');
3625 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3627 raise EglBitmap.Create('mapping for compressed formats is not supported');
3630 constructor TfdS3tcDtx1RGBA.Create;
3633 fFormat := tfS3tcDtx1RGBA;
3634 fWithAlpha := tfS3tcDtx1RGBA;
3635 fUncompressed := tfRGB5A1;
3637 fIsCompressed := true;
3638 fglFormat := GL_COMPRESSED_RGBA;
3639 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3640 fglDataFormat := GL_UNSIGNED_BYTE;
3643 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3644 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3645 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3646 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3648 raise EglBitmap.Create('mapping for compressed formats is not supported');
3651 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3653 raise EglBitmap.Create('mapping for compressed formats is not supported');
3656 constructor TfdS3tcDtx3RGBA.Create;
3659 fFormat := tfS3tcDtx3RGBA;
3660 fWithAlpha := tfS3tcDtx3RGBA;
3661 fUncompressed := tfRGBA8;
3663 fIsCompressed := true;
3664 fglFormat := GL_COMPRESSED_RGBA;
3665 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3666 fglDataFormat := GL_UNSIGNED_BYTE;
3669 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3670 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3671 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3672 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3674 raise EglBitmap.Create('mapping for compressed formats is not supported');
3677 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3679 raise EglBitmap.Create('mapping for compressed formats is not supported');
3682 constructor TfdS3tcDtx5RGBA.Create;
3685 fFormat := tfS3tcDtx3RGBA;
3686 fWithAlpha := tfS3tcDtx3RGBA;
3687 fUncompressed := tfRGBA8;
3689 fIsCompressed := true;
3690 fglFormat := GL_COMPRESSED_RGBA;
3691 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3692 fglDataFormat := GL_UNSIGNED_BYTE;
3695 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3696 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3697 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3698 class procedure TFormatDescriptor.Init;
3700 if not Assigned(FormatDescriptorCS) then
3701 FormatDescriptorCS := TCriticalSection.Create;
3704 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3705 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3707 FormatDescriptorCS.Enter;
3709 result := FormatDescriptors[aFormat];
3710 if not Assigned(result) then begin
3711 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3712 FormatDescriptors[aFormat] := result;
3715 FormatDescriptorCS.Leave;
3719 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3720 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3722 result := Get(Get(aFormat).WithAlpha);
3725 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3726 class procedure TFormatDescriptor.Clear;
3730 FormatDescriptorCS.Enter;
3732 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3733 FreeAndNil(FormatDescriptors[f]);
3735 FormatDescriptorCS.Leave;
3739 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3740 class procedure TFormatDescriptor.Finalize;
3743 FreeAndNil(FormatDescriptorCS);
3746 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3747 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3748 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3749 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3751 Update(aValue, fRange.r, fShift.r);
3754 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3755 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3757 Update(aValue, fRange.g, fShift.g);
3760 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3761 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3763 Update(aValue, fRange.b, fShift.b);
3766 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3767 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3769 Update(aValue, fRange.a, fShift.a);
3772 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3773 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3780 while (aMask > 0) and ((aMask and 1) = 0) do begin
3782 aMask := aMask shr 1;
3785 while (aMask > 0) do begin
3786 aRange := aRange shl 1;
3787 aMask := aMask shr 1;
3791 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3794 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3795 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3801 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3802 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3803 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3804 ((aPixel.Data.a and fRange.a) shl fShift.a);
3805 s := Round(fPixelSize);
3808 2: PWord(aData)^ := data;
3809 4: PCardinal(aData)^ := data;
3810 8: PQWord(aData)^ := data;
3812 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3817 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3818 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3823 s := Round(fPixelSize);
3826 2: data := PWord(aData)^;
3827 4: data := PCardinal(aData)^;
3828 8: data := PQWord(aData)^;
3830 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3833 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3837 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3838 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3839 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3840 procedure TbmpColorTableFormat.CreateColorTable;
3844 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3845 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3847 if (Format = tfLuminance4) then
3848 SetLength(fColorTable, 16)
3850 SetLength(fColorTable, 256);
3854 for i := 0 to High(fColorTable) do begin
3855 fColorTable[i].r := 16 * i;
3856 fColorTable[i].g := 16 * i;
3857 fColorTable[i].b := 16 * i;
3858 fColorTable[i].a := 0;
3863 for i := 0 to High(fColorTable) do begin
3864 fColorTable[i].r := i;
3865 fColorTable[i].g := i;
3866 fColorTable[i].b := i;
3867 fColorTable[i].a := 0;
3872 for i := 0 to High(fColorTable) do begin
3873 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3874 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3875 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3876 fColorTable[i].a := 0;
3882 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3883 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3887 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3888 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3892 if (aMapData = nil) then
3894 d := LuminanceWeight(aPixel) and Range.r;
3895 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3896 inc(PByte(aMapData), 4);
3897 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3904 aData^ := LuminanceWeight(aPixel) and Range.r;
3910 ((aPixel.Data.r and Range.r) shl Shift.r) or
3911 ((aPixel.Data.g and Range.g) shl Shift.g) or
3912 ((aPixel.Data.b and Range.b) shl Shift.b));
3918 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3919 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3926 s := Trunc(fPixelSize);
3927 f := fPixelSize - s;
3928 bits := Round(8 * f);
3930 0: idx := (aData^ shr (8 - bits - {%H-}PtrInt(aMapData))) and ((1 shl bits) - 1);
3932 2: idx := PWord(aData)^;
3933 4: idx := PCardinal(aData)^;
3934 8: idx := PQWord(aData)^;
3936 raise EglBitmap.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3938 if (idx >= Length(fColorTable)) then
3939 raise EglBitmap.CreateFmt('invalid color index: %d', [idx]);
3940 with fColorTable[idx] do begin
3946 inc(PByte(aMapData), bits);
3947 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3949 dec(PByte(aMapData), 8);
3954 destructor TbmpColorTableFormat.Destroy;
3956 SetLength(fColorTable, 0);
3960 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3961 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3962 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3963 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
3967 for i := 0 to 3 do begin
3968 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
3969 if (aSourceFD.Range.arr[i] > 0) then
3970 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
3972 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
3977 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3978 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
3980 with aFuncRec do begin
3981 if (Source.Range.r > 0) then
3982 Dest.Data.r := Source.Data.r;
3983 if (Source.Range.g > 0) then
3984 Dest.Data.g := Source.Data.g;
3985 if (Source.Range.b > 0) then
3986 Dest.Data.b := Source.Data.b;
3987 if (Source.Range.a > 0) then
3988 Dest.Data.a := Source.Data.a;
3992 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3993 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3997 with aFuncRec do begin
3999 if (Source.Range.arr[i] > 0) then
4000 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4005 TShiftData = packed record
4007 0: (r, g, b, a: SmallInt);
4008 1: (arr: array[0..3] of SmallInt);
4010 PShiftData = ^TShiftData;
4012 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4013 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4019 if (Source.Range.arr[i] > 0) then
4020 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4023 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4024 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4026 with aFuncRec do begin
4027 Dest.Data := Source.Data;
4028 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4029 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4030 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4031 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4033 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4034 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4039 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4040 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4044 with aFuncRec do begin
4046 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4050 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4051 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4055 with FuncRec do begin
4056 if (FuncRec.Args = nil) then begin //source has no alpha
4058 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4059 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4060 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4061 Dest.Data.a := Round(Dest.Range.a * Temp);
4063 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4067 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4068 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4070 PglBitmapPixelData = ^TglBitmapPixelData;
4072 with FuncRec do begin
4073 Dest.Data.r := Source.Data.r;
4074 Dest.Data.g := Source.Data.g;
4075 Dest.Data.b := Source.Data.b;
4077 with PglBitmapPixelData(Args)^ do
4078 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4079 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4080 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4083 Dest.Data.a := Dest.Range.a;
4087 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4088 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4090 with FuncRec do begin
4091 Dest.Data.r := Source.Data.r;
4092 Dest.Data.g := Source.Data.g;
4093 Dest.Data.b := Source.Data.b;
4094 Dest.Data.a := PCardinal(Args)^;
4098 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4099 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4102 TRGBPix = array [0..2] of byte;
4106 while aWidth > 0 do begin
4107 Temp := PRGBPix(aData)^[0];
4108 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4109 PRGBPix(aData)^[2] := Temp;
4119 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4120 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4122 function TglBitmap.GetFormatDesc: TglBitmapFormatDescriptor;
4124 result := TFormatDescriptor.Get(Format);
4127 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4128 function TglBitmap.GetWidth: Integer;
4130 if (ffX in fDimension.Fields) then
4131 result := fDimension.X
4136 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4137 function TglBitmap.GetHeight: Integer;
4139 if (ffY in fDimension.Fields) then
4140 result := fDimension.Y
4145 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4146 function TglBitmap.GetFileWidth: Integer;
4148 result := Max(1, Width);
4151 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4152 function TglBitmap.GetFileHeight: Integer;
4154 result := Max(1, Height);
4157 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4158 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4160 if fCustomData = aValue then
4162 fCustomData := aValue;
4165 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4166 procedure TglBitmap.SetCustomName(const aValue: String);
4168 if fCustomName = aValue then
4170 fCustomName := aValue;
4173 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4174 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4176 if fCustomNameW = aValue then
4178 fCustomNameW := aValue;
4181 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4182 procedure TglBitmap.SetFreeDataOnDestroy(const aValue: Boolean);
4184 if fFreeDataOnDestroy = aValue then
4186 fFreeDataOnDestroy := aValue;
4189 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4190 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4192 if fDeleteTextureOnFree = aValue then
4194 fDeleteTextureOnFree := aValue;
4197 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4198 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4200 if fFormat = aValue then
4202 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4203 raise EglBitmapUnsupportedFormat.Create(Format);
4204 SetDataPointer(fData, aValue, Width, Height); //be careful, Data could be freed by this method
4207 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4208 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4210 if fFreeDataAfterGenTexture = aValue then
4212 fFreeDataAfterGenTexture := aValue;
4215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4216 procedure TglBitmap.SetID(const aValue: Cardinal);
4218 if fID = aValue then
4223 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4224 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4226 if fMipMap = aValue then
4231 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4232 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4234 if fTarget = aValue then
4239 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4240 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4242 MaxAnisotropic: Integer;
4244 fAnisotropic := aValue;
4245 if (ID > 0) then begin
4246 if GL_EXT_texture_filter_anisotropic then begin
4247 if fAnisotropic > 0 then begin
4249 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4250 if aValue > MaxAnisotropic then
4251 fAnisotropic := MaxAnisotropic;
4252 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4260 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4261 procedure TglBitmap.CreateID;
4264 glDeleteTextures(1, @fID);
4265 glGenTextures(1, @fID);
4269 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4270 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4272 // Set Up Parameters
4273 SetWrap(fWrapS, fWrapT, fWrapR);
4274 SetFilter(fFilterMin, fFilterMag);
4275 SetAnisotropic(fAnisotropic);
4276 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4278 if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
4279 SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4281 // Mip Maps Generation Mode
4282 aBuildWithGlu := false;
4283 if (MipMap = mmMipmap) then begin
4284 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4285 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4287 aBuildWithGlu := true;
4288 end else if (MipMap = mmMipmapGlu) then
4289 aBuildWithGlu := true;
4292 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4293 procedure TglBitmap.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
4294 const aWidth: Integer; const aHeight: Integer);
4298 if (Data <> aData) then begin
4299 if (Assigned(Data)) then
4304 if not Assigned(fData) then begin
4308 FillChar(fDimension, SizeOf(fDimension), 0);
4309 if aWidth <> -1 then begin
4310 fDimension.Fields := fDimension.Fields + [ffX];
4311 fDimension.X := aWidth;
4314 if aHeight <> -1 then begin
4315 fDimension.Fields := fDimension.Fields + [ffY];
4316 fDimension.Y := aHeight;
4319 s := TFormatDescriptor.Get(aFormat).PixelSize;
4321 fPixelSize := Ceil(s);
4322 fRowSize := Ceil(s * aWidth);
4326 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4327 function TglBitmap.FlipHorz: Boolean;
4332 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4333 function TglBitmap.FlipVert: Boolean;
4338 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4339 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4340 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4341 procedure TglBitmap.AfterConstruction;
4343 inherited AfterConstruction;
4347 fIsResident := false;
4349 fMipMap := glBitmapDefaultMipmap;
4350 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4351 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4353 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4354 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4355 glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4358 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4359 procedure TglBitmap.BeforeDestruction;
4363 if fFreeDataOnDestroy then begin
4365 SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
4367 if (fID > 0) and fDeleteTextureOnFree then
4368 glDeleteTextures(1, @fID);
4369 inherited BeforeDestruction;
4372 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4373 procedure TglBitmap.PrepareResType(var aResource: String; var aResType: PChar);
4377 if not Assigned(aResType) then begin
4378 TempPos := Pos('.', aResource);
4379 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4380 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4384 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4385 procedure TglBitmap.LoadFromFile(const aFilename: String);
4389 if not FileExists(aFilename) then
4390 raise EglBitmap.Create('file does not exist: ' + aFilename);
4391 fFilename := aFilename;
4392 fs := TFileStream.Create(fFilename, fmOpenRead);
4401 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4402 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4404 {$IFDEF GLB_SUPPORT_PNG_READ}
4405 if not LoadPNG(aStream) then
4407 {$IFDEF GLB_SUPPORT_JPEG_READ}
4408 if not LoadJPEG(aStream) then
4410 if not LoadDDS(aStream) then
4411 if not LoadTGA(aStream) then
4412 if not LoadBMP(aStream) then
4413 raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4416 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4417 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4418 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4423 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4424 GetMem(tmpData, size);
4426 FillChar(tmpData^, size, #$FF);
4427 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
4429 if Assigned(tmpData) then
4433 AddFunc(Self, aFunc, false, aFormat, aArgs);
4436 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4437 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
4439 rs: TResourceStream;
4441 PrepareResType(aResource, aResType);
4442 rs := TResourceStream.Create(aInstance, aResource, aResType);
4450 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4451 procedure TglBitmap.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4453 rs: TResourceStream;
4455 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
4463 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4464 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4468 fs := TFileStream.Create(aFileName, fmCreate);
4471 SaveToStream(fs, aFileType);
4477 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4478 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4481 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4482 ftPNG: SavePNG(aStream);
4484 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4485 ftJPEG: SaveJPEG(aStream);
4487 ftDDS: SaveDDS(aStream);
4488 ftTGA: SaveTGA(aStream);
4489 ftBMP: SaveBMP(aStream);
4493 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4494 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4496 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4499 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4500 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4501 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4503 DestData, TmpData, SourceData: pByte;
4504 TempHeight, TempWidth: Integer;
4505 SourceFD, DestFD: TFormatDescriptor;
4506 SourceMD, DestMD: Pointer;
4508 FuncRec: TglBitmapFunctionRec;
4510 Assert(Assigned(Data));
4511 Assert(Assigned(aSource));
4512 Assert(Assigned(aSource.Data));
4515 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4516 SourceFD := TFormatDescriptor.Get(aSource.Format);
4517 DestFD := TFormatDescriptor.Get(aFormat);
4519 if (SourceFD.IsCompressed) then
4520 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
4521 if (DestFD.IsCompressed) then
4522 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
4524 // inkompatible Formats so CreateTemp
4525 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4526 aCreateTemp := true;
4529 TempHeight := Max(1, aSource.Height);
4530 TempWidth := Max(1, aSource.Width);
4532 FuncRec.Sender := Self;
4533 FuncRec.Args := aArgs;
4536 if aCreateTemp then begin
4537 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
4538 DestData := TmpData;
4543 SourceFD.PreparePixel(FuncRec.Source);
4544 DestFD.PreparePixel (FuncRec.Dest);
4546 SourceMD := SourceFD.CreateMappingData;
4547 DestMD := DestFD.CreateMappingData;
4549 FuncRec.Size := aSource.Dimension;
4550 FuncRec.Position.Fields := FuncRec.Size.Fields;
4553 SourceData := aSource.Data;
4554 FuncRec.Position.Y := 0;
4555 while FuncRec.Position.Y < TempHeight do begin
4556 FuncRec.Position.X := 0;
4557 while FuncRec.Position.X < TempWidth do begin
4558 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4560 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4561 inc(FuncRec.Position.X);
4563 inc(FuncRec.Position.Y);
4566 // Updating Image or InternalFormat
4568 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) //be careful, Data could be freed by this method
4569 else if (aFormat <> fFormat) then
4574 SourceFD.FreeMappingData(SourceMD);
4575 DestFD.FreeMappingData(DestMD);
4578 if aCreateTemp and Assigned(TmpData) then
4586 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4587 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4589 Row, RowSize: Integer;
4590 SourceData, TmpData: PByte;
4592 FormatDesc: TFormatDescriptor;
4594 function GetRowPointer(Row: Integer): pByte;
4596 result := aSurface.pixels;
4597 Inc(result, Row * RowSize);
4603 FormatDesc := TFormatDescriptor.Get(Format);
4604 if FormatDesc.IsCompressed then
4605 raise EglBitmapUnsupportedFormat.Create(Format);
4607 if Assigned(Data) then begin
4608 case Trunc(FormatDesc.PixelSize) of
4614 raise EglBitmapUnsupportedFormat.Create(Format);
4617 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4618 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4620 RowSize := FormatDesc.GetSize(FileWidth, 1);
4622 for Row := 0 to FileHeight-1 do begin
4623 TmpData := GetRowPointer(Row);
4624 if Assigned(TmpData) then begin
4625 Move(SourceData^, TmpData^, RowSize);
4626 inc(SourceData, RowSize);
4633 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4634 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4636 pSource, pData, pTempData: PByte;
4637 Row, RowSize, TempWidth, TempHeight: Integer;
4638 IntFormat: TglBitmapFormat;
4639 FormatDesc: TFormatDescriptor;
4641 function GetRowPointer(Row: Integer): pByte;
4643 result := aSurface^.pixels;
4644 Inc(result, Row * RowSize);
4649 if (Assigned(aSurface)) then begin
4650 with aSurface^.format^ do begin
4651 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4652 FormatDesc := TFormatDescriptor.Get(IntFormat);
4653 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4656 if (IntFormat = tfEmpty) then
4657 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4660 TempWidth := aSurface^.w;
4661 TempHeight := aSurface^.h;
4662 RowSize := FormatDesc.GetSize(TempWidth, 1);
4663 GetMem(pData, TempHeight * RowSize);
4666 for Row := 0 to TempHeight -1 do begin
4667 pSource := GetRowPointer(Row);
4668 if (Assigned(pSource)) then begin
4669 Move(pSource^, pTempData^, RowSize);
4670 Inc(pTempData, RowSize);
4673 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4676 if Assigned(pData) then
4683 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4684 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4686 Row, Col, AlphaInterleave: Integer;
4687 pSource, pDest: PByte;
4689 function GetRowPointer(Row: Integer): pByte;
4691 result := aSurface.pixels;
4692 Inc(result, Row * Width);
4697 if Assigned(Data) then begin
4698 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4699 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4701 AlphaInterleave := 0;
4704 AlphaInterleave := 1;
4706 AlphaInterleave := 3;
4710 for Row := 0 to Height -1 do begin
4711 pDest := GetRowPointer(Row);
4712 if Assigned(pDest) then begin
4713 for Col := 0 to Width -1 do begin
4714 Inc(pSource, AlphaInterleave);
4726 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4727 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4731 bmp := TglBitmap2D.Create;
4733 bmp.AssignFromSurface(aSurface);
4734 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4742 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4743 function CreateGrayPalette: HPALETTE;
4748 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
4750 Pal.palVersion := $300;
4751 Pal.palNumEntries := 256;
4753 for Idx := 0 to Pal.palNumEntries - 1 do begin
4754 Pal.palPalEntry[Idx].peRed := Idx;
4755 Pal.palPalEntry[Idx].peGreen := Idx;
4756 Pal.palPalEntry[Idx].peBlue := Idx;
4757 Pal.palPalEntry[Idx].peFlags := 0;
4759 Result := CreatePalette(Pal^);
4763 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4764 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4767 pSource, pData: PByte;
4770 if Assigned(Data) then begin
4771 if Assigned(aBitmap) then begin
4772 aBitmap.Width := Width;
4773 aBitmap.Height := Height;
4776 tfAlpha8, tfLuminance8: begin
4777 aBitmap.PixelFormat := pf8bit;
4778 aBitmap.Palette := CreateGrayPalette;
4781 aBitmap.PixelFormat := pf15bit;
4783 aBitmap.PixelFormat := pf16bit;
4785 aBitmap.PixelFormat := pf24bit;
4787 aBitmap.PixelFormat := pf32bit;
4789 raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.');
4793 for Row := 0 to FileHeight -1 do begin
4794 pData := aBitmap.Scanline[Row];
4795 Move(pSource^, pData^, fRowSize);
4796 Inc(pSource, fRowSize);
4797 if (Format in [tfRGB8, tfRGBA8]) then // swap RGB(A) to BGR(A)
4798 SwapRGB(pData, FileWidth, Format = tfRGBA8);
4805 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4806 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4808 pSource, pData, pTempData: PByte;
4809 Row, RowSize, TempWidth, TempHeight: Integer;
4810 IntFormat: TglBitmapFormat;
4814 if (Assigned(aBitmap)) then begin
4815 case aBitmap.PixelFormat of
4817 IntFormat := tfLuminance8;
4819 IntFormat := tfRGB5A1;
4821 IntFormat := tfR5G6B5;
4823 IntFormat := tfBGR8;
4825 IntFormat := tfBGRA8;
4827 raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.');
4830 TempWidth := aBitmap.Width;
4831 TempHeight := aBitmap.Height;
4832 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
4833 GetMem(pData, TempHeight * RowSize);
4836 for Row := 0 to TempHeight -1 do begin
4837 pSource := aBitmap.Scanline[Row];
4838 if (Assigned(pSource)) then begin
4839 Move(pSource^, pTempData^, RowSize);
4840 Inc(pTempData, RowSize);
4843 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4846 if Assigned(pData) then
4853 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4854 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4856 Row, Col, AlphaInterleave: Integer;
4857 pSource, pDest: PByte;
4861 if Assigned(Data) then begin
4862 if (Format in [tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8]) then begin
4863 if Assigned(aBitmap) then begin
4864 aBitmap.PixelFormat := pf8bit;
4865 aBitmap.Palette := CreateGrayPalette;
4866 aBitmap.Width := Width;
4867 aBitmap.Height := Height;
4871 AlphaInterleave := 1;
4873 AlphaInterleave := 3;
4875 AlphaInterleave := 0;
4881 for Row := 0 to Height -1 do begin
4882 pDest := aBitmap.Scanline[Row];
4883 if Assigned(pDest) then begin
4884 for Col := 0 to Width -1 do begin
4885 Inc(pSource, AlphaInterleave);
4898 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4899 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4903 tex := TglBitmap2D.Create;
4905 tex.AssignFromBitmap(ABitmap);
4906 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4913 {$IFDEF GLB_LAZARUS}
4914 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4915 function TglBitmap.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4917 rid: TRawImageDescription;
4918 FormatDesc: TFormatDescriptor;
4921 if not Assigned(aImage) or (Format = tfEmpty) then
4923 FormatDesc := TFormatDescriptor.Get(Format);
4924 if FormatDesc.IsCompressed then
4927 FillChar(rid{%H-}, SizeOf(rid), 0);
4929 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
4930 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
4931 tfLuminance4Alpha4, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16]) then
4932 rid.Format := ricfGray
4934 rid.Format := ricfRGBA;
4937 rid.Height := Height;
4938 rid.Depth := CountSetBits(FormatDesc.RedMask or FormatDesc.GreenMask or FormatDesc.BlueMask or FormatDesc.AlphaMask);
4939 rid.BitOrder := riboBitsInOrder;
4940 rid.ByteOrder := riboLSBFirst;
4941 rid.LineOrder := riloTopToBottom;
4942 rid.LineEnd := rileTight;
4943 rid.BitsPerPixel := Round(8 * FormatDesc.PixelSize);
4944 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
4945 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
4946 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
4947 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
4948 rid.RedShift := FormatDesc.Shift.r;
4949 rid.GreenShift := FormatDesc.Shift.g;
4950 rid.BlueShift := FormatDesc.Shift.b;
4951 rid.AlphaShift := FormatDesc.Shift.a;
4953 rid.MaskBitsPerPixel := 0;
4954 rid.PaletteColorCount := 0;
4956 aImage.DataDescription := rid;
4959 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
4964 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4965 function TglBitmap.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
4968 FormatDesc: TFormatDescriptor;
4973 procedure CopyConvert;
4975 bfFormat: TbmpBitfieldFormat;
4976 pSourceLine, pDestLine: PByte;
4977 pSourceMD, pDestMD: Pointer;
4979 pixel: TglBitmapPixelData;
4981 bfFormat := TbmpBitfieldFormat.Create;
4982 with aImage.DataDescription do begin
4983 bfFormat.RedMask := ((1 shl RedPrec) - 1) shl RedShift;
4984 bfFormat.GreenMask := ((1 shl GreenPrec) - 1) shl GreenShift;
4985 bfFormat.BlueMask := ((1 shl BluePrec) - 1) shl BlueShift;
4986 bfFormat.AlphaMask := ((1 shl AlphaPrec) - 1) shl AlphaShift;
4987 bfFormat.PixelSize := BitsPerPixel / 8;
4989 pSourceMD := bfFormat.CreateMappingData;
4990 pDestMD := FormatDesc.CreateMappingData;
4992 for y := 0 to aImage.Height-1 do begin
4993 pSourceLine := aImage.PixelData + y * aImage.DataDescription.BytesPerLine;
4994 pDestLine := ImageData + y * Round(FormatDesc.PixelSize * aImage.Width);
4995 for x := 0 to aImage.Width-1 do begin
4996 bfFormat.Unmap(pSourceLine, pixel, pSourceMD);
4997 FormatDesc.Map(pixel, pDestLine, pDestMD);
5001 FormatDesc.FreeMappingData(pDestMD);
5002 bfFormat.FreeMappingData(pSourceMD);
5009 if not Assigned(aImage) then
5011 for f := High(f) downto Low(f) do begin
5012 FormatDesc := TFormatDescriptor.Get(f);
5013 with aImage.DataDescription do
5014 if FormatDesc.MaskMatch(
5015 (QWord(1 shl RedPrec )-1) shl RedShift,
5016 (QWord(1 shl GreenPrec)-1) shl GreenShift,
5017 (QWord(1 shl BluePrec )-1) shl BlueShift,
5018 (QWord(1 shl AlphaPrec)-1) shl AlphaShift) then
5022 if (f = tfEmpty) then
5026 (Round(FormatDesc.PixelSize * 8) = aImage.DataDescription.Depth) and
5027 (aImage.DataDescription.BitsPerPixel = aImage.DataDescription.Depth);
5029 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
5030 ImageData := GetMem(ImageSize);
5033 Move(aImage.PixelData^, ImageData^, ImageSize)
5036 SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method
5038 if Assigned(ImageData) then
5046 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5047 function TglBitmap.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
5049 rid: TRawImageDescription;
5050 FormatDesc: TFormatDescriptor;
5051 Pixel: TglBitmapPixelData;
5057 if not Assigned(aImage) or (Format = tfEmpty) then
5059 FormatDesc := TFormatDescriptor.Get(Format);
5060 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5063 FillChar(rid{%H-}, SizeOf(rid), 0);
5064 rid.Format := ricfGray;
5066 rid.Height := Height;
5067 rid.Depth := CountSetBits(FormatDesc.Range.a);
5068 rid.BitOrder := riboBitsInOrder;
5069 rid.ByteOrder := riboLSBFirst;
5070 rid.LineOrder := riloTopToBottom;
5071 rid.LineEnd := rileTight;
5072 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
5073 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
5078 rid.GreenShift := 0;
5080 rid.AlphaShift := 0;
5082 rid.MaskBitsPerPixel := 0;
5083 rid.PaletteColorCount := 0;
5085 aImage.DataDescription := rid;
5088 srcMD := FormatDesc.CreateMappingData;
5090 FormatDesc.PreparePixel(Pixel);
5092 dst := aImage.PixelData;
5093 for y := 0 to Height-1 do
5094 for x := 0 to Width-1 do begin
5095 FormatDesc.Unmap(src, Pixel, srcMD);
5096 case rid.BitsPerPixel of
5098 dst^ := Pixel.Data.a;
5102 PWord(dst)^ := Pixel.Data.a;
5106 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
5107 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
5108 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
5112 PCardinal(dst)^ := Pixel.Data.a;
5116 raise EglBitmapUnsupportedFormat.Create(Format);
5120 FormatDesc.FreeMappingData(srcMD);
5125 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5126 function TglBitmap.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5130 tex := TglBitmap2D.Create;
5132 tex.AssignFromLazIntfImage(aImage);
5133 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5140 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5141 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
5142 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5144 rs: TResourceStream;
5146 PrepareResType(aResource, aResType);
5147 rs := TResourceStream.Create(aInstance, aResource, aResType);
5149 result := AddAlphaFromStream(rs, aFunc, aArgs);
5155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5156 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
5157 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5159 rs: TResourceStream;
5161 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
5163 result := AddAlphaFromStream(rs, aFunc, aArgs);
5169 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5170 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5172 if TFormatDescriptor.Get(Format).IsCompressed then
5173 raise EglBitmapUnsupportedFormat.Create(Format);
5174 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
5177 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5178 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5182 FS := TFileStream.Create(aFileName, fmOpenRead);
5184 result := AddAlphaFromStream(FS, aFunc, aArgs);
5190 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5191 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5195 tex := TglBitmap2D.Create(aStream);
5197 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5203 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5204 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5206 DestData, DestData2, SourceData: pByte;
5207 TempHeight, TempWidth: Integer;
5208 SourceFD, DestFD: TFormatDescriptor;
5209 SourceMD, DestMD, DestMD2: Pointer;
5211 FuncRec: TglBitmapFunctionRec;
5215 Assert(Assigned(Data));
5216 Assert(Assigned(aBitmap));
5217 Assert(Assigned(aBitmap.Data));
5219 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
5220 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
5222 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
5223 DestFD := TFormatDescriptor.Get(Format);
5225 if not Assigned(aFunc) then begin
5226 aFunc := glBitmapAlphaFunc;
5227 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5229 FuncRec.Args := aArgs;
5232 TempHeight := aBitmap.FileHeight;
5233 TempWidth := aBitmap.FileWidth;
5235 FuncRec.Sender := Self;
5236 FuncRec.Size := Dimension;
5237 FuncRec.Position.Fields := FuncRec.Size.Fields;
5241 SourceData := aBitmap.Data;
5244 SourceFD.PreparePixel(FuncRec.Source);
5245 DestFD.PreparePixel (FuncRec.Dest);
5247 SourceMD := SourceFD.CreateMappingData;
5248 DestMD := DestFD.CreateMappingData;
5249 DestMD2 := DestFD.CreateMappingData;
5251 FuncRec.Position.Y := 0;
5252 while FuncRec.Position.Y < TempHeight do begin
5253 FuncRec.Position.X := 0;
5254 while FuncRec.Position.X < TempWidth do begin
5255 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5256 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5258 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5259 inc(FuncRec.Position.X);
5261 inc(FuncRec.Position.Y);
5264 SourceFD.FreeMappingData(SourceMD);
5265 DestFD.FreeMappingData(DestMD);
5266 DestFD.FreeMappingData(DestMD2);
5271 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5272 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5274 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5277 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5278 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5280 PixelData: TglBitmapPixelData;
5282 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5283 result := AddAlphaFromColorKeyFloat(
5284 aRed / PixelData.Range.r,
5285 aGreen / PixelData.Range.g,
5286 aBlue / PixelData.Range.b,
5287 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5290 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5291 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5293 values: array[0..2] of Single;
5296 PixelData: TglBitmapPixelData;
5298 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5299 with PixelData do begin
5301 values[1] := aGreen;
5304 for i := 0 to 2 do begin
5305 tmp := Trunc(Range.arr[i] * aDeviation);
5306 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5307 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5312 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5315 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5316 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5318 result := AddAlphaFromValueFloat(aAlpha / $FF);
5321 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5322 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5324 PixelData: TglBitmapPixelData;
5326 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5327 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5330 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5331 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5333 PixelData: TglBitmapPixelData;
5335 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5337 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5338 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5341 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5342 function TglBitmap.RemoveAlpha: Boolean;
5344 FormatDesc: TFormatDescriptor;
5347 FormatDesc := TFormatDescriptor.Get(Format);
5348 if Assigned(Data) then begin
5349 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5350 raise EglBitmapUnsupportedFormat.Create(Format);
5351 result := ConvertTo(FormatDesc.WithoutAlpha);
5355 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5356 function TglBitmap.Clone: TglBitmap;
5363 Temp := (ClassType.Create as TglBitmap);
5365 // copy texture data if assigned
5366 if Assigned(Data) then begin
5367 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5368 GetMem(TempPtr, Size);
5370 Move(Data^, TempPtr^, Size);
5371 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5373 if Assigned(TempPtr) then
5379 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5384 Temp.fTarget := Target;
5385 Temp.fFormat := Format;
5386 Temp.fMipMap := MipMap;
5387 Temp.fAnisotropic := Anisotropic;
5388 Temp.fBorderColor := fBorderColor;
5389 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5390 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5391 Temp.fFilterMin := fFilterMin;
5392 Temp.fFilterMag := fFilterMag;
5393 Temp.fWrapS := fWrapS;
5394 Temp.fWrapT := fWrapT;
5395 Temp.fWrapR := fWrapR;
5396 Temp.fFilename := fFilename;
5397 Temp.fCustomName := fCustomName;
5398 Temp.fCustomNameW := fCustomNameW;
5399 Temp.fCustomData := fCustomData;
5408 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5409 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5411 SourceFD, DestFD: TFormatDescriptor;
5412 SourcePD, DestPD: TglBitmapPixelData;
5413 ShiftData: TShiftData;
5415 function CanCopyDirect: Boolean;
5418 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5419 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5420 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5421 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5424 function CanShift: Boolean;
5427 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5428 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5429 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5430 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5433 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5436 while (aSource > aDest) and (aSource > 0) do begin
5438 aSource := aSource shr 1;
5443 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5444 SourceFD := TFormatDescriptor.Get(Format);
5445 DestFD := TFormatDescriptor.Get(aFormat);
5447 SourceFD.PreparePixel(SourcePD);
5448 DestFD.PreparePixel (DestPD);
5450 if CanCopyDirect then
5451 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5452 else if CanShift then begin
5453 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5454 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5455 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5456 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5457 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5459 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5464 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5465 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5467 if aUseRGB or aUseAlpha then
5468 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5469 ((Byte(aUseAlpha) and 1) shl 1) or
5470 (Byte(aUseRGB) and 1) ));
5473 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5474 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5476 fBorderColor[0] := aRed;
5477 fBorderColor[1] := aGreen;
5478 fBorderColor[2] := aBlue;
5479 fBorderColor[3] := aAlpha;
5480 if (ID > 0) then begin
5482 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5486 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5487 procedure TglBitmap.FreeData;
5492 SetDataPointer(TempPtr, tfEmpty); //be careful, Data could be freed by this method
5495 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5496 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5497 const aAlpha: Byte);
5499 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5502 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5503 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5505 PixelData: TglBitmapPixelData;
5507 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5509 aRed / PixelData.Range.r,
5510 aGreen / PixelData.Range.g,
5511 aBlue / PixelData.Range.b,
5512 aAlpha / PixelData.Range.a);
5515 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5516 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5518 PixelData: TglBitmapPixelData;
5520 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5521 with PixelData do begin
5522 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5523 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5524 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5525 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5527 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5530 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5531 procedure TglBitmap.SetFilter(const aMin, aMag: GLenum);
5536 fFilterMin := GL_NEAREST;
5538 fFilterMin := GL_LINEAR;
5539 GL_NEAREST_MIPMAP_NEAREST:
5540 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5541 GL_LINEAR_MIPMAP_NEAREST:
5542 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5543 GL_NEAREST_MIPMAP_LINEAR:
5544 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5545 GL_LINEAR_MIPMAP_LINEAR:
5546 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5548 raise EglBitmap.Create('SetFilter - Unknow MIN filter.');
5554 fFilterMag := GL_NEAREST;
5556 fFilterMag := GL_LINEAR;
5558 raise EglBitmap.Create('SetFilter - Unknow MAG filter.');
5562 if (ID > 0) then begin
5564 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5566 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5568 GL_NEAREST, GL_LINEAR:
5569 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5570 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5571 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5572 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5573 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5576 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5580 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5581 procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum);
5583 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5587 aTarget := GL_CLAMP;
5590 aTarget := GL_REPEAT;
5592 GL_CLAMP_TO_EDGE: begin
5593 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5594 aTarget := GL_CLAMP_TO_EDGE
5596 aTarget := GL_CLAMP;
5599 GL_CLAMP_TO_BORDER: begin
5600 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5601 aTarget := GL_CLAMP_TO_BORDER
5603 aTarget := GL_CLAMP;
5606 GL_MIRRORED_REPEAT: begin
5607 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5608 aTarget := GL_MIRRORED_REPEAT
5610 raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5613 raise EglBitmap.Create('SetWrap - Unknow Texturewrap');
5618 CheckAndSetWrap(S, fWrapS);
5619 CheckAndSetWrap(T, fWrapT);
5620 CheckAndSetWrap(R, fWrapR);
5622 if (ID > 0) then begin
5624 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5625 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5626 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5630 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5631 procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum);
5633 procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer);
5635 if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or
5636 (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then
5637 fSwizzle[aIndex] := aValue
5639 raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value');
5643 if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
5644 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
5645 CheckAndSetValue(r, 0);
5646 CheckAndSetValue(g, 1);
5647 CheckAndSetValue(b, 2);
5648 CheckAndSetValue(a, 3);
5650 if (ID > 0) then begin
5652 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, @fSwizzle[0]);
5656 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5657 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5659 if aEnableTextureUnit then
5662 glBindTexture(Target, ID);
5665 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5666 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5668 if aDisableTextureUnit then
5670 glBindTexture(Target, 0);
5673 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5674 constructor TglBitmap.Create;
5676 if (ClassType = TglBitmap) then
5677 raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5678 {$IFDEF GLB_NATIVE_OGL}
5679 glbReadOpenGLExtensions;
5682 fFormat := glBitmapGetDefaultFormat;
5683 fFreeDataOnDestroy := true;
5686 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5687 constructor TglBitmap.Create(const aFileName: String);
5690 LoadFromFile(aFileName);
5693 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5694 constructor TglBitmap.Create(const aStream: TStream);
5697 LoadFromStream(aStream);
5700 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5701 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte);
5706 if not Assigned(aData) then begin
5707 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5708 GetMem(aData, ImageSize);
5710 FillChar(aData^, ImageSize, #$FF);
5711 SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5713 if Assigned(aData) then
5718 SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5719 fFreeDataOnDestroy := false;
5723 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5724 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer);
5727 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5730 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5731 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5734 LoadFromResource(aInstance, aResource, aResType);
5737 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5738 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5741 LoadFromResourceID(aInstance, aResourceID, aResType);
5744 {$IFDEF GLB_SUPPORT_PNG_READ}
5745 {$IF DEFINED(GLB_LAZ_PNG)}
5746 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5747 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5748 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5749 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5752 PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A;
5754 png: TPortableNetworkGraphic;
5755 intf: TLazIntfImage;
5757 magic: String[MAGIC_LEN];
5760 StreamPos := aStream.Position;
5762 SetLength(magic, MAGIC_LEN);
5763 aStream.Read(magic[1], MAGIC_LEN);
5764 aStream.Position := StreamPos;
5765 if (magic <> PNG_MAGIC) then begin
5770 png := TPortableNetworkGraphic.Create;
5772 png.LoadFromStream(aStream);
5773 intf := png.CreateIntfImage;
5775 AssignFromLazIntfImage(intf);
5778 aStream.Position := StreamPos;
5786 aStream.Position := StreamPos;
5794 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
5795 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5796 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5798 Surface: PSDL_Surface;
5802 RWops := glBitmapCreateRWops(aStream);
5804 if IMG_isPNG(RWops) > 0 then begin
5805 Surface := IMG_LoadPNG_RW(RWops);
5807 AssignFromSurface(Surface);
5810 SDL_FreeSurface(Surface);
5818 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5819 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5820 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5822 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5825 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5826 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5829 signature: array [0..7] of byte;
5831 png_info: png_infop;
5833 TempHeight, TempWidth: Integer;
5834 Format: TglBitmapFormat;
5837 png_rows: array of pByte;
5838 Row, LineSize: Integer;
5842 if not init_libPNG then
5843 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5847 StreamPos := aStream.Position;
5848 aStream.Read(signature{%H-}, 8);
5849 aStream.Position := StreamPos;
5851 if png_check_sig(@signature, 8) <> 0 then begin
5853 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5855 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5858 png_info := png_create_info_struct(png);
5859 if png_info = nil then begin
5860 png_destroy_read_struct(@png, nil, nil);
5861 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5864 // set read callback
5865 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5867 // read informations
5868 png_read_info(png, png_info);
5871 TempHeight := png_get_image_height(png, png_info);
5872 TempWidth := png_get_image_width(png, png_info);
5875 case png_get_color_type(png, png_info) of
5876 PNG_COLOR_TYPE_GRAY:
5877 Format := tfLuminance8;
5878 PNG_COLOR_TYPE_GRAY_ALPHA:
5879 Format := tfLuminance8Alpha8;
5882 PNG_COLOR_TYPE_RGB_ALPHA:
5885 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5888 // cut upper 8 bit from 16 bit formats
5889 if png_get_bit_depth(png, png_info) > 8 then
5890 png_set_strip_16(png);
5892 // expand bitdepth smaller than 8
5893 if png_get_bit_depth(png, png_info) < 8 then
5894 png_set_expand(png);
5896 // allocating mem for scanlines
5897 LineSize := png_get_rowbytes(png, png_info);
5898 GetMem(png_data, TempHeight * LineSize);
5900 SetLength(png_rows, TempHeight);
5901 for Row := Low(png_rows) to High(png_rows) do begin
5902 png_rows[Row] := png_data;
5903 Inc(png_rows[Row], Row * LineSize);
5906 // read complete image into scanlines
5907 png_read_image(png, @png_rows[0]);
5910 png_read_end(png, png_info);
5912 // destroy read struct
5913 png_destroy_read_struct(@png, @png_info, nil);
5915 SetLength(png_rows, 0);
5918 SetDataPointer(png_data, Format, TempWidth, TempHeight); //be careful, Data could be freed by this method
5922 if Assigned(png_data) then
5932 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5933 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5934 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5939 Row, Col, PixSize, LineSize: Integer;
5940 NewImage, pSource, pDest, pAlpha: pByte;
5941 PngFormat: TglBitmapFormat;
5942 FormatDesc: TFormatDescriptor;
5945 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
5950 StreamPos := aStream.Position;
5951 aStream.Read(Header[0], SizeOf(Header));
5952 aStream.Position := StreamPos;
5954 {Test if the header matches}
5955 if Header = PngHeader then begin
5956 Png := TPNGObject.Create;
5958 Png.LoadFromStream(aStream);
5960 case Png.Header.ColorType of
5962 PngFormat := tfLuminance8;
5963 COLOR_GRAYSCALEALPHA:
5964 PngFormat := tfLuminance8Alpha8;
5966 PngFormat := tfBGR8;
5968 PngFormat := tfBGRA8;
5970 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5973 FormatDesc := TFormatDescriptor.Get(PngFormat);
5974 PixSize := Round(FormatDesc.PixelSize);
5975 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
5977 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5981 case Png.Header.ColorType of
5982 COLOR_RGB, COLOR_GRAYSCALE:
5984 for Row := 0 to Png.Height -1 do begin
5985 Move (Png.Scanline[Row]^, pDest^, LineSize);
5986 Inc(pDest, LineSize);
5989 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5991 PixSize := PixSize -1;
5993 for Row := 0 to Png.Height -1 do begin
5994 pSource := Png.Scanline[Row];
5995 pAlpha := pByte(Png.AlphaScanline[Row]);
5997 for Col := 0 to Png.Width -1 do begin
5998 Move (pSource^, pDest^, PixSize);
5999 Inc(pSource, PixSize);
6000 Inc(pDest, PixSize);
6009 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
6012 SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); //be careful, Data could be freed by this method
6016 if Assigned(NewImage) then
6028 {$IFDEF GLB_SUPPORT_PNG_WRITE}
6029 {$IFDEF GLB_LIB_PNG}
6030 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6031 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
6033 TStream(png_get_io_ptr(png)).Write(buffer^, size);
6037 {$IF DEFINED(GLB_LAZ_PNG)}
6038 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6039 procedure TglBitmap.SavePNG(const aStream: TStream);
6041 png: TPortableNetworkGraphic;
6042 intf: TLazIntfImage;
6045 png := TPortableNetworkGraphic.Create;
6046 intf := TLazIntfImage.Create(0, 0);
6048 if not AssignToLazIntfImage(intf) then
6049 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6050 intf.GetRawImage(raw);
6051 png.LoadFromRawImage(raw, false);
6052 png.SaveToStream(aStream);
6059 {$ELSEIF DEFINED(GLB_LIB_PNG)}
6060 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6061 procedure TglBitmap.SavePNG(const aStream: TStream);
6064 png_info: png_infop;
6065 png_rows: array of pByte;
6069 FormatDesc: TFormatDescriptor;
6071 if not (ftPNG in FormatGetSupportedFiles(Format)) then
6072 raise EglBitmapUnsupportedFormat.Create(Format);
6074 if not init_libPNG then
6075 raise Exception.Create('unable to initialize libPNG.');
6079 tfAlpha8, tfLuminance8:
6080 ColorType := PNG_COLOR_TYPE_GRAY;
6082 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
6084 ColorType := PNG_COLOR_TYPE_RGB;
6086 ColorType := PNG_COLOR_TYPE_RGBA;
6088 raise EglBitmapUnsupportedFormat.Create(Format);
6091 FormatDesc := TFormatDescriptor.Get(Format);
6092 LineSize := FormatDesc.GetSize(Width, 1);
6094 // creating array for scanline
6095 SetLength(png_rows, Height);
6097 for Row := 0 to Height - 1 do begin
6098 png_rows[Row] := Data;
6099 Inc(png_rows[Row], Row * LineSize)
6103 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
6105 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
6108 png_info := png_create_info_struct(png);
6109 if png_info = nil then begin
6110 png_destroy_write_struct(@png, nil);
6111 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
6114 // set read callback
6115 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
6118 png_set_compression_level(png, 6);
6120 if Format in [tfBGR8, tfBGRA8] then
6123 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
6124 png_write_info(png, png_info);
6125 png_write_image(png, @png_rows[0]);
6126 png_write_end(png, png_info);
6127 png_destroy_write_struct(@png, @png_info);
6129 SetLength(png_rows, 0);
6136 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
6137 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6138 procedure TglBitmap.SavePNG(const aStream: TStream);
6142 pSource, pDest: pByte;
6143 X, Y, PixSize: Integer;
6144 ColorType: Cardinal;
6150 if not (ftPNG in FormatGetSupportedFiles (Format)) then
6151 raise EglBitmapUnsupportedFormat.Create(Format);
6154 tfAlpha8, tfLuminance8: begin
6155 ColorType := COLOR_GRAYSCALE;
6159 tfLuminance8Alpha8: begin
6160 ColorType := COLOR_GRAYSCALEALPHA;
6164 tfBGR8, tfRGB8: begin
6165 ColorType := COLOR_RGB;
6169 tfBGRA8, tfRGBA8: begin
6170 ColorType := COLOR_RGBALPHA;
6175 raise EglBitmapUnsupportedFormat.Create(Format);
6178 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
6182 for Y := 0 to Height -1 do begin
6183 pDest := png.ScanLine[Y];
6184 for X := 0 to Width -1 do begin
6185 Move(pSource^, pDest^, PixSize);
6186 Inc(pDest, PixSize);
6187 Inc(pSource, PixSize);
6189 png.AlphaScanline[Y]^[X] := pSource^;
6194 // convert RGB line to BGR
6195 if Format in [tfRGB8, tfRGBA8] then begin
6196 pTemp := png.ScanLine[Y];
6197 for X := 0 to Width -1 do begin
6198 Temp := pByteArray(pTemp)^[0];
6199 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
6200 pByteArray(pTemp)^[2] := Temp;
6207 Png.CompressionLevel := 6;
6208 Png.SaveToStream(aStream);
6216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6217 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6218 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6219 {$IFDEF GLB_LIB_JPEG}
6221 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
6222 glBitmap_libJPEG_source_mgr = record
6223 pub: jpeg_source_mgr;
6226 SrcBuffer: array [1..4096] of byte;
6229 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
6230 glBitmap_libJPEG_dest_mgr = record
6231 pub: jpeg_destination_mgr;
6233 DestStream: TStream;
6234 DestBuffer: array [1..4096] of byte;
6237 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
6243 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
6249 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
6254 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
6260 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
6266 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6267 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
6269 src: glBitmap_libJPEG_source_mgr_ptr;
6272 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6274 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
6275 if (bytes <= 0) then begin
6276 src^.SrcBuffer[1] := $FF;
6277 src^.SrcBuffer[2] := JPEG_EOI;
6281 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
6282 src^.pub.bytes_in_buffer := bytes;
6287 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6288 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
6290 src: glBitmap_libJPEG_source_mgr_ptr;
6292 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6294 if num_bytes > 0 then begin
6295 // wanted byte isn't in buffer so set stream position and read buffer
6296 if num_bytes > src^.pub.bytes_in_buffer then begin
6297 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
6298 src^.pub.fill_input_buffer(cinfo);
6300 // wanted byte is in buffer so only skip
6301 inc(src^.pub.next_input_byte, num_bytes);
6302 dec(src^.pub.bytes_in_buffer, num_bytes);
6307 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6308 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
6310 dest: glBitmap_libJPEG_dest_mgr_ptr;
6312 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6314 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
6315 // write complete buffer
6316 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
6319 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
6320 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
6326 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6327 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
6330 dest: glBitmap_libJPEG_dest_mgr_ptr;
6332 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6334 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6335 // check for endblock
6336 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6338 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6343 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6348 {$IFDEF GLB_SUPPORT_JPEG_READ}
6349 {$IF DEFINED(GLB_LAZ_JPEG)}
6350 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6351 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6354 JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
6357 intf: TLazIntfImage;
6359 magic: String[MAGIC_LEN];
6362 StreamPos := aStream.Position;
6364 SetLength(magic, MAGIC_LEN);
6365 aStream.Read(magic[1], MAGIC_LEN);
6366 aStream.Position := StreamPos;
6367 if (magic <> JPEG_MAGIC) then begin
6372 jpeg := TJPEGImage.Create;
6374 jpeg.LoadFromStream(aStream);
6375 intf := TLazIntfImage.Create(0, 0);
6377 intf.LoadFromBitmap(jpeg.BitmapHandle, jpeg.MaskHandle);
6378 AssignFromLazIntfImage(intf);
6381 aStream.Position := StreamPos;
6389 aStream.Position := StreamPos;
6397 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
6398 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6399 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6401 Surface: PSDL_Surface;
6406 RWops := glBitmapCreateRWops(aStream);
6408 if IMG_isJPG(RWops) > 0 then begin
6409 Surface := IMG_LoadJPG_RW(RWops);
6411 AssignFromSurface(Surface);
6414 SDL_FreeSurface(Surface);
6422 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6423 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6424 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6427 Temp: array[0..1]of Byte;
6429 jpeg: jpeg_decompress_struct;
6430 jpeg_err: jpeg_error_mgr;
6432 IntFormat: TglBitmapFormat;
6434 TempHeight, TempWidth: Integer;
6439 FormatDesc: TFormatDescriptor;
6443 if not init_libJPEG then
6444 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6447 // reading first two bytes to test file and set cursor back to begin
6448 StreamPos := aStream.Position;
6449 aStream.Read({%H-}Temp[0], 2);
6450 aStream.Position := StreamPos;
6452 // if Bitmap then read file.
6453 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6454 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6455 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6458 jpeg.err := jpeg_std_error(@jpeg_err);
6459 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6460 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6462 // decompression struct
6463 jpeg_create_decompress(@jpeg);
6465 // allocation space for streaming methods
6466 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6468 // seeting up custom functions
6469 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6470 pub.init_source := glBitmap_libJPEG_init_source;
6471 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6472 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6473 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6474 pub.term_source := glBitmap_libJPEG_term_source;
6476 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6477 pub.next_input_byte := nil; // until buffer loaded
6479 SrcStream := aStream;
6482 // set global decoding state
6483 jpeg.global_state := DSTATE_START;
6485 // read header of jpeg
6486 jpeg_read_header(@jpeg, false);
6488 // setting output parameter
6489 case jpeg.jpeg_color_space of
6492 jpeg.out_color_space := JCS_GRAYSCALE;
6493 IntFormat := tfLuminance8;
6496 jpeg.out_color_space := JCS_RGB;
6497 IntFormat := tfRGB8;
6501 jpeg_start_decompress(@jpeg);
6503 TempHeight := jpeg.output_height;
6504 TempWidth := jpeg.output_width;
6506 FormatDesc := TFormatDescriptor.Get(IntFormat);
6508 // creating new image
6509 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6513 for Row := 0 to TempHeight -1 do begin
6514 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6515 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6518 // finish decompression
6519 jpeg_finish_decompress(@jpeg);
6521 // destroy decompression
6522 jpeg_destroy_decompress(@jpeg);
6524 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
6528 if Assigned(pImage) then
6538 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6539 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6540 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6545 Temp: array[0..1]of Byte;
6549 // reading first two bytes to test file and set cursor back to begin
6550 StreamPos := aStream.Position;
6551 aStream.Read(Temp[0], 2);
6552 aStream.Position := StreamPos;
6554 // if Bitmap then read file.
6555 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6556 bmp := TBitmap.Create;
6558 jpg := TJPEGImage.Create;
6560 jpg.LoadFromStream(aStream);
6562 result := AssignFromBitmap(bmp);
6574 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6575 {$IF DEFINED(GLB_LAZ_JPEG)}
6576 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6577 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6580 intf: TLazIntfImage;
6583 jpeg := TJPEGImage.Create;
6584 intf := TLazIntfImage.Create(0, 0);
6586 if not AssignToLazIntfImage(intf) then
6587 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6588 intf.GetRawImage(raw);
6589 jpeg.LoadFromRawImage(raw, false);
6590 jpeg.SaveToStream(aStream);
6597 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6598 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6599 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6601 jpeg: jpeg_compress_struct;
6602 jpeg_err: jpeg_error_mgr;
6604 pTemp, pTemp2: pByte;
6606 procedure CopyRow(pDest, pSource: pByte);
6610 for X := 0 to Width - 1 do begin
6611 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6612 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6613 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6620 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6621 raise EglBitmapUnsupportedFormat.Create(Format);
6623 if not init_libJPEG then
6624 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6627 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6628 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6631 jpeg.err := jpeg_std_error(@jpeg_err);
6632 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6633 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6635 // compression struct
6636 jpeg_create_compress(@jpeg);
6638 // allocation space for streaming methods
6639 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6641 // seeting up custom functions
6642 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6643 pub.init_destination := glBitmap_libJPEG_init_destination;
6644 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6645 pub.term_destination := glBitmap_libJPEG_term_destination;
6647 pub.next_output_byte := @DestBuffer[1];
6648 pub.free_in_buffer := Length(DestBuffer);
6650 DestStream := aStream;
6653 // very important state
6654 jpeg.global_state := CSTATE_START;
6655 jpeg.image_width := Width;
6656 jpeg.image_height := Height;
6658 tfAlpha8, tfLuminance8: begin
6659 jpeg.input_components := 1;
6660 jpeg.in_color_space := JCS_GRAYSCALE;
6662 tfRGB8, tfBGR8: begin
6663 jpeg.input_components := 3;
6664 jpeg.in_color_space := JCS_RGB;
6668 jpeg_set_defaults(@jpeg);
6669 jpeg_set_quality(@jpeg, 95, true);
6670 jpeg_start_compress(@jpeg, true);
6673 if Format = tfBGR8 then
6674 GetMem(pTemp2, fRowSize)
6679 for Row := 0 to jpeg.image_height -1 do begin
6681 if Format = tfBGR8 then
6682 CopyRow(pTemp2, pTemp)
6687 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6688 inc(pTemp, fRowSize);
6692 if Format = tfBGR8 then
6695 jpeg_finish_compress(@jpeg);
6696 jpeg_destroy_compress(@jpeg);
6702 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6703 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6704 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6709 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6710 raise EglBitmapUnsupportedFormat.Create(Format);
6712 Bmp := TBitmap.Create;
6714 Jpg := TJPEGImage.Create;
6716 AssignToBitmap(Bmp);
6717 if (Format in [tfAlpha8, tfLuminance8]) then begin
6718 Jpg.Grayscale := true;
6719 Jpg.PixelFormat := jf8Bit;
6722 Jpg.SaveToStream(aStream);
6733 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6734 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6735 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6742 BMP_COMP_BITFIELDS = 3;
6745 TBMPHeader = packed record
6750 bfOffBits: Cardinal;
6753 TBMPInfo = packed record
6759 biCompression: Cardinal;
6760 biSizeImage: Cardinal;
6761 biXPelsPerMeter: Longint;
6762 biYPelsPerMeter: Longint;
6763 biClrUsed: Cardinal;
6764 biClrImportant: Cardinal;
6767 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6768 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6770 //////////////////////////////////////////////////////////////////////////////////////////////////
6771 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6774 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6775 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6778 case aInfo.biCompression of
6780 BMP_COMP_RLE8: begin
6781 raise EglBitmap.Create('RLE compression is not supported');
6783 BMP_COMP_BITFIELDS: begin
6784 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6785 aStream.Read(aMask.r, SizeOf(aMask.r));
6786 aStream.Read(aMask.g, SizeOf(aMask.g));
6787 aStream.Read(aMask.b, SizeOf(aMask.b));
6788 aStream.Read(aMask.a, SizeOf(aMask.a));
6790 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
6794 //get suitable format
6795 case aInfo.biBitCount of
6796 8: result := tfLuminance8;
6797 16: result := tfBGR5;
6798 24: result := tfBGR8;
6799 32: result := tfBGRA8;
6803 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6806 ColorTable: TbmpColorTable;
6809 if (aInfo.biBitCount >= 16) then
6811 aFormat := tfLuminance8;
6812 c := aInfo.biClrUsed;
6814 c := 1 shl aInfo.biBitCount;
6815 SetLength(ColorTable, c);
6816 for i := 0 to c-1 do begin
6817 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6818 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6822 result := TbmpColorTableFormat.Create;
6823 result.PixelSize := aInfo.biBitCount / 8;
6824 result.ColorTable := ColorTable;
6825 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6828 //////////////////////////////////////////////////////////////////////////////////////////////////
6829 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6830 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6832 TmpFormat: TglBitmapFormat;
6833 FormatDesc: TFormatDescriptor;
6836 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6837 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6838 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6839 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6840 aFormat := FormatDesc.Format;
6845 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6846 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6847 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6848 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6850 result := TbmpBitfieldFormat.Create;
6851 result.PixelSize := aInfo.biBitCount / 8;
6852 result.RedMask := aMask.r;
6853 result.GreenMask := aMask.g;
6854 result.BlueMask := aMask.b;
6855 result.AlphaMask := aMask.a;
6862 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6863 PaddingBuff: Cardinal;
6864 LineBuf, ImageData, TmpData: PByte;
6865 SourceMD, DestMD: Pointer;
6866 BmpFormat: TglBitmapFormat;
6869 Mask: TglBitmapColorRec;
6874 SpecialFormat: TFormatDescriptor;
6875 FormatDesc: TFormatDescriptor;
6877 //////////////////////////////////////////////////////////////////////////////////////////////////
6878 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6881 Pixel: TglBitmapPixelData;
6883 aStream.Read(aLineBuf^, rbLineSize);
6884 SpecialFormat.PreparePixel(Pixel);
6885 for i := 0 to Info.biWidth-1 do begin
6886 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6887 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6888 FormatDesc.Map(Pixel, aData, DestMD);
6894 BmpFormat := tfEmpty;
6895 SpecialFormat := nil;
6901 StartPos := aStream.Position;
6902 aStream.Read(Header{%H-}, SizeOf(Header));
6904 if Header.bfType = BMP_MAGIC then begin
6906 BmpFormat := ReadInfo(Info, Mask);
6907 SpecialFormat := ReadColorTable(BmpFormat, Info);
6908 if not Assigned(SpecialFormat) then
6909 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6910 aStream.Position := StartPos + Header.bfOffBits;
6912 if (BmpFormat <> tfEmpty) then begin
6913 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6914 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6915 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6916 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6919 DestMD := FormatDesc.CreateMappingData;
6920 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6921 GetMem(ImageData, ImageSize);
6922 if Assigned(SpecialFormat) then begin
6923 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6924 SourceMD := SpecialFormat.CreateMappingData;
6929 FillChar(ImageData^, ImageSize, $FF);
6930 TmpData := ImageData;
6931 if (Info.biHeight > 0) then
6932 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6933 for i := 0 to Abs(Info.biHeight)-1 do begin
6934 if Assigned(SpecialFormat) then
6935 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6937 aStream.Read(TmpData^, wbLineSize); //else only read data
6938 if (Info.biHeight > 0) then
6939 dec(TmpData, wbLineSize)
6941 inc(TmpData, wbLineSize);
6942 aStream.Read(PaddingBuff{%H-}, Padding);
6944 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method
6947 if Assigned(LineBuf) then
6949 if Assigned(SourceMD) then
6950 SpecialFormat.FreeMappingData(SourceMD);
6951 FormatDesc.FreeMappingData(DestMD);
6954 if Assigned(ImageData) then
6959 raise EglBitmap.Create('LoadBMP - No suitable format found');
6961 aStream.Position := StartPos;
6965 FreeAndNil(SpecialFormat);
6968 else aStream.Position := StartPos;
6971 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6972 procedure TglBitmap.SaveBMP(const aStream: TStream);
6976 Converter: TFormatDescriptor;
6977 FormatDesc: TFormatDescriptor;
6978 SourceFD, DestFD: Pointer;
6979 pData, srcData, dstData, ConvertBuffer: pByte;
6981 Pixel: TglBitmapPixelData;
6982 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6983 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6985 PaddingBuff: Cardinal;
6987 function GetLineWidth : Integer;
6989 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6993 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6994 raise EglBitmapUnsupportedFormat.Create(Format);
6997 FormatDesc := TFormatDescriptor.Get(Format);
6998 ImageSize := FormatDesc.GetSize(Dimension);
7000 FillChar(Header{%H-}, SizeOf(Header), 0);
7001 Header.bfType := BMP_MAGIC;
7002 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
7003 Header.bfReserved1 := 0;
7004 Header.bfReserved2 := 0;
7005 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
7007 FillChar(Info{%H-}, SizeOf(Info), 0);
7008 Info.biSize := SizeOf(Info);
7009 Info.biWidth := Width;
7010 Info.biHeight := Height;
7012 Info.biCompression := BMP_COMP_RGB;
7013 Info.biSizeImage := ImageSize;
7018 Info.biBitCount := 4;
7019 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
7020 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
7021 Converter := TbmpColorTableFormat.Create;
7022 with (Converter as TbmpColorTableFormat) do begin
7025 Range := glBitmapColorRec($F, $F, $F, $0);
7030 tfR3G3B2, tfLuminance8: begin
7031 Info.biBitCount := 8;
7032 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
7033 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
7034 Converter := TbmpColorTableFormat.Create;
7035 with (Converter as TbmpColorTableFormat) do begin
7038 if (Format = tfR3G3B2) then begin
7039 Range := glBitmapColorRec($7, $7, $3, $0);
7040 Shift := glBitmapShiftRec(0, 3, 6, 0);
7042 Range := glBitmapColorRec($FF, $FF, $FF, $0);
7047 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
7048 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
7049 Info.biBitCount := 16;
7050 Info.biCompression := BMP_COMP_BITFIELDS;
7053 tfBGR8, tfRGB8: begin
7054 Info.biBitCount := 24;
7055 if (Format = tfRGB8) then
7056 Converter := TfdBGR8.Create; //use BGR8 Format Descriptor to Swap RGB Values
7059 tfRGB10, tfRGB10A2, tfRGBA8,
7060 tfBGR10, tfBGR10A2, tfBGRA8: begin
7061 Info.biBitCount := 32;
7062 Info.biCompression := BMP_COMP_BITFIELDS;
7065 raise EglBitmapUnsupportedFormat.Create(Format);
7067 Info.biXPelsPerMeter := 2835;
7068 Info.biYPelsPerMeter := 2835;
7071 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7072 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
7073 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
7075 RedMask := FormatDesc.RedMask;
7076 GreenMask := FormatDesc.GreenMask;
7077 BlueMask := FormatDesc.BlueMask;
7078 AlphaMask := FormatDesc.AlphaMask;
7082 aStream.Write(Header, SizeOf(Header));
7083 aStream.Write(Info, SizeOf(Info));
7086 if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
7087 with (Converter as TbmpColorTableFormat) do
7088 aStream.Write(ColorTable[0].b,
7089 SizeOf(TbmpColorTableEnty) * Length(ColorTable));
7092 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7093 aStream.Write(RedMask, SizeOf(Cardinal));
7094 aStream.Write(GreenMask, SizeOf(Cardinal));
7095 aStream.Write(BlueMask, SizeOf(Cardinal));
7096 aStream.Write(AlphaMask, SizeOf(Cardinal));
7100 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
7101 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
7102 Padding := GetLineWidth - wbLineSize;
7106 inc(pData, (Height-1) * rbLineSize);
7108 // prepare row buffer. But only for RGB because RGBA supports color masks
7109 // so it's possible to change color within the image.
7110 if Assigned(Converter) then begin
7111 FormatDesc.PreparePixel(Pixel);
7112 GetMem(ConvertBuffer, wbLineSize);
7113 SourceFD := FormatDesc.CreateMappingData;
7114 DestFD := Converter.CreateMappingData;
7116 ConvertBuffer := nil;
7119 for LineIdx := 0 to Height - 1 do begin
7121 if Assigned(Converter) then begin
7123 dstData := ConvertBuffer;
7124 for PixelIdx := 0 to Info.biWidth-1 do begin
7125 FormatDesc.Unmap(srcData, Pixel, SourceFD);
7126 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
7127 Converter.Map(Pixel, dstData, DestFD);
7129 aStream.Write(ConvertBuffer^, wbLineSize);
7131 aStream.Write(pData^, rbLineSize);
7133 dec(pData, rbLineSize);
7134 if (Padding > 0) then
7135 aStream.Write(PaddingBuff, Padding);
7138 // destroy row buffer
7139 if Assigned(ConvertBuffer) then begin
7140 FormatDesc.FreeMappingData(SourceFD);
7141 Converter.FreeMappingData(DestFD);
7142 FreeMem(ConvertBuffer);
7146 if Assigned(Converter) then
7151 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7152 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7153 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7155 TTGAHeader = packed record
7159 //ColorMapSpec: Array[0..4] of Byte;
7160 ColorMapStart: Word;
7161 ColorMapLength: Word;
7162 ColorMapEntrySize: Byte;
7172 TGA_UNCOMPRESSED_RGB = 2;
7173 TGA_UNCOMPRESSED_GRAY = 3;
7174 TGA_COMPRESSED_RGB = 10;
7175 TGA_COMPRESSED_GRAY = 11;
7177 TGA_NONE_COLOR_TABLE = 0;
7179 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7180 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
7183 ImageData: System.PByte;
7184 StartPosition: Int64;
7185 PixelSize, LineSize: Integer;
7186 tgaFormat: TglBitmapFormat;
7187 FormatDesc: TFormatDescriptor;
7188 Counter: packed record
7190 low, high, dir: Integer;
7197 ////////////////////////////////////////////////////////////////////////////////////////
7198 procedure ReadUncompressed;
7201 buf, tmp1, tmp2: System.PByte;
7204 if (Counter.X.dir < 0) then
7205 GetMem(buf, LineSize);
7207 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
7209 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
7210 if (Counter.X.dir < 0) then begin //flip X
7211 aStream.Read(buf^, LineSize);
7213 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
7214 for i := 0 to Header.Width-1 do begin //for all pixels in line
7215 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
7220 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
7223 aStream.Read(tmp1^, LineSize);
7224 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
7227 if Assigned(buf) then
7232 ////////////////////////////////////////////////////////////////////////////////////////
7233 procedure ReadCompressed;
7235 /////////////////////////////////////////////////////////////////
7237 TmpData: System.PByte;
7238 LinePixelsRead: Integer;
7239 procedure CheckLine;
7241 if (LinePixelsRead >= Header.Width) then begin
7242 LinePixelsRead := 0;
7243 inc(Counter.Y.low, Counter.Y.dir); //next line index
7244 TmpData := ImageData;
7245 inc(TmpData, Counter.Y.low * LineSize); //set line
7246 if (Counter.X.dir < 0) then //if x flipped then
7247 inc(TmpData, LineSize - PixelSize); //set last pixel
7251 /////////////////////////////////////////////////////////////////
7254 CacheSize, CachePos: Integer;
7255 procedure CachedRead(out Buffer; Count: Integer);
7259 if (CachePos + Count > CacheSize) then begin
7260 //if buffer overflow save non read bytes
7262 if (CacheSize - CachePos > 0) then begin
7263 BytesRead := CacheSize - CachePos;
7264 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
7265 inc(CachePos, BytesRead);
7268 //load cache from file
7269 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
7270 aStream.Read(Cache^, CacheSize);
7273 //read rest of requested bytes
7274 if (Count - BytesRead > 0) then begin
7275 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
7276 inc(CachePos, Count - BytesRead);
7279 //if no buffer overflow just read the data
7280 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
7281 inc(CachePos, Count);
7285 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
7290 inc(aBuffer, Counter.X.dir);
7293 PWord(aBuffer)^ := PWord(aData)^;
7294 inc(aBuffer, 2 * Counter.X.dir);
7297 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
7298 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
7299 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
7300 inc(aBuffer, 3 * Counter.X.dir);
7303 PCardinal(aBuffer)^ := PCardinal(aData)^;
7304 inc(aBuffer, 4 * Counter.X.dir);
7310 TotalPixelsToRead, TotalPixelsRead: Integer;
7312 buf: array [0..3] of Byte; //1 pixel is max 32bit long
7313 PixelRepeat: Boolean;
7314 PixelsToRead, PixelCount: Integer;
7319 TotalPixelsToRead := Header.Width * Header.Height;
7320 TotalPixelsRead := 0;
7321 LinePixelsRead := 0;
7323 GetMem(Cache, CACHE_SIZE);
7325 TmpData := ImageData;
7326 inc(TmpData, Counter.Y.low * LineSize); //set line
7327 if (Counter.X.dir < 0) then //if x flipped then
7328 inc(TmpData, LineSize - PixelSize); //set last pixel
7332 CachedRead(Temp, 1);
7333 PixelRepeat := (Temp and $80) > 0;
7334 PixelsToRead := (Temp and $7F) + 1;
7335 inc(TotalPixelsRead, PixelsToRead);
7338 CachedRead(buf[0], PixelSize);
7339 while (PixelsToRead > 0) do begin
7341 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
7342 while (PixelCount > 0) do begin
7343 if not PixelRepeat then
7344 CachedRead(buf[0], PixelSize);
7345 PixelToBuffer(@buf[0], TmpData);
7346 inc(LinePixelsRead);
7351 until (TotalPixelsRead >= TotalPixelsToRead);
7357 function IsGrayFormat: Boolean;
7359 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
7365 // reading header to test file and set cursor back to begin
7366 StartPosition := aStream.Position;
7367 aStream.Read(Header{%H-}, SizeOf(Header));
7369 // no colormapped files
7370 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
7371 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
7374 if Header.ImageID <> 0 then // skip image ID
7375 aStream.Position := aStream.Position + Header.ImageID;
7377 tgaFormat := tfEmpty;
7379 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
7380 0: tgaFormat := tfLuminance8;
7381 8: tgaFormat := tfAlpha8;
7384 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
7385 0: tgaFormat := tfLuminance16;
7386 8: tgaFormat := tfLuminance8Alpha8;
7387 end else case (Header.ImageDesc and $F) of
7388 0: tgaFormat := tfBGR5;
7389 1: tgaFormat := tfBGR5A1;
7390 4: tgaFormat := tfBGRA4;
7393 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7394 0: tgaFormat := tfBGR8;
7397 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7398 2: tgaFormat := tfBGR10A2;
7399 8: tgaFormat := tfBGRA8;
7403 if (tgaFormat = tfEmpty) then
7404 raise EglBitmap.Create('LoadTga - unsupported format');
7406 FormatDesc := TFormatDescriptor.Get(tgaFormat);
7407 PixelSize := FormatDesc.GetSize(1, 1);
7408 LineSize := FormatDesc.GetSize(Header.Width, 1);
7410 GetMem(ImageData, LineSize * Header.Height);
7413 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7414 Counter.X.low := Header.Height-1;;
7415 Counter.X.high := 0;
7416 Counter.X.dir := -1;
7419 Counter.X.high := Header.Height-1;
7424 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7426 Counter.Y.high := Header.Height-1;
7429 Counter.Y.low := Header.Height-1;;
7430 Counter.Y.high := 0;
7431 Counter.Y.dir := -1;
7435 case Header.ImageType of
7436 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7438 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7442 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method
7445 if Assigned(ImageData) then
7450 aStream.Position := StartPosition;
7453 else aStream.Position := StartPosition;
7456 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7457 procedure TglBitmap.SaveTGA(const aStream: TStream);
7460 LineSize, Size, x, y: Integer;
7461 Pixel: TglBitmapPixelData;
7462 LineBuf, SourceData, DestData: PByte;
7463 SourceMD, DestMD: Pointer;
7464 FormatDesc: TFormatDescriptor;
7465 Converter: TFormatDescriptor;
7467 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7468 raise EglBitmapUnsupportedFormat.Create(Format);
7471 FillChar(Header{%H-}, SizeOf(Header), 0);
7474 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7475 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7476 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7478 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7481 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7483 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7484 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7486 else if (Format in [tfBGR8, tfRGB8]) then
7494 Header.ImageDesc := 1 and $F;
7495 tfRGB10A2, tfBGR10A2:
7496 Header.ImageDesc := 2 and $F;
7498 Header.ImageDesc := 4 and $F;
7499 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7500 Header.ImageDesc := 8 and $F;
7503 Header.Width := Width;
7504 Header.Height := Height;
7505 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7506 aStream.Write(Header, SizeOf(Header));
7508 // convert RGB(A) to BGR(A)
7510 FormatDesc := TFormatDescriptor.Get(Format);
7511 Size := FormatDesc.GetSize(Dimension);
7512 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7513 if (FormatDesc.RGBInverted = tfEmpty) then
7514 raise EglBitmap.Create('inverted RGB format is empty');
7515 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7516 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7517 (Converter.PixelSize <> FormatDesc.PixelSize) then
7518 raise EglBitmap.Create('invalid inverted RGB format');
7521 if Assigned(Converter) then begin
7522 LineSize := FormatDesc.GetSize(Width, 1);
7523 GetMem(LineBuf, LineSize);
7524 SourceMD := FormatDesc.CreateMappingData;
7525 DestMD := Converter.CreateMappingData;
7528 for y := 0 to Height-1 do begin
7529 DestData := LineBuf;
7530 for x := 0 to Width-1 do begin
7531 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7532 Converter.Map(Pixel, DestData, DestMD);
7534 aStream.Write(LineBuf^, LineSize);
7538 FormatDesc.FreeMappingData(SourceMD);
7539 FormatDesc.FreeMappingData(DestMD);
7542 aStream.Write(Data^, Size);
7545 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7546 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7547 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7549 DDS_MAGIC: Cardinal = $20534444;
7551 // DDS_header.dwFlags
7552 DDSD_CAPS = $00000001;
7553 DDSD_HEIGHT = $00000002;
7554 DDSD_WIDTH = $00000004;
7555 DDSD_PIXELFORMAT = $00001000;
7557 // DDS_header.sPixelFormat.dwFlags
7558 DDPF_ALPHAPIXELS = $00000001;
7559 DDPF_ALPHA = $00000002;
7560 DDPF_FOURCC = $00000004;
7561 DDPF_RGB = $00000040;
7562 DDPF_LUMINANCE = $00020000;
7564 // DDS_header.sCaps.dwCaps1
7565 DDSCAPS_TEXTURE = $00001000;
7567 // DDS_header.sCaps.dwCaps2
7568 DDSCAPS2_CUBEMAP = $00000200;
7570 D3DFMT_DXT1 = $31545844;
7571 D3DFMT_DXT3 = $33545844;
7572 D3DFMT_DXT5 = $35545844;
7575 TDDSPixelFormat = packed record
7579 dwRGBBitCount: Cardinal;
7580 dwRBitMask: Cardinal;
7581 dwGBitMask: Cardinal;
7582 dwBBitMask: Cardinal;
7583 dwABitMask: Cardinal;
7586 TDDSCaps = packed record
7590 dwReserved: Cardinal;
7593 TDDSHeader = packed record
7598 dwPitchOrLinearSize: Cardinal;
7600 dwMipMapCount: Cardinal;
7601 dwReserved: array[0..10] of Cardinal;
7602 PixelFormat: TDDSPixelFormat;
7604 dwReserved2: Cardinal;
7607 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7608 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7611 Converter: TbmpBitfieldFormat;
7613 function GetDDSFormat: TglBitmapFormat;
7615 fd: TFormatDescriptor;
7617 Range: TglBitmapColorRec;
7621 with Header.PixelFormat do begin
7623 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7624 case Header.PixelFormat.dwFourCC of
7625 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7626 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7627 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7629 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7631 //find matching format
7632 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7633 fd := TFormatDescriptor.Get(result);
7634 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7635 (8 * fd.PixelSize = dwRGBBitCount) then
7639 //find format with same Range
7640 Range.r := dwRBitMask;
7641 Range.g := dwGBitMask;
7642 Range.b := dwBBitMask;
7643 Range.a := dwABitMask;
7644 for i := 0 to 3 do begin
7645 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7646 Range.arr[i] := Range.arr[i] shr 1;
7648 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7649 fd := TFormatDescriptor.Get(result);
7652 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7660 //no format with same range found -> use default
7661 if (result = tfEmpty) then begin
7662 if (dwABitMask > 0) then
7668 Converter := TbmpBitfieldFormat.Create;
7669 Converter.RedMask := dwRBitMask;
7670 Converter.GreenMask := dwGBitMask;
7671 Converter.BlueMask := dwBBitMask;
7672 Converter.AlphaMask := dwABitMask;
7673 Converter.PixelSize := dwRGBBitCount / 8;
7680 x, y, LineSize, RowSize, Magic: Cardinal;
7681 NewImage, TmpData, RowData, SrcData: System.PByte;
7682 SourceMD, DestMD: Pointer;
7683 Pixel: TglBitmapPixelData;
7684 ddsFormat: TglBitmapFormat;
7685 FormatDesc: TFormatDescriptor;
7690 StreamPos := aStream.Position;
7693 aStream.Read(Magic{%H-}, sizeof(Magic));
7694 if (Magic <> DDS_MAGIC) then begin
7695 aStream.Position := StreamPos;
7700 aStream.Read(Header{%H-}, sizeof(Header));
7701 if (Header.dwSize <> SizeOf(Header)) or
7702 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7703 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7705 aStream.Position := StreamPos;
7709 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7710 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
7712 ddsFormat := GetDDSFormat;
7714 if (ddsFormat = tfEmpty) then
7715 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7717 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7718 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7719 GetMem(NewImage, Header.dwHeight * LineSize);
7721 TmpData := NewImage;
7724 if Assigned(Converter) then begin
7725 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7726 GetMem(RowData, RowSize);
7727 SourceMD := Converter.CreateMappingData;
7728 DestMD := FormatDesc.CreateMappingData;
7730 for y := 0 to Header.dwHeight-1 do begin
7731 TmpData := NewImage;
7732 inc(TmpData, y * LineSize);
7734 aStream.Read(SrcData^, RowSize);
7735 for x := 0 to Header.dwWidth-1 do begin
7736 Converter.Unmap(SrcData, Pixel, SourceMD);
7737 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7738 FormatDesc.Map(Pixel, TmpData, DestMD);
7742 Converter.FreeMappingData(SourceMD);
7743 FormatDesc.FreeMappingData(DestMD);
7749 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7750 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7751 for Y := 0 to Header.dwHeight-1 do begin
7752 aStream.Read(TmpData^, RowSize);
7753 Inc(TmpData, LineSize);
7758 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7759 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7760 for Y := 0 to Header.dwHeight-1 do begin
7761 aStream.Read(TmpData^, RowSize);
7762 Inc(TmpData, LineSize);
7765 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7767 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method
7770 if Assigned(NewImage) then
7775 FreeAndNil(Converter);
7779 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7780 procedure TglBitmap.SaveDDS(const aStream: TStream);
7783 FormatDesc: TFormatDescriptor;
7785 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7786 raise EglBitmapUnsupportedFormat.Create(Format);
7788 FormatDesc := TFormatDescriptor.Get(Format);
7791 FillChar(Header{%H-}, SizeOf(Header), 0);
7792 Header.dwSize := SizeOf(Header);
7793 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7795 Header.dwWidth := Max(1, Width);
7796 Header.dwHeight := Max(1, Height);
7799 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7802 Header.PixelFormat.dwSize := sizeof(Header);
7803 if (FormatDesc.IsCompressed) then begin
7804 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7806 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7807 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7808 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7810 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7811 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7812 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7813 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7814 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7815 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7816 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7817 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7818 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7820 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7821 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7822 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7823 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7824 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7825 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7828 if (FormatDesc.HasAlpha) then
7829 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7831 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7832 aStream.Write(Header, SizeOf(Header));
7833 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7836 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7837 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7838 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7839 procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7840 const aWidth: Integer; const aHeight: Integer);
7845 if (aHeight > 1) then begin
7846 Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1);
7847 GetMem(pTemp, Size);
7849 Move(aData^, pTemp^, Size);
7858 inherited SetDataPointer(pTemp, aFormat, aWidth);
7861 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7862 function TglBitmap1D.FlipHorz: Boolean;
7865 pTempDest, pDest, pSource: PByte;
7867 result := inherited FlipHorz;
7868 if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin
7870 GetMem(pDest, fRowSize);
7873 Inc(pTempDest, fRowSize);
7874 for Col := 0 to Width-1 do begin
7875 dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data
7876 Move(pSource^, pTempDest^, fPixelSize);
7877 Inc(pSource, fPixelSize);
7879 SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method
7882 if Assigned(pDest) then
7889 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7890 procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean);
7892 FormatDesc: TFormatDescriptor;
7895 FormatDesc := TFormatDescriptor.Get(Format);
7896 if FormatDesc.IsCompressed then begin
7897 if not Assigned(glCompressedTexImage1D) then
7898 raise EglBitmap.Create('compressed formats not supported by video adapter');
7899 glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
7900 end else if aBuildWithGlu then
7901 gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7903 glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7906 if (FreeDataAfterGenTexture) then
7910 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7911 procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean);
7913 BuildWithGlu, TexRec: Boolean;
7916 if Assigned(Data) then begin
7917 // Check Texture Size
7918 if (aTestTextureSize) then begin
7919 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7921 if (Width > TexSize) then
7922 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7924 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7925 (Target = GL_TEXTURE_RECTANGLE);
7926 if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7927 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7931 SetupParameters(BuildWithGlu);
7932 UploadData(BuildWithGlu);
7933 glAreTexturesResident(1, @fID, @fIsResident);
7937 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7938 procedure TglBitmap1D.AfterConstruction;
7941 Target := GL_TEXTURE_1D;
7944 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7945 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7946 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7947 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7949 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7950 result := fLines[aIndex]
7955 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7956 procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7957 const aWidth: Integer; const aHeight: Integer);
7959 Idx, LineWidth: Integer;
7961 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7963 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7965 if Assigned(Data) then begin
7966 SetLength(fLines, GetHeight);
7967 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7969 for Idx := 0 to GetHeight-1 do begin
7970 fLines[Idx] := Data;
7971 Inc(fLines[Idx], Idx * LineWidth);
7974 else SetLength(fLines, 0);
7976 SetLength(fLines, 0);
7980 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7981 procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
7983 FormatDesc: TFormatDescriptor;
7985 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7987 FormatDesc := TFormatDescriptor.Get(Format);
7988 if FormatDesc.IsCompressed then begin
7989 if not Assigned(glCompressedTexImage2D) then
7990 raise EglBitmap.Create('compressed formats not supported by video adapter');
7991 glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7992 end else if aBuildWithGlu then begin
7993 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7994 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7996 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7997 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
8001 if (FreeDataAfterGenTexture) then
8005 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8006 procedure TglBitmap2D.AfterConstruction;
8009 Target := GL_TEXTURE_2D;
8012 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8013 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
8016 Size, w, h: Integer;
8017 FormatDesc: TFormatDescriptor;
8019 FormatDesc := TFormatDescriptor.Get(aFormat);
8020 if FormatDesc.IsCompressed then
8021 raise EglBitmapUnsupportedFormat.Create(aFormat);
8023 w := aRight - aLeft;
8024 h := aBottom - aTop;
8025 Size := FormatDesc.GetSize(w, h);
8028 glPixelStorei(GL_PACK_ALIGNMENT, 1);
8029 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8030 SetDataPointer(Temp, aFormat, w, h); //be careful, Data could be freed by this method
8033 if Assigned(Temp) then
8039 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8040 procedure TglBitmap2D.GetDataFromTexture;
8043 TempWidth, TempHeight: Integer;
8044 TempIntFormat: Cardinal;
8045 IntFormat, f: TglBitmapFormat;
8046 FormatDesc: TFormatDescriptor;
8051 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
8052 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
8053 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
8055 IntFormat := tfEmpty;
8056 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
8057 FormatDesc := TFormatDescriptor.Get(f);
8058 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
8059 IntFormat := FormatDesc.Format;
8064 // Getting data from OpenGL
8065 FormatDesc := TFormatDescriptor.Get(IntFormat);
8066 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
8068 if FormatDesc.IsCompressed then begin
8069 if not Assigned(glGetCompressedTexImage) then
8070 raise EglBitmap.Create('compressed formats not supported by video adapter');
8071 glGetCompressedTexImage(Target, 0, Temp)
8073 glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8074 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
8076 if Assigned(Temp) then
8082 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8083 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
8085 BuildWithGlu, PotTex, TexRec: Boolean;
8088 if Assigned(Data) then begin
8089 // Check Texture Size
8090 if (aTestTextureSize) then begin
8091 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8093 if ((Height > TexSize) or (Width > TexSize)) then
8094 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8096 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
8097 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
8098 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8099 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8103 SetupParameters(BuildWithGlu);
8104 UploadData(Target, BuildWithGlu);
8105 glAreTexturesResident(1, @fID, @fIsResident);
8109 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8110 function TglBitmap2D.FlipHorz: Boolean;
8113 TempDestData, DestData, SourceData: PByte;
8116 result := inherited FlipHorz;
8117 if Assigned(Data) then begin
8119 ImgSize := Height * fRowSize;
8120 GetMem(DestData, ImgSize);
8122 TempDestData := DestData;
8123 Dec(TempDestData, fRowSize + fPixelSize);
8124 for Row := 0 to Height -1 do begin
8125 Inc(TempDestData, fRowSize * 2);
8126 for Col := 0 to Width -1 do begin
8127 Move(SourceData^, TempDestData^, fPixelSize);
8128 Inc(SourceData, fPixelSize);
8129 Dec(TempDestData, fPixelSize);
8132 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8135 if Assigned(DestData) then
8142 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8143 function TglBitmap2D.FlipVert: Boolean;
8146 TempDestData, DestData, SourceData: PByte;
8148 result := inherited FlipVert;
8149 if Assigned(Data) then begin
8151 GetMem(DestData, Height * fRowSize);
8153 TempDestData := DestData;
8154 Inc(TempDestData, Width * (Height -1) * fPixelSize);
8155 for Row := 0 to Height -1 do begin
8156 Move(SourceData^, TempDestData^, fRowSize);
8157 Dec(TempDestData, fRowSize);
8158 Inc(SourceData, fRowSize);
8160 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
8163 if Assigned(DestData) then
8170 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8171 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8172 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8174 TMatrixItem = record
8179 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
8180 TglBitmapToNormalMapRec = Record
8182 Heights: array of Single;
8183 MatrixU : array of TMatrixItem;
8184 MatrixV : array of TMatrixItem;
8188 ONE_OVER_255 = 1 / 255;
8190 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8191 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
8195 with FuncRec do begin
8197 Source.Data.r * LUMINANCE_WEIGHT_R +
8198 Source.Data.g * LUMINANCE_WEIGHT_G +
8199 Source.Data.b * LUMINANCE_WEIGHT_B;
8200 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
8204 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8205 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
8208 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
8211 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8212 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
8214 TVec = Array[0..2] of Single;
8221 function GetHeight(X, Y: Integer): Single;
8223 with FuncRec do begin
8224 X := Max(0, Min(Size.X -1, X));
8225 Y := Max(0, Min(Size.Y -1, Y));
8226 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
8231 with FuncRec do begin
8232 with PglBitmapToNormalMapRec(Args)^ do begin
8234 for Idx := Low(MatrixU) to High(MatrixU) do
8235 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
8238 for Idx := Low(MatrixU) to High(MatrixU) do
8239 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
8241 Vec[0] := -du * Scale;
8242 Vec[1] := -dv * Scale;
8247 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8248 if Len <> 0 then begin
8249 Vec[0] := Vec[0] * Len;
8250 Vec[1] := Vec[1] * Len;
8251 Vec[2] := Vec[2] * Len;
8255 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
8256 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
8257 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
8261 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8262 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
8264 Rec: TglBitmapToNormalMapRec;
8266 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
8268 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
8269 Matrix[Index].X := X;
8270 Matrix[Index].Y := Y;
8271 Matrix[Index].W := W;
8276 if TFormatDescriptor.Get(Format).IsCompressed then
8277 raise EglBitmapUnsupportedFormat.Create(Format);
8279 if aScale > 100 then
8281 else if aScale < -100 then
8284 Rec.Scale := aScale;
8286 SetLength(Rec.Heights, Width * Height);
8290 SetLength(Rec.MatrixU, 2);
8291 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
8292 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
8294 SetLength(Rec.MatrixV, 2);
8295 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
8296 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
8300 SetLength(Rec.MatrixU, 6);
8301 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
8302 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
8303 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
8304 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
8305 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
8306 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
8308 SetLength(Rec.MatrixV, 6);
8309 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
8310 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
8311 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
8312 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
8313 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
8314 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
8318 SetLength(Rec.MatrixU, 6);
8319 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
8320 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
8321 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
8322 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
8323 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
8324 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
8326 SetLength(Rec.MatrixV, 6);
8327 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
8328 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
8329 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
8330 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
8331 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
8332 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
8336 SetLength(Rec.MatrixU, 20);
8337 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
8338 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
8339 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
8340 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
8341 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
8342 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
8343 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
8344 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
8345 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
8346 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
8347 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
8348 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
8349 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
8350 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
8351 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
8352 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
8353 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
8354 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
8355 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
8356 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
8358 SetLength(Rec.MatrixV, 20);
8359 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
8360 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
8361 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
8362 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
8363 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
8364 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
8365 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
8366 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
8367 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
8368 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
8369 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
8370 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
8371 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
8372 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
8373 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
8374 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
8375 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
8376 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
8377 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
8378 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
8383 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
8384 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
8386 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
8387 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
8389 SetLength(Rec.Heights, 0);
8393 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8394 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8395 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8396 procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean);
8398 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8401 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8402 procedure TglBitmapCubeMap.AfterConstruction;
8406 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8407 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8410 Target := GL_TEXTURE_CUBE_MAP;
8411 fGenMode := GL_REFLECTION_MAP;
8414 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8415 procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean);
8417 BuildWithGlu: Boolean;
8420 if (aTestTextureSize) then begin
8421 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8423 if (Height > TexSize) or (Width > TexSize) then
8424 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8426 if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8427 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8432 SetupParameters(BuildWithGlu);
8433 UploadData(aCubeTarget, BuildWithGlu);
8436 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8437 procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean);
8439 inherited Bind (aEnableTextureUnit);
8440 if aEnableTexCoordsGen then begin
8441 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8442 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8443 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8444 glEnable(GL_TEXTURE_GEN_S);
8445 glEnable(GL_TEXTURE_GEN_T);
8446 glEnable(GL_TEXTURE_GEN_R);
8450 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8451 procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean);
8453 inherited Unbind(aDisableTextureUnit);
8454 if aDisableTexCoordsGen then begin
8455 glDisable(GL_TEXTURE_GEN_S);
8456 glDisable(GL_TEXTURE_GEN_T);
8457 glDisable(GL_TEXTURE_GEN_R);
8461 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8462 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8463 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8465 TVec = Array[0..2] of Single;
8466 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8468 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8469 TglBitmapNormalMapRec = record
8471 Func: TglBitmapNormalMapGetVectorFunc;
8474 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8475 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8477 aVec[0] := aHalfSize;
8478 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8479 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8482 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8483 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8485 aVec[0] := - aHalfSize;
8486 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8487 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8490 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8491 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8493 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8494 aVec[1] := aHalfSize;
8495 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8498 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8499 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8501 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8502 aVec[1] := - aHalfSize;
8503 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8506 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8507 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8509 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8510 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8511 aVec[2] := aHalfSize;
8514 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8515 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8517 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8518 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8519 aVec[2] := - aHalfSize;
8522 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8523 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8529 with FuncRec do begin
8530 with PglBitmapNormalMapRec(Args)^ do begin
8531 Func(Vec, Position, HalfSize);
8534 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8535 if Len <> 0 then begin
8536 Vec[0] := Vec[0] * Len;
8537 Vec[1] := Vec[1] * Len;
8538 Vec[2] := Vec[2] * Len;
8541 // Scale Vector and AddVectro
8542 Vec[0] := Vec[0] * 0.5 + 0.5;
8543 Vec[1] := Vec[1] * 0.5 + 0.5;
8544 Vec[2] := Vec[2] * 0.5 + 0.5;
8549 Dest.Data.arr[i] := Round(Vec[i] * 255);
8553 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8554 procedure TglBitmapNormalMap.AfterConstruction;
8557 fGenMode := GL_NORMAL_MAP;
8560 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8561 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean);
8563 Rec: TglBitmapNormalMapRec;
8564 SizeRec: TglBitmapPixelPosition;
8566 Rec.HalfSize := aSize div 2;
8567 FreeDataAfterGenTexture := false;
8569 SizeRec.Fields := [ffX, ffY];
8574 Rec.Func := glBitmapNormalMapPosX;
8575 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8576 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize);
8579 Rec.Func := glBitmapNormalMapNegX;
8580 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8581 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize);
8584 Rec.Func := glBitmapNormalMapPosY;
8585 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8586 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize);
8589 Rec.Func := glBitmapNormalMapNegY;
8590 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8591 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize);
8594 Rec.Func := glBitmapNormalMapPosZ;
8595 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8596 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize);
8599 Rec.Func := glBitmapNormalMapNegZ;
8600 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8601 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize);
8606 glBitmapSetDefaultFormat (tfEmpty);
8607 glBitmapSetDefaultMipmap (mmMipmap);
8608 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8609 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8610 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8612 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8613 glBitmapSetDefaultDeleteTextureOnFree (true);
8615 TFormatDescriptor.Init;
8617 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8618 OpenGLInitialized := false;
8619 InitOpenGLCS := TCriticalSection.Create;
8623 TFormatDescriptor.Finalize;
8625 {$IFDEF GLB_NATIVE_OGL}
8626 if Assigned(GL_LibHandle) then
8627 glbFreeLibrary(GL_LibHandle);
8629 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8630 if Assigned(GLU_LibHandle) then
8631 glbFreeLibrary(GLU_LibHandle);
8632 FreeAndNil(InitOpenGLCS);