1 {***********************************************************
2 glBitmap by Steffen Xonna aka Lossy eX (2003-2008)
3 http://www.opengl24.de/index.php?cat=header&file=glbitmap
5 modified by Delphi OpenGL Community (http://delphigl.com/) (2013)
7 ------------------------------------------------------------
8 The contents of this file are used with permission, subject to
9 the Mozilla Public License Version 1.1 (the "License"); you may
10 not use this file except in compliance with the License. You may
11 obtain a copy of the License at
12 http://www.mozilla.org/MPL/MPL-1.1.html
13 ------------------------------------------------------------
15 ------------------------------------------------------------
18 - refactoring of the complete library
20 - The define GLB_DELPHI dosn't check versions anymore. If you say you are using delphi
21 then it's your problem if that isn't true. This prevents the unit for incompatibility
22 with newer versions of Delphi.
23 - Problems with D2009+ resolved (Thanks noeska and all i forgot)
24 - GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson)
26 - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson)
27 - Additional Datapointer for functioninterface now has the name CustomData
29 - AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson)
30 - If you load an texture from an file the property Filename will be set to the name of the file
31 - Three new properties to attach custom data to the Texture objects
32 - CustomName (free for use string)
33 - CustomNameW (free for use widestring)
34 - CustomDataPointer (free for use pointer to attach other objects or complex structures)
36 - RLE TGAs loaded much faster
38 - fixed some problem with reading RLE TGAs.
40 - function clone now only copys data if it's assigned and now it also copies the ID
41 - it seems that lazarus dont like comments in comments.
43 - It's possible to set the id of the texture
44 - define GLB_NO_NATIVE_GL deactivated by default
46 - Now supports the following libraries
50 - Linux compatibillity via free pascal compatibility (delphi sources optional)
51 - BMPs now loaded manuel
53 - Property DataPtr now has the name Data
54 - Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR
55 - Unused Depth removed
56 - Function FreeData to freeing image data added
58 - ImageID flag of TGAs was ignored. (Thanks Zwoetzen)
60 - Function SetBorderColor implemented (only used by opengl if wrap is set to GL_CLAMP_TO_BORDER)
61 - Function AddAlphaFromValue implemented to use an fixed Value as Alphachannel
62 - Function ReadOpenGLExtension is now only intern
64 - pngimage now disabled by default like all other versions.
66 - Setting up an anisotropic filter of 0 isnt allowed by nvidia (Thanks Ogridi)
68 - Fixed some Problem with Delphi 5
69 - Now uses the newest version of pngimage. Makes saving pngs much easier.
71 - Property IsCompressed and Size removed. Not really supported by Spec (Thanks Ogridi)
73 - Internal Format ifDepth8 added
74 - function GrabScreen now supports all uncompressed formats
76 - AddAlphaFromglBitmap implemented
78 - LoadFromResource and LoadFromResourceId now needs an Instance and an ResourceType (for ID)
80 - Width, Height and Depth internal changed to TglBitmapPixelPosition.
81 property Width, Height, Depth are still existing and new property Dimension are avail
83 - Added native OpenGL Support. Breaking the dglOpenGL "barrier".
85 - Added function GrabScreen to class TglBitmap2D
87 - Added support to Save images
88 - Added function Clone to Clone Instance
90 - Functions now works with Cardinals for each channel. Up to 32 Bits per channel.
92 - Several speed optimizations
94 - Internal structure change. Loading of TGA, PNG and DDS improved.
95 Data, format and size will now set directly with SetDataPtr.
96 - AddFunc now works with all Types of Images and Formats
97 - Some Funtions moved to Baseclass TglBitmap
99 - Added Support to decompress DXT3 and DXT5 compressed Images.
100 - Added Mapping to convert data from one format into an other.
102 - Added method ConvertTo in Class TglBitmap2D. Method allows to convert every
103 supported Input format (supported by GetPixel) into any uncompresed Format
104 - Added Support to decompress DXT1 compressed Images.
105 - SwapColors replaced by ConvertTo
107 - Added Support for compressed DDSs
108 - Added new internal formats (DXT1, DXT3, DXT5)
110 - Parameter Components renamed to InternalFormat
112 - Some AllocMem replaced with GetMem (little speed change)
113 - better exception handling. Better protection from memory leaks.
115 - Added support for Direct Draw Surfaces (.DDS) (uncompressed images only)
116 - Added new internal formats (RGB8, RGBA8, RGBA4, RGB5A1, RGB10A2, R5G6B5)
118 - Added support for Grayscale textures
119 - Added internal formats (Alpha, Luminance, LuminanceAlpha, BGR8, BGRA8)
121 - Added support for GL_VERSION_2_0
122 - Added support for GL_EXT_texture_filter_anisotropic
124 - Function FillWithColor fills the Image with one Color
125 - Function LoadNormalMap added
127 - ToNormalMap allows to Create an NormalMap from the Alphachannel
128 - ToNormalMap now supports Sobel (nmSobel) function.
130 - support for RLE Compressed RGB TGAs added
132 - Class TglBitmapNormalMap added to support Normalmap generation
133 - Added function ToNormalMap in class TglBitmap2D to genereate normal maps from textures.
134 3 Filters are supported. (4 Samples, 3x3 and 5x5)
136 - Method LoadCubeMapClass removed
137 - LoadCubeMap returnvalue is now the Texture paramter. Such as LoadTextures
138 - virtual abstract method GenTexture in class TglBitmap now is protected
140 - now support DescriptionFlag in LoadTga. Allows vertical flipped images to be loaded as normal
142 - little enhancement for IsPowerOfTwo
143 - TglBitmap1D.GenTexture now tests NPOT Textures
145 - some little name changes. All properties or function with Texture in name are
146 now without texture in name. We have allways texture so we dosn't name it.
148 - GenTexture now tests if texture is NPOT and NPOT-Texture are supported or
149 TextureTarget is GL_TEXTURE_RECTANGLE. Else it raised an exception.
151 - added support for GL_ARB_texture_rectangle, GL_EXT_texture_rectangle and GL_NV_texture_rectangle
153 - Function Unbind added
154 - call of SetFilter or SetTextureWrap if TextureID exists results in setting properties to opengl texture.
156 - class TglBitmapCubeMap added (allows to Create Cubemaps)
158 - Added Support for PNG Images. (http://pngdelphi.sourceforge.net/)
159 To Enable png's use the define pngimage
161 - New Functioninterface added
162 - Function GetPixel added
164 - Property BuildMipMaps renamed to MipMap
166 - property Name removed.
167 - BuildMipMaps is now a set of 3 values. None, GluBuildMipmaps and SGIS_generate_mipmap
169 - property name added. Only used in glForms!
171 - property FreeDataAfterGenTexture is now available as default (default = true)
172 - BuildMipmaps now implemented in TglBitmap1D (i've forgotten it)
173 - function MoveMemory replaced with function Move (little speed change)
174 - several calculations stored in variables (little speed change)
176 - property BuildMipsMaps added (default = true)
177 if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps
178 - property FreeDataAfterGenTexture added (default = true)
179 if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated.
180 - parameter DisableOtherTextureUnits of Bind removed
181 - parameter FreeDataAfterGeneration of GenTextures removed
183 - TglBitmap dosn't delete data if class was destroyed (fixed)
185 - Bind now enables TextureUnits (by params)
186 - GenTextures can leave data (by param)
187 - LoadTextures now optimal
189 - Performance optimization in AddFunc
190 - procedure Bind moved to subclasses
191 - Added new Class TglBitmap1D to support real OpenGL 1D Textures
193 - Texturefilter and texturewrap now also as defaults
194 Minfilter = GL_LINEAR_MIPMAP_LINEAR
195 Magfilter = GL_LINEAR
196 Wrap(str) = GL_CLAMP_TO_EDGE
197 - Added new format tfCompressed to create a compressed texture.
198 - propertys IsCompressed, TextureSize and IsResident added
199 IsCompressed and TextureSize only contains data from level 0
201 - Added function AddFunc to add PerPixelEffects to Image
202 - LoadFromFunc now based on AddFunc
203 - Invert now based on AddFunc
204 - SwapColors now based on AddFunc
206 - Added function FlipHorz
208 - Added function LaodFromFunc to create images with function
209 - Added function FlipVert
210 - Added internal format RGB(A) if GL_EXT_bgra or OpenGL 1.2 isn't supported
212 - Added Alphafunctions to calculate alpha per function
213 - Added Alpha from ColorKey using alphafunctions
215 - First full functionally Version of glBitmap
216 - Support for 24Bit and 32Bit TGA Pictures added
218 - begin of programming
219 ***********************************************************}
222 // Please uncomment the defines below to configure the glBitmap to your preferences.
223 // If you have configured the unit you can uncomment the warning above.
224 {$MESSAGE error 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
227 // Preferences ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
229 // activate to enable build-in OpenGL support with statically linked methods
230 // use dglOpenGL.pas if not enabled
231 {.$DEFINE GLB_NATIVE_OGL_STATIC}
233 // activate to enable build-in OpenGL support with dynamically linked methods
234 // use dglOpenGL.pas if not enabled
235 {.$DEFINE GLB_NATIVE_OGL_DYNAMIC}
238 // activate to enable the support for SDL_surfaces
241 // activate to enable the support for Delphi (including support for Delphi's (not Lazarus') TBitmap)
242 {.$DEFINE GLB_DELPHI}
244 // activate to enable the support for TLazIntfImage from Lazarus
245 {.$DEFINE GLB_LAZARUS}
249 // activate to enable the support of SDL_image to load files. (READ ONLY)
250 // If you enable SDL_image all other libraries will be ignored!
251 {.$DEFINE GLB_SDL_IMAGE}
255 // activate to enable Lazarus TPortableNetworkGraphic support
256 // if you enable this pngImage and libPNG will be ignored
257 {.$DEFINE GLB_LAZ_PNG}
259 // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/
260 // if you enable pngimage the libPNG will be ignored
261 {.$DEFINE GLB_PNGIMAGE}
263 // activate to use the libPNG -> http://www.libpng.org/
264 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libpng
265 {.$DEFINE GLB_LIB_PNG}
269 // activate to enable Lazarus TJPEGImage support
270 // if you enable this delphi jpegs and libJPEG will be ignored
271 {.$DEFINE GLB_LAZ_JPEG}
273 // if you enable delphi jpegs the libJPEG will be ignored
274 {.$DEFINE GLB_DELPHI_JPEG}
276 // activate to use the libJPEG -> http://www.ijg.org/
277 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libjpeg
278 {.$DEFINE GLB_LIB_JPEG}
281 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
282 // PRIVATE: do not change anything! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299 {$IF DEFINED(WIN32) or DEFINED(WIN64) or DEFINED(WINDOWS)}
301 {$ELSEIF DEFINED(LINUX)}
305 // native OpenGL Support
306 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) OR DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
307 {$DEFINE GLB_NATIVE_OGL}
310 // checking define combinations
312 {$IFDEF GLB_SDL_IMAGE}
314 {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
319 {$MESSAGE warn 'The Lazarus TPortableNetworkGraphics will be ignored because you are using SDL_image.'}
323 {$IFDEF GLB_PNGIMAGE}
324 {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
325 {$undef GLB_PNGIMAGE}
328 {$IFDEF GLB_LAZ_JPEG}
329 {$MESSAGE warn 'The Lazarus TJPEGImage will be ignored because you are using SDL_image.'}
330 {$undef GLB_LAZ_JPEG}
333 {$IFDEF GLB_DELPHI_JPEG}
334 {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
335 {$undef GLB_DELPHI_JPEG}
339 {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
343 {$IFDEF GLB_LIB_JPEG}
344 {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
345 {$undef GLB_LIB_JPEG}
348 {$DEFINE GLB_SUPPORT_PNG_READ}
349 {$DEFINE GLB_SUPPORT_JPEG_READ}
352 // Lazarus TPortableNetworkGraphic
354 {$IFNDEF GLB_LAZARUS}
355 {$MESSAGE warn 'Lazarus TPortableNetworkGraphic won''t work without Lazarus. Lazarus will be activated.'}
356 {$DEFINE GLB_LAZARUS}
359 {$IFDEF GLB_PNGIMAGE}
360 {$MESSAGE warn 'The pngimage will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
361 {$undef GLB_PNGIMAGE}
365 {$MESSAGE warn 'The library libPNG will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
369 {$DEFINE GLB_SUPPORT_PNG_READ}
370 {$DEFINE GLB_SUPPORT_PNG_WRITE}
374 {$IFDEF GLB_PNGIMAGE}
376 {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'}
380 {$DEFINE GLB_SUPPORT_PNG_READ}
381 {$DEFINE GLB_SUPPORT_PNG_WRITE}
386 {$DEFINE GLB_SUPPORT_PNG_READ}
387 {$DEFINE GLB_SUPPORT_PNG_WRITE}
390 // Lazarus TJPEGImage
391 {$IFDEF GLB_LAZ_JPEG}
392 {$IFNDEF GLB_LAZARUS}
393 {$MESSAGE warn 'Lazarus TJPEGImage won''t work without Lazarus. Lazarus will be activated.'}
394 {$DEFINE GLB_LAZARUS}
397 {$IFDEF GLB_DELPHI_JPEG}
398 {$MESSAGE warn 'The Delphi JPEGImage will be ignored if you are using the Lazarus TJPEGImage.'}
399 {$undef GLB_DELPHI_JPEG}
402 {$IFDEF GLB_LIB_JPEG}
403 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the Lazarus TJPEGImage.'}
404 {$undef GLB_LIB_JPEG}
407 {$DEFINE GLB_SUPPORT_JPEG_READ}
408 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
412 {$IFDEF GLB_DELPHI_JPEG}
413 {$IFDEF GLB_LIB_JPEG}
414 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
415 {$undef GLB_LIB_JPEG}
418 {$DEFINE GLB_SUPPORT_JPEG_READ}
419 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
423 {$IFDEF GLB_LIB_JPEG}
424 {$DEFINE GLB_SUPPORT_JPEG_READ}
425 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
429 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) AND DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
430 {$MESSAGE warn 'GLB_NATIVE_OGL_STATIC will be ignored because you enabled GLB_NATIVE_OGL_DYNAMIC'}
444 {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF}
445 {$IF DEFINED(GLB_WIN) AND
446 (DEFINED(GLB_NATIVE_OGL) OR
447 DEFINED(GLB_DELPHI))} windows, {$IFEND}
449 {$IFDEF GLB_SDL} SDL, {$ENDIF}
450 {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, Graphics, {$ENDIF}
451 {$IFDEF GLB_DELPHI} Dialogs, Graphics, Types, {$ENDIF}
453 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
454 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
455 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
456 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
457 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
461 {$IFDEF GLB_NATIVE_OGL}
470 GL_EXTENSIONS = $1F03;
472 GL_TEXTURE_1D = $0DE0;
473 GL_TEXTURE_2D = $0DE1;
474 GL_TEXTURE_RECTANGLE = $84F5;
476 GL_NORMAL_MAP = $8511;
477 GL_TEXTURE_CUBE_MAP = $8513;
478 GL_REFLECTION_MAP = $8512;
479 GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515;
480 GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516;
481 GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517;
482 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518;
483 GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519;
484 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A;
486 GL_TEXTURE_WIDTH = $1000;
487 GL_TEXTURE_HEIGHT = $1001;
488 GL_TEXTURE_INTERNAL_FORMAT = $1003;
489 GL_TEXTURE_SWIZZLE_RGBA = $8E46;
496 GL_TEXTURE_GEN_S = $0C60;
497 GL_TEXTURE_GEN_T = $0C61;
498 GL_TEXTURE_GEN_R = $0C62;
499 GL_TEXTURE_GEN_Q = $0C63;
511 GL_LUMINANCE = $1909;
512 GL_LUMINANCE4 = $803F;
513 GL_LUMINANCE8 = $8040;
514 GL_LUMINANCE12 = $8041;
515 GL_LUMINANCE16 = $8042;
517 GL_LUMINANCE_ALPHA = $190A;
518 GL_LUMINANCE4_ALPHA4 = $8043;
519 GL_LUMINANCE6_ALPHA2 = $8044;
520 GL_LUMINANCE8_ALPHA8 = $8045;
521 GL_LUMINANCE12_ALPHA4 = $8046;
522 GL_LUMINANCE12_ALPHA12 = $8047;
523 GL_LUMINANCE16_ALPHA16 = $8048;
546 GL_DEPTH_COMPONENT = $1902;
547 GL_DEPTH_COMPONENT16 = $81A5;
548 GL_DEPTH_COMPONENT24 = $81A6;
549 GL_DEPTH_COMPONENT32 = $81A7;
551 GL_COMPRESSED_RGB = $84ED;
552 GL_COMPRESSED_RGBA = $84EE;
553 GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
554 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
555 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
556 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
558 GL_UNSIGNED_BYTE = $1401;
559 GL_UNSIGNED_BYTE_3_3_2 = $8032;
560 GL_UNSIGNED_BYTE_2_3_3_REV = $8362;
562 GL_UNSIGNED_SHORT = $1403;
563 GL_UNSIGNED_SHORT_5_6_5 = $8363;
564 GL_UNSIGNED_SHORT_4_4_4_4 = $8033;
565 GL_UNSIGNED_SHORT_5_5_5_1 = $8034;
566 GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
567 GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
568 GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
570 GL_UNSIGNED_INT = $1405;
571 GL_UNSIGNED_INT_8_8_8_8 = $8035;
572 GL_UNSIGNED_INT_10_10_10_2 = $8036;
573 GL_UNSIGNED_INT_8_8_8_8_REV = $8367;
574 GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
577 GL_TEXTURE_MAG_FILTER = $2800;
578 GL_TEXTURE_MIN_FILTER = $2801;
580 GL_NEAREST_MIPMAP_NEAREST = $2700;
581 GL_NEAREST_MIPMAP_LINEAR = $2702;
583 GL_LINEAR_MIPMAP_NEAREST = $2701;
584 GL_LINEAR_MIPMAP_LINEAR = $2703;
587 GL_TEXTURE_WRAP_S = $2802;
588 GL_TEXTURE_WRAP_T = $2803;
589 GL_TEXTURE_WRAP_R = $8072;
592 GL_CLAMP_TO_EDGE = $812F;
593 GL_CLAMP_TO_BORDER = $812D;
594 GL_MIRRORED_REPEAT = $8370;
597 GL_GENERATE_MIPMAP = $8191;
598 GL_TEXTURE_BORDER_COLOR = $1004;
599 GL_MAX_TEXTURE_SIZE = $0D33;
600 GL_PACK_ALIGNMENT = $0D05;
601 GL_UNPACK_ALIGNMENT = $0CF5;
603 GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
604 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
605 GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C;
606 GL_TEXTURE_GEN_MODE = $2500;
608 {$IF DEFINED(GLB_WIN)}
609 libglu = 'glu32.dll';
610 libopengl = 'opengl32.dll';
611 {$ELSEIF DEFINED(GLB_LINUX)}
612 libglu = 'libGLU.so.1';
613 libopengl = 'libGL.so.1';
617 GLboolean = BYTEBOOL;
625 PGLboolean = ^GLboolean;
630 TglCompressedTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
631 TglCompressedTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
632 TglGetCompressedTexImage = procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
634 {$IF DEFINED(GLB_WIN)}
635 TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall;
636 {$ELSEIF DEFINED(GLB_LINUX)}
637 TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl;
638 TglXGetProcAddressARB = function(const name: PAnsiChar): pointer; cdecl;
641 {$IF DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
642 TglEnable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
643 TglDisable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
645 TglGetString = function(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
646 TglGetIntegerv = procedure(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
648 TglTexParameteri = procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
649 TglTexParameteriv = procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
650 TglTexParameterfv = procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
651 TglGetTexParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
652 TglGetTexParameterfv = procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
653 TglGetTexLevelParameteriv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
654 TglGetTexLevelParameterfv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
656 TglTexGeni = procedure(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
657 TglGenTextures = procedure(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
658 TglBindTexture = procedure(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
659 TglDeleteTextures = procedure(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
661 TglAreTexturesResident = function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
662 TglReadPixels = procedure(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
663 TglPixelStorei = procedure(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
665 TglTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
666 TglTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
667 TglGetTexImage = procedure(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
669 TgluBuild1DMipmaps = function(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
670 TgluBuild2DMipmaps = function(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
672 {$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)}
673 procedure glEnable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
674 procedure glDisable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
676 function glGetString(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
677 procedure glGetIntegerv(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
679 procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
680 procedure glTexParameteriv(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
681 procedure glTexParameterfv(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
682 procedure glGetTexParameteriv(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
683 procedure glGetTexParameterfv(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
684 procedure glGetTexLevelParameteriv(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
685 procedure glGetTexLevelParameterfv(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
687 procedure glTexGeni(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
688 procedure glGenTextures(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
689 procedure glBindTexture(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
690 procedure glDeleteTextures(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
692 function glAreTexturesResident(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
693 procedure glReadPixels(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
694 procedure glPixelStorei(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
696 procedure glTexImage1D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
697 procedure glTexImage2D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
698 procedure glGetTexImage(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
700 function gluBuild1DMipmaps(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
701 function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
711 GL_SGIS_generate_mipmap,
713 GL_ARB_texture_border_clamp,
714 GL_ARB_texture_mirrored_repeat,
715 GL_ARB_texture_rectangle,
716 GL_ARB_texture_non_power_of_two,
717 GL_ARB_texture_swizzle,
718 GL_ARB_texture_cube_map,
720 GL_IBM_texture_mirrored_repeat,
722 GL_NV_texture_rectangle,
724 GL_EXT_texture_edge_clamp,
725 GL_EXT_texture_rectangle,
726 GL_EXT_texture_swizzle,
727 GL_EXT_texture_cube_map,
728 GL_EXT_texture_filter_anisotropic: Boolean;
730 glCompressedTexImage1D: TglCompressedTexImage1D;
731 glCompressedTexImage2D: TglCompressedTexImage2D;
732 glGetCompressedTexImage: TglGetCompressedTexImage;
734 {$IF DEFINED(GLB_WIN)}
735 wglGetProcAddress: TwglGetProcAddress;
736 {$ELSEIF DEFINED(GLB_LINUX)}
737 glXGetProcAddress: TglXGetProcAddress;
738 glXGetProcAddressARB: TglXGetProcAddress;
741 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
743 glDisable: TglDisable;
745 glGetString: TglGetString;
746 glGetIntegerv: TglGetIntegerv;
748 glTexParameteri: TglTexParameteri;
749 glTexParameteriv: TglTexParameteriv;
750 glTexParameterfv: TglTexParameterfv;
751 glGetTexParameteriv: TglGetTexParameteriv;
752 glGetTexParameterfv: TglGetTexParameterfv;
753 glGetTexLevelParameteriv: TglGetTexLevelParameteriv;
754 glGetTexLevelParameterfv: TglGetTexLevelParameterfv;
756 glTexGeni: TglTexGeni;
757 glGenTextures: TglGenTextures;
758 glBindTexture: TglBindTexture;
759 glDeleteTextures: TglDeleteTextures;
761 glAreTexturesResident: TglAreTexturesResident;
762 glReadPixels: TglReadPixels;
763 glPixelStorei: TglPixelStorei;
765 glTexImage1D: TglTexImage1D;
766 glTexImage2D: TglTexImage2D;
767 glGetTexImage: TglGetTexImage;
769 gluBuild1DMipmaps: TgluBuild1DMipmaps;
770 gluBuild2DMipmaps: TgluBuild2DMipmaps;
775 ////////////////////////////////////////////////////////////////////////////////////////////////////
777 tfEmpty = 0, //must be smallest value!
793 tfLuminance12Alpha12,
794 tfLuminance16Alpha16,
838 TglBitmapFileType = (
839 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
840 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
844 TglBitmapFileTypes = set of TglBitmapFileType;
851 TglBitmapNormalMapFunc = (
857 ////////////////////////////////////////////////////////////////////////////////////////////////////
858 EglBitmap = class(Exception);
859 EglBitmapNotSupported = class(Exception);
860 EglBitmapSizeToLarge = class(EglBitmap);
861 EglBitmapNonPowerOfTwo = class(EglBitmap);
862 EglBitmapUnsupportedFormat = class(EglBitmap)
864 constructor Create(const aFormat: TglBitmapFormat); overload;
865 constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload;
868 ////////////////////////////////////////////////////////////////////////////////////////////////////
869 TglBitmapColorRec = packed record
871 0: (r, g, b, a: Cardinal);
872 1: (arr: array[0..3] of Cardinal);
875 TglBitmapPixelData = packed record
876 Data, Range: TglBitmapColorRec;
877 Format: TglBitmapFormat;
879 PglBitmapPixelData = ^TglBitmapPixelData;
881 ////////////////////////////////////////////////////////////////////////////////////////////////////
882 TglBitmapPixelPositionFields = set of (ffX, ffY);
883 TglBitmapPixelPosition = record
884 Fields : TglBitmapPixelPositionFields;
889 TglBitmapFormatDescriptor = class(TObject)
891 function GetIsCompressed: Boolean; virtual; abstract;
892 function GetHasRed: Boolean; virtual; abstract;
893 function GetHasGreen: Boolean; virtual; abstract;
894 function GetHasBlue: Boolean; virtual; abstract;
895 function GetHasAlpha: Boolean; virtual; abstract;
897 function GetglDataFormat: GLenum; virtual; abstract;
898 function GetglFormat: GLenum; virtual; abstract;
899 function GetglInternalFormat: GLenum; virtual; abstract;
901 property IsCompressed: Boolean read GetIsCompressed;
902 property HasRed: Boolean read GetHasRed;
903 property HasGreen: Boolean read GetHasGreen;
904 property HasBlue: Boolean read GetHasBlue;
905 property HasAlpha: Boolean read GetHasAlpha;
907 property glFormat: GLenum read GetglFormat;
908 property glInternalFormat: GLenum read GetglInternalFormat;
909 property glDataFormat: GLenum read GetglDataFormat;
911 class function GetByFormat(const aInternalFormat: GLenum): TglBitmapFormatDescriptor;
914 ////////////////////////////////////////////////////////////////////////////////////////////////////
916 TglBitmapFunctionRec = record
918 Size: TglBitmapPixelPosition;
919 Position: TglBitmapPixelPosition;
920 Source: TglBitmapPixelData;
921 Dest: TglBitmapPixelData;
924 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
926 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
929 function GetFormatDesc: TglBitmapFormatDescriptor;
933 fAnisotropic: Integer;
934 fDeleteTextureOnFree: Boolean;
935 fFreeDataOnDestroy: Boolean;
936 fFreeDataAfterGenTexture: Boolean;
938 fIsResident: GLboolean;
939 fBorderColor: array[0..3] of Single;
941 fDimension: TglBitmapPixelPosition;
942 fMipMap: TglBitmapMipMap;
943 fFormat: TglBitmapFormat;
959 fSwizzle: array[0..3] of GLenum;
964 fCustomNameW: WideString;
965 fCustomData: Pointer;
968 function GetWidth: Integer; virtual;
969 function GetHeight: Integer; virtual;
971 function GetFileWidth: Integer; virtual;
972 function GetFileHeight: Integer; virtual;
975 procedure SetCustomData(const aValue: Pointer);
976 procedure SetCustomName(const aValue: String);
977 procedure SetCustomNameW(const aValue: WideString);
978 procedure SetFreeDataOnDestroy(const aValue: Boolean);
979 procedure SetDeleteTextureOnFree(const aValue: Boolean);
980 procedure SetFormat(const aValue: TglBitmapFormat);
981 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
982 procedure SetID(const aValue: Cardinal);
983 procedure SetMipMap(const aValue: TglBitmapMipMap);
984 procedure SetTarget(const aValue: Cardinal);
985 procedure SetAnisotropic(const aValue: Integer);
988 procedure SetupParameters(out aBuildWithGlu: Boolean);
989 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
990 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; //be careful, aData could be freed by this method
991 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
993 function FlipHorz: Boolean; virtual;
994 function FlipVert: Boolean; virtual;
996 property Width: Integer read GetWidth;
997 property Height: Integer read GetHeight;
999 property FileWidth: Integer read GetFileWidth;
1000 property FileHeight: Integer read GetFileHeight;
1003 property ID: Cardinal read fID write SetID;
1004 property Target: Cardinal read fTarget write SetTarget;
1005 property Format: TglBitmapFormat read fFormat write SetFormat;
1006 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
1007 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
1009 property FormatDesc: TglBitmapFormatDescriptor read GetFormatDesc;
1011 property Filename: String read fFilename;
1012 property CustomName: String read fCustomName write SetCustomName;
1013 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
1014 property CustomData: Pointer read fCustomData write SetCustomData;
1016 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
1017 property FreeDataOnDestroy: Boolean read fFreeDataOnDestroy write SetFreeDataOnDestroy;
1018 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
1020 property Dimension: TglBitmapPixelPosition read fDimension;
1021 property Data: PByte read fData;
1022 property IsResident: GLboolean read fIsResident;
1024 procedure AfterConstruction; override;
1025 procedure BeforeDestruction; override;
1027 procedure PrepareResType(var aResource: String; var aResType: PChar);
1030 procedure LoadFromFile(const aFilename: String);
1031 procedure LoadFromStream(const aStream: TStream); virtual;
1032 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
1033 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil);
1034 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil);
1035 procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
1038 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
1039 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
1042 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
1043 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
1044 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
1048 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
1049 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
1050 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
1051 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
1052 const aArgs: Pointer = nil): Boolean;
1056 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
1057 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
1058 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
1059 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
1060 const aArgs: Pointer = nil): Boolean;
1063 {$IFDEF GLB_LAZARUS}
1064 function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1065 function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
1066 function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
1067 function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil;
1068 const aArgs: Pointer = nil): Boolean;
1071 function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil;
1072 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1073 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
1074 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1076 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
1077 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1078 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1079 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
1081 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
1082 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
1083 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
1085 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
1086 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
1087 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
1089 function RemoveAlpha: Boolean; virtual;
1092 function Clone: TglBitmap;
1093 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
1094 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
1095 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
1099 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
1100 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
1101 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
1104 procedure SetFilter(const aMin, aMag: GLenum);
1106 const S: GLenum = GL_CLAMP_TO_EDGE;
1107 const T: GLenum = GL_CLAMP_TO_EDGE;
1108 const R: GLenum = GL_CLAMP_TO_EDGE);
1109 procedure SetSwizzle(const r, g, b, a: GLenum);
1111 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
1112 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
1115 constructor Create; overload;
1116 constructor Create(const aFileName: String); overload;
1117 constructor Create(const aStream: TStream); overload;
1118 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte = nil); overload;
1119 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
1120 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
1121 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
1123 {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1124 {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF}
1126 {$IFDEF GLB_SUPPORT_JPEG_READ} function LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF}
1127 {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF}
1129 function LoadBMP(const aStream: TStream): Boolean; virtual;
1130 procedure SaveBMP(const aStream: TStream); virtual;
1132 function LoadTGA(const aStream: TStream): Boolean; virtual;
1133 procedure SaveTGA(const aStream: TStream); virtual;
1135 function LoadDDS(const aStream: TStream): Boolean; virtual;
1136 procedure SaveDDS(const aStream: TStream); virtual;
1139 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1140 TglBitmap1D = class(TglBitmap)
1142 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1143 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1144 procedure UploadData(const aBuildWithGlu: Boolean);
1147 procedure AfterConstruction; override;
1148 function FlipHorz: Boolean; override;
1149 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1152 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1153 TglBitmap2D = class(TglBitmap)
1155 fLines: array of PByte;
1156 function GetScanline(const aIndex: Integer): Pointer;
1157 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1158 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1159 procedure UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
1163 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
1165 procedure AfterConstruction; override;
1167 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
1168 procedure GetDataFromTexture;
1169 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1171 function FlipHorz: Boolean; override;
1172 function FlipVert: Boolean; override;
1174 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
1175 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1178 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1179 TglBitmapCubeMap = class(TglBitmap2D)
1182 procedure GenTexture(const aTestTextureSize: Boolean = true); reintroduce;
1184 procedure AfterConstruction; override;
1185 procedure GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean = true);
1186 procedure Bind(const aEnableTexCoordsGen: Boolean = true; const aEnableTextureUnit: Boolean = true); reintroduce; virtual;
1187 procedure Unbind(const aDisableTexCoordsGen: Boolean = true; const aDisableTextureUnit: Boolean = true); reintroduce; virtual;
1190 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1191 TglBitmapNormalMap = class(TglBitmapCubeMap)
1193 procedure AfterConstruction; override;
1194 procedure GenerateNormalMap(const aSize: Integer = 32; const aTestTextureSize: Boolean = true);
1197 TglcBitmapFormat = TglBitmapFormat;
1198 TglcBitmap1D = TglBitmap1D;
1199 TglcBitmap2D = TglBitmap2D;
1200 TglcBitmapCubeMap = TglBitmapCubeMap;
1201 TglcBitmapNormalMap = TglBitmapNormalMap;
1204 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1206 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1207 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1208 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1209 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1210 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1211 procedure glBitmapSetDefaultWrap(
1212 const S: Cardinal = GL_CLAMP_TO_EDGE;
1213 const T: Cardinal = GL_CLAMP_TO_EDGE;
1214 const R: Cardinal = GL_CLAMP_TO_EDGE);
1216 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1217 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1218 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1219 function glBitmapGetDefaultFormat: TglBitmapFormat;
1220 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1221 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1223 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1224 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1225 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1228 glBitmapDefaultDeleteTextureOnFree: Boolean;
1229 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1230 glBitmapDefaultFormat: TglBitmapFormat;
1231 glBitmapDefaultMipmap: TglBitmapMipMap;
1232 glBitmapDefaultFilterMin: Cardinal;
1233 glBitmapDefaultFilterMag: Cardinal;
1234 glBitmapDefaultWrapS: Cardinal;
1235 glBitmapDefaultWrapT: Cardinal;
1236 glBitmapDefaultWrapR: Cardinal;
1237 glDefaultSwizzle: array[0..3] of GLenum;
1240 function CreateGrayPalette: HPALETTE;
1246 Math, syncobjs, typinfo
1247 {$IF DEFINED(GLB_SUPPORT_JPEG_READ) AND DEFINED(GLB_LAZ_JPEG)}, FPReadJPEG{$IFEND};
1251 QWord = System.UInt64;
1258 ////////////////////////////////////////////////////////////////////////////////////////////////////
1259 TShiftRec = packed record
1261 0: (r, g, b, a: Byte);
1262 1: (arr: array[0..3] of Byte);
1265 TFormatDescriptor = class(TglBitmapFormatDescriptor)
1267 function GetRedMask: QWord;
1268 function GetGreenMask: QWord;
1269 function GetBlueMask: QWord;
1270 function GetAlphaMask: QWord;
1272 fFormat: TglBitmapFormat;
1273 fWithAlpha: TglBitmapFormat;
1274 fWithoutAlpha: TglBitmapFormat;
1275 fRGBInverted: TglBitmapFormat;
1276 fUncompressed: TglBitmapFormat;
1278 fIsCompressed: Boolean;
1280 fRange: TglBitmapColorRec;
1284 fglInternalFormat: GLenum;
1285 fglDataFormat: GLenum;
1287 function GetIsCompressed: Boolean; override;
1288 function GetHasRed: Boolean; override;
1289 function GetHasGreen: Boolean; override;
1290 function GetHasBlue: Boolean; override;
1291 function GetHasAlpha: Boolean; override;
1293 function GetglFormat: GLenum; override;
1294 function GetglInternalFormat: GLenum; override;
1295 function GetglDataFormat: GLenum; override;
1297 function GetComponents: Integer; virtual;
1299 property Format: TglBitmapFormat read fFormat;
1300 property WithAlpha: TglBitmapFormat read fWithAlpha;
1301 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1302 property RGBInverted: TglBitmapFormat read fRGBInverted;
1303 property Components: Integer read GetComponents;
1304 property PixelSize: Single read fPixelSize;
1306 property Range: TglBitmapColorRec read fRange;
1307 property Shift: TShiftRec read fShift;
1309 property RedMask: QWord read GetRedMask;
1310 property GreenMask: QWord read GetGreenMask;
1311 property BlueMask: QWord read GetBlueMask;
1312 property AlphaMask: QWord read GetAlphaMask;
1314 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1315 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1317 function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual;
1318 function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
1320 function CreateMappingData: Pointer; virtual;
1321 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1323 function IsEmpty: Boolean; virtual;
1324 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual;
1326 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1328 constructor Create; virtual;
1330 class procedure Init;
1331 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1332 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1333 class procedure Clear;
1334 class procedure Finalize;
1336 TFormatDescriptorClass = class of TFormatDescriptor;
1338 TfdEmpty = class(TFormatDescriptor);
1340 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1341 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1342 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1343 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1344 constructor Create; override;
1347 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1348 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1349 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1350 constructor Create; override;
1353 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1354 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1355 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1356 constructor Create; override;
1359 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1360 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1361 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1362 constructor Create; override;
1365 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1366 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1367 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1368 constructor Create; override;
1371 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1372 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1373 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1374 constructor Create; override;
1377 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1378 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1379 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1380 constructor Create; override;
1383 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1384 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1385 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1386 constructor Create; override;
1389 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1390 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1391 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1392 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1393 constructor Create; override;
1396 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1397 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1398 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1399 constructor Create; override;
1402 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1403 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1404 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1405 constructor Create; override;
1408 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1409 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1410 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1411 constructor Create; override;
1414 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1415 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1416 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1417 constructor Create; override;
1420 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1421 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1422 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1423 constructor Create; override;
1426 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1427 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1428 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1429 constructor Create; override;
1432 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1433 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1434 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1435 constructor Create; override;
1438 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1439 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1440 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1441 constructor Create; override;
1444 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1445 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1446 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1447 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1448 constructor Create; override;
1451 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1452 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1453 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1454 constructor Create; override;
1457 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1458 TfdAlpha4 = class(TfdAlpha_UB1)
1459 constructor Create; override;
1462 TfdAlpha8 = class(TfdAlpha_UB1)
1463 constructor Create; override;
1466 TfdAlpha12 = class(TfdAlpha_US1)
1467 constructor Create; override;
1470 TfdAlpha16 = class(TfdAlpha_US1)
1471 constructor Create; override;
1474 TfdLuminance4 = class(TfdLuminance_UB1)
1475 constructor Create; override;
1478 TfdLuminance8 = class(TfdLuminance_UB1)
1479 constructor Create; override;
1482 TfdLuminance12 = class(TfdLuminance_US1)
1483 constructor Create; override;
1486 TfdLuminance16 = class(TfdLuminance_US1)
1487 constructor Create; override;
1490 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1491 constructor Create; override;
1494 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1495 constructor Create; override;
1498 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1499 constructor Create; override;
1502 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1503 constructor Create; override;
1506 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1507 constructor Create; override;
1510 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1511 constructor Create; override;
1514 TfdR3G3B2 = class(TfdUniversal_UB1)
1515 constructor Create; override;
1518 TfdRGB4 = class(TfdUniversal_US1)
1519 constructor Create; override;
1522 TfdR5G6B5 = class(TfdUniversal_US1)
1523 constructor Create; override;
1526 TfdRGB5 = class(TfdUniversal_US1)
1527 constructor Create; override;
1530 TfdRGB8 = class(TfdRGB_UB3)
1531 constructor Create; override;
1534 TfdRGB10 = class(TfdUniversal_UI1)
1535 constructor Create; override;
1538 TfdRGB12 = class(TfdRGB_US3)
1539 constructor Create; override;
1542 TfdRGB16 = class(TfdRGB_US3)
1543 constructor Create; override;
1546 TfdRGBA2 = class(TfdRGBA_UB4)
1547 constructor Create; override;
1550 TfdRGBA4 = class(TfdUniversal_US1)
1551 constructor Create; override;
1554 TfdRGB5A1 = class(TfdUniversal_US1)
1555 constructor Create; override;
1558 TfdRGBA8 = class(TfdRGBA_UB4)
1559 constructor Create; override;
1562 TfdRGB10A2 = class(TfdUniversal_UI1)
1563 constructor Create; override;
1566 TfdRGBA12 = class(TfdRGBA_US4)
1567 constructor Create; override;
1570 TfdRGBA16 = class(TfdRGBA_US4)
1571 constructor Create; override;
1574 TfdBGR4 = class(TfdUniversal_US1)
1575 constructor Create; override;
1578 TfdB5G6R5 = class(TfdUniversal_US1)
1579 constructor Create; override;
1582 TfdBGR5 = class(TfdUniversal_US1)
1583 constructor Create; override;
1586 TfdBGR8 = class(TfdBGR_UB3)
1587 constructor Create; override;
1590 TfdBGR10 = class(TfdUniversal_UI1)
1591 constructor Create; override;
1594 TfdBGR12 = class(TfdBGR_US3)
1595 constructor Create; override;
1598 TfdBGR16 = class(TfdBGR_US3)
1599 constructor Create; override;
1602 TfdBGRA2 = class(TfdBGRA_UB4)
1603 constructor Create; override;
1606 TfdBGRA4 = class(TfdUniversal_US1)
1607 constructor Create; override;
1610 TfdBGR5A1 = class(TfdUniversal_US1)
1611 constructor Create; override;
1614 TfdBGRA8 = class(TfdBGRA_UB4)
1615 constructor Create; override;
1618 TfdBGR10A2 = class(TfdUniversal_UI1)
1619 constructor Create; override;
1622 TfdBGRA12 = class(TfdBGRA_US4)
1623 constructor Create; override;
1626 TfdBGRA16 = class(TfdBGRA_US4)
1627 constructor Create; override;
1630 TfdDepth16 = class(TfdDepth_US1)
1631 constructor Create; override;
1634 TfdDepth24 = class(TfdDepth_UI1)
1635 constructor Create; override;
1638 TfdDepth32 = class(TfdDepth_UI1)
1639 constructor Create; override;
1642 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1643 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1644 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1645 constructor Create; override;
1648 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1649 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1650 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1651 constructor Create; override;
1654 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1655 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1656 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1657 constructor Create; override;
1660 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1661 TbmpBitfieldFormat = class(TFormatDescriptor)
1663 procedure SetRedMask (const aValue: QWord);
1664 procedure SetGreenMask(const aValue: QWord);
1665 procedure SetBlueMask (const aValue: QWord);
1666 procedure SetAlphaMask(const aValue: QWord);
1668 procedure Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte);
1670 property RedMask: QWord read GetRedMask write SetRedMask;
1671 property GreenMask: QWord read GetGreenMask write SetGreenMask;
1672 property BlueMask: QWord read GetBlueMask write SetBlueMask;
1673 property AlphaMask: QWord read GetAlphaMask write SetAlphaMask;
1675 property PixelSize: Single read fPixelSize write fPixelSize;
1677 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1678 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1681 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1682 TbmpColorTableEnty = packed record
1685 TbmpColorTable = array of TbmpColorTableEnty;
1686 TbmpColorTableFormat = class(TFormatDescriptor)
1688 fColorTable: TbmpColorTable;
1690 property PixelSize: Single read fPixelSize write fPixelSize;
1691 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1692 property Range: TglBitmapColorRec read fRange write fRange;
1693 property Shift: TShiftRec read fShift write fShift;
1694 property Format: TglBitmapFormat read fFormat write fFormat;
1696 procedure CreateColorTable;
1698 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1699 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1700 destructor Destroy; override;
1704 LUMINANCE_WEIGHT_R = 0.30;
1705 LUMINANCE_WEIGHT_G = 0.59;
1706 LUMINANCE_WEIGHT_B = 0.11;
1708 ALPHA_WEIGHT_R = 0.30;
1709 ALPHA_WEIGHT_G = 0.59;
1710 ALPHA_WEIGHT_B = 0.11;
1712 DEPTH_WEIGHT_R = 0.333333333;
1713 DEPTH_WEIGHT_G = 0.333333333;
1714 DEPTH_WEIGHT_B = 0.333333333;
1716 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1718 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1731 TfdLuminance4Alpha4,
1732 TfdLuminance6Alpha2,
1733 TfdLuminance8Alpha8,
1734 TfdLuminance12Alpha4,
1735 TfdLuminance12Alpha12,
1736 TfdLuminance16Alpha16,
1781 FormatDescriptorCS: TCriticalSection;
1782 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1784 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1785 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1787 inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1790 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1791 constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat);
1793 inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1796 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1797 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1799 result.Fields := [];
1802 result.Fields := result.Fields + [ffX];
1804 result.Fields := result.Fields + [ffY];
1806 result.X := Max(0, X);
1807 result.Y := Max(0, Y);
1810 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1811 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1819 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1820 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1825 for i := 0 to high(r1.arr) do
1826 if (r1.arr[i] <> r2.arr[i]) then
1831 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1832 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1840 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1841 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1850 tfR3G3B2, tfLuminance8,
1853 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1854 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1860 tfRGB10, tfRGB10A2, tfRGBA8,
1861 tfBGR10, tfBGR10A2, tfBGRA8]) then
1862 result := result + [ftBMP];
1866 tfLuminance8, tfAlpha8,
1869 tfLuminance16, tfLuminance8Alpha8,
1870 tfRGB5, tfRGB5A1, tfRGBA4,
1871 tfBGR5, tfBGR5A1, tfBGRA4,
1877 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1878 result := result + [ftTGA];
1882 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1883 tfR3G3B2, tfRGBA2, tfBGRA2,
1886 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1887 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1888 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1894 tfLuminance16Alpha16,
1899 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1900 result := result + [ftDDS];
1902 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1904 tfAlpha8, tfLuminance8, tfLuminance8Alpha8,
1906 tfBGR8, tfBGRA8] then
1907 result := result + [ftPNG];
1910 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1911 if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then
1912 result := result + [ftJPEG];
1916 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1917 function IsPowerOfTwo(aNumber: Integer): Boolean;
1919 while (aNumber and 1) = 0 do
1920 aNumber := aNumber shr 1;
1921 result := aNumber = 1;
1924 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1925 function GetTopMostBit(aBitSet: QWord): Integer;
1928 while aBitSet > 0 do begin
1930 aBitSet := aBitSet shr 1;
1934 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1935 function CountSetBits(aBitSet: QWord): Integer;
1938 while aBitSet > 0 do begin
1939 if (aBitSet and 1) = 1 then
1941 aBitSet := aBitSet shr 1;
1945 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1946 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1949 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1950 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1951 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1954 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1955 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1958 DEPTH_WEIGHT_R * aPixel.Data.r +
1959 DEPTH_WEIGHT_G * aPixel.Data.g +
1960 DEPTH_WEIGHT_B * aPixel.Data.b);
1963 {$IFDEF GLB_NATIVE_OGL}
1964 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1965 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1966 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1968 GL_LibHandle: Pointer = nil;
1970 function glbGetProcAddress(aProcName: PAnsiChar; aLibHandle: Pointer = nil; const aRaiseOnErr: Boolean = true): Pointer;
1972 if not Assigned(aLibHandle) then
1973 aLibHandle := GL_LibHandle;
1975 {$IF DEFINED(GLB_WIN)}
1976 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1977 if Assigned(result) then
1980 if Assigned(wglGetProcAddress) then
1981 result := wglGetProcAddress(aProcName);
1982 {$ELSEIF DEFINED(GLB_LINUX)}
1983 if Assigned(glXGetProcAddress) then begin
1984 result := glXGetProcAddress(aProcName);
1985 if Assigned(result) then
1989 if Assigned(glXGetProcAddressARB) then begin
1990 result := glXGetProcAddressARB(aProcName);
1991 if Assigned(result) then
1995 result := dlsym(aLibHandle, aProcName);
1997 if not Assigned(result) and aRaiseOnErr then
1998 raise EglBitmap.Create('unable to load procedure form library: ' + aProcName);
2001 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2003 GLU_LibHandle: Pointer = nil;
2004 OpenGLInitialized: Boolean;
2005 InitOpenGLCS: TCriticalSection;
2007 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2008 procedure glbInitOpenGL;
2010 ////////////////////////////////////////////////////////////////////////////////
2011 function glbLoadLibrary(const aName: PChar): Pointer;
2013 {$IF DEFINED(GLB_WIN)}
2014 result := {%H-}Pointer(LoadLibrary(aName));
2015 {$ELSEIF DEFINED(GLB_LINUX)}
2016 result := dlopen(Name, RTLD_LAZY);
2022 ////////////////////////////////////////////////////////////////////////////////
2023 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
2026 if not Assigned(aLibHandle) then
2029 {$IF DEFINED(GLB_WIN)}
2030 Result := FreeLibrary({%H-}HINST(aLibHandle));
2031 {$ELSEIF DEFINED(GLB_LINUX)}
2032 Result := dlclose(aLibHandle) = 0;
2037 if Assigned(GL_LibHandle) then
2038 glbFreeLibrary(GL_LibHandle);
2040 if Assigned(GLU_LibHandle) then
2041 glbFreeLibrary(GLU_LibHandle);
2043 GL_LibHandle := glbLoadLibrary(libopengl);
2044 if not Assigned(GL_LibHandle) then
2045 raise EglBitmap.Create('unable to load library: ' + libopengl);
2047 GLU_LibHandle := glbLoadLibrary(libglu);
2048 if not Assigned(GLU_LibHandle) then
2049 raise EglBitmap.Create('unable to load library: ' + libglu);
2051 {$IF DEFINED(GLB_WIN)}
2052 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
2053 {$ELSEIF DEFINED(GLB_LINUX)}
2054 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
2055 glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
2058 glEnable := glbGetProcAddress('glEnable');
2059 glDisable := glbGetProcAddress('glDisable');
2060 glGetString := glbGetProcAddress('glGetString');
2061 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
2062 glTexParameteri := glbGetProcAddress('glTexParameteri');
2063 glTexParameteriv := glbGetProcAddress('glTexParameteriv');
2064 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
2065 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
2066 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
2067 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
2068 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
2069 glTexGeni := glbGetProcAddress('glTexGeni');
2070 glGenTextures := glbGetProcAddress('glGenTextures');
2071 glBindTexture := glbGetProcAddress('glBindTexture');
2072 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
2073 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
2074 glReadPixels := glbGetProcAddress('glReadPixels');
2075 glPixelStorei := glbGetProcAddress('glPixelStorei');
2076 glTexImage1D := glbGetProcAddress('glTexImage1D');
2077 glTexImage2D := glbGetProcAddress('glTexImage2D');
2078 glGetTexImage := glbGetProcAddress('glGetTexImage');
2080 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
2081 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
2085 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2086 procedure glbReadOpenGLExtensions;
2089 MajorVersion, MinorVersion: Integer;
2091 ///////////////////////////////////////////////////////////////////////////////////////////
2092 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
2099 Separator := Pos(AnsiString('.'), aBuffer);
2100 if (Separator > 1) and (Separator < Length(aBuffer)) and
2101 (aBuffer[Separator - 1] in ['0'..'9']) and
2102 (aBuffer[Separator + 1] in ['0'..'9']) then begin
2105 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
2108 Delete(aBuffer, 1, Separator);
2109 Separator := Pos(AnsiString('.'), aBuffer) + 1;
2111 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
2114 Delete(aBuffer, Separator, 255);
2115 Separator := Pos(AnsiString('.'), aBuffer);
2117 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
2118 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2122 ///////////////////////////////////////////////////////////////////////////////////////////
2123 function CheckExtension(const Extension: AnsiString): Boolean;
2127 ExtPos := Pos(Extension, Buffer);
2128 result := ExtPos > 0;
2130 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2133 ///////////////////////////////////////////////////////////////////////////////////////////
2134 function CheckVersion(const aMajor, aMinor: Integer): Boolean;
2136 result := (MajorVersion > aMajor) or ((MajorVersion = aMajor) and (MinorVersion >= aMinor));
2140 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2143 if not OpenGLInitialized then begin
2145 OpenGLInitialized := true;
2153 Buffer := glGetString(GL_VERSION);
2154 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2156 GL_VERSION_1_2 := CheckVersion(1, 2);
2157 GL_VERSION_1_3 := CheckVersion(1, 3);
2158 GL_VERSION_1_4 := CheckVersion(1, 4);
2159 GL_VERSION_2_0 := CheckVersion(2, 0);
2160 GL_VERSION_3_3 := CheckVersion(3, 3);
2163 Buffer := glGetString(GL_EXTENSIONS);
2164 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2165 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2166 GL_ARB_texture_swizzle := CheckExtension('GL_ARB_texture_swizzle');
2167 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
2168 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2169 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2170 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2171 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2172 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2173 GL_EXT_texture_swizzle := CheckExtension('GL_EXT_texture_swizzle');
2174 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
2175 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2176 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2177 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2179 if GL_VERSION_1_3 then begin
2180 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2181 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2182 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2184 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB', nil, false);
2185 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB', nil, false);
2186 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB', nil, false);
2191 {$IFDEF GLB_SDL_IMAGE}
2192 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2193 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2194 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2195 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2197 result := TStream(context^.unknown.data1).Seek(offset, whence);
2200 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2202 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2205 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2207 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2210 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2215 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2217 result := SDL_AllocRW;
2219 if result = nil then
2220 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2222 result^.seek := glBitmapRWseek;
2223 result^.read := glBitmapRWread;
2224 result^.write := glBitmapRWwrite;
2225 result^.close := glBitmapRWclose;
2226 result^.unknown.data1 := Stream;
2230 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2231 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2233 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2236 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2237 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2239 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2242 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2243 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2245 glBitmapDefaultMipmap := aValue;
2248 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2249 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2251 glBitmapDefaultFormat := aFormat;
2254 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2255 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2257 glBitmapDefaultFilterMin := aMin;
2258 glBitmapDefaultFilterMag := aMag;
2261 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2262 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2264 glBitmapDefaultWrapS := S;
2265 glBitmapDefaultWrapT := T;
2266 glBitmapDefaultWrapR := R;
2269 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2270 procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA);
2272 glDefaultSwizzle[0] := r;
2273 glDefaultSwizzle[1] := g;
2274 glDefaultSwizzle[2] := b;
2275 glDefaultSwizzle[3] := a;
2278 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2279 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2281 result := glBitmapDefaultDeleteTextureOnFree;
2284 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2285 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2287 result := glBitmapDefaultFreeDataAfterGenTextures;
2290 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2291 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2293 result := glBitmapDefaultMipmap;
2296 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2297 function glBitmapGetDefaultFormat: TglBitmapFormat;
2299 result := glBitmapDefaultFormat;
2302 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2303 procedure glBitmapGetDefaultFilter(var aMin, aMag: GLenum);
2305 aMin := glBitmapDefaultFilterMin;
2306 aMag := glBitmapDefaultFilterMag;
2309 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2310 procedure glBitmapGetDefaultTextureWrap(var S, T, R: GLenum);
2312 S := glBitmapDefaultWrapS;
2313 T := glBitmapDefaultWrapT;
2314 R := glBitmapDefaultWrapR;
2317 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2318 procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum);
2320 r := glDefaultSwizzle[0];
2321 g := glDefaultSwizzle[1];
2322 b := glDefaultSwizzle[2];
2323 a := glDefaultSwizzle[3];
2326 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2327 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2328 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2329 function TFormatDescriptor.GetRedMask: QWord;
2331 result := fRange.r shl fShift.r;
2334 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2335 function TFormatDescriptor.GetGreenMask: QWord;
2337 result := fRange.g shl fShift.g;
2340 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2341 function TFormatDescriptor.GetBlueMask: QWord;
2343 result := fRange.b shl fShift.b;
2346 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2347 function TFormatDescriptor.GetAlphaMask: QWord;
2349 result := fRange.a shl fShift.a;
2352 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2353 function TFormatDescriptor.GetIsCompressed: Boolean;
2355 result := fIsCompressed;
2358 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2359 function TFormatDescriptor.GetHasRed: Boolean;
2361 result := (fRange.r > 0);
2364 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2365 function TFormatDescriptor.GetHasGreen: Boolean;
2367 result := (fRange.g > 0);
2370 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2371 function TFormatDescriptor.GetHasBlue: Boolean;
2373 result := (fRange.b > 0);
2376 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2377 function TFormatDescriptor.GetHasAlpha: Boolean;
2379 result := (fRange.a > 0);
2382 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2383 function TFormatDescriptor.GetglFormat: GLenum;
2385 result := fglFormat;
2388 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2389 function TFormatDescriptor.GetglInternalFormat: GLenum;
2391 result := fglInternalFormat;
2394 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2395 function TFormatDescriptor.GetglDataFormat: GLenum;
2397 result := fglDataFormat;
2400 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2401 function TFormatDescriptor.GetComponents: Integer;
2407 if (fRange.arr[i] > 0) then
2411 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2412 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2416 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2417 w := Max(1, aSize.X);
2418 h := Max(1, aSize.Y);
2419 result := GetSize(w, h);
2424 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2425 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2428 if (aWidth <= 0) or (aHeight <= 0) then
2430 result := Ceil(aWidth * aHeight * fPixelSize);
2433 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2434 function TFormatDescriptor.CreateMappingData: Pointer;
2439 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2440 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2445 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2446 function TFormatDescriptor.IsEmpty: Boolean;
2448 result := (fFormat = tfEmpty);
2451 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2452 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2455 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2456 raise EglBitmap.Create('FormatCheckFormat - All Masks are 0');
2457 if (aRedMask <> RedMask) then
2459 if (aGreenMask <> GreenMask) then
2461 if (aBlueMask <> BlueMask) then
2463 if (aAlphaMask <> AlphaMask) then
2468 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2469 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2471 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2472 aPixel.Data := fRange;
2473 aPixel.Range := fRange;
2474 aPixel.Format := fFormat;
2477 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2478 constructor TFormatDescriptor.Create;
2483 fWithAlpha := tfEmpty;
2484 fWithoutAlpha := tfEmpty;
2485 fRGBInverted := tfEmpty;
2486 fUncompressed := tfEmpty;
2488 fIsCompressed := false;
2491 fglInternalFormat := 0;
2494 FillChar(fRange, 0, SizeOf(fRange));
2495 FillChar(fShift, 0, SizeOf(fShift));
2498 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2499 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2500 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2501 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2503 aData^ := aPixel.Data.a;
2507 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2512 aPixel.Data.a := aData^;
2516 constructor TfdAlpha_UB1.Create;
2521 fglFormat := GL_ALPHA;
2522 fglDataFormat := GL_UNSIGNED_BYTE;
2525 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2526 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2527 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2528 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2530 aData^ := LuminanceWeight(aPixel);
2534 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2536 aPixel.Data.r := aData^;
2537 aPixel.Data.g := aData^;
2538 aPixel.Data.b := aData^;
2543 constructor TfdLuminance_UB1.Create;
2550 fglFormat := GL_LUMINANCE;
2551 fglDataFormat := GL_UNSIGNED_BYTE;
2554 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2555 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2556 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2557 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2563 if (fRange.arr[i] > 0) then
2564 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2568 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2573 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2577 constructor TfdUniversal_UB1.Create;
2583 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2584 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2585 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2586 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2588 inherited Map(aPixel, aData, aMapData);
2589 aData^ := aPixel.Data.a;
2593 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2595 inherited Unmap(aData, aPixel, aMapData);
2596 aPixel.Data.a := aData^;
2600 constructor TfdLuminanceAlpha_UB2.Create;
2606 fglFormat := GL_LUMINANCE_ALPHA;
2607 fglDataFormat := GL_UNSIGNED_BYTE;
2610 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2611 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2612 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2613 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2615 aData^ := aPixel.Data.r;
2617 aData^ := aPixel.Data.g;
2619 aData^ := aPixel.Data.b;
2623 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2625 aPixel.Data.r := aData^;
2627 aPixel.Data.g := aData^;
2629 aPixel.Data.b := aData^;
2634 constructor TfdRGB_UB3.Create;
2644 fglFormat := GL_RGB;
2645 fglDataFormat := GL_UNSIGNED_BYTE;
2648 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2649 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2650 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2651 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2653 aData^ := aPixel.Data.b;
2655 aData^ := aPixel.Data.g;
2657 aData^ := aPixel.Data.r;
2661 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2663 aPixel.Data.b := aData^;
2665 aPixel.Data.g := aData^;
2667 aPixel.Data.r := aData^;
2672 constructor TfdBGR_UB3.Create;
2681 fglFormat := GL_BGR;
2682 fglDataFormat := GL_UNSIGNED_BYTE;
2685 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2686 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2687 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2688 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2690 inherited Map(aPixel, aData, aMapData);
2691 aData^ := aPixel.Data.a;
2695 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2697 inherited Unmap(aData, aPixel, aMapData);
2698 aPixel.Data.a := aData^;
2702 constructor TfdRGBA_UB4.Create;
2708 fglFormat := GL_RGBA;
2709 fglDataFormat := GL_UNSIGNED_BYTE;
2712 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2713 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2714 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2715 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2717 inherited Map(aPixel, aData, aMapData);
2718 aData^ := aPixel.Data.a;
2722 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2724 inherited Unmap(aData, aPixel, aMapData);
2725 aPixel.Data.a := aData^;
2729 constructor TfdBGRA_UB4.Create;
2735 fglFormat := GL_BGRA;
2736 fglDataFormat := GL_UNSIGNED_BYTE;
2739 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2740 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2741 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2742 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2744 PWord(aData)^ := aPixel.Data.a;
2748 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2753 aPixel.Data.a := PWord(aData)^;
2757 constructor TfdAlpha_US1.Create;
2762 fglFormat := GL_ALPHA;
2763 fglDataFormat := GL_UNSIGNED_SHORT;
2766 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2767 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2768 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2769 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2771 PWord(aData)^ := LuminanceWeight(aPixel);
2775 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2777 aPixel.Data.r := PWord(aData)^;
2778 aPixel.Data.g := PWord(aData)^;
2779 aPixel.Data.b := PWord(aData)^;
2784 constructor TfdLuminance_US1.Create;
2791 fglFormat := GL_LUMINANCE;
2792 fglDataFormat := GL_UNSIGNED_SHORT;
2795 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2796 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2797 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2798 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2804 if (fRange.arr[i] > 0) then
2805 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2809 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2814 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2818 constructor TfdUniversal_US1.Create;
2824 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2825 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2826 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2827 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2829 PWord(aData)^ := DepthWeight(aPixel);
2833 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2835 aPixel.Data.r := PWord(aData)^;
2836 aPixel.Data.g := PWord(aData)^;
2837 aPixel.Data.b := PWord(aData)^;
2842 constructor TfdDepth_US1.Create;
2849 fglFormat := GL_DEPTH_COMPONENT;
2850 fglDataFormat := GL_UNSIGNED_SHORT;
2853 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2854 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2855 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2856 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2858 inherited Map(aPixel, aData, aMapData);
2859 PWord(aData)^ := aPixel.Data.a;
2863 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2865 inherited Unmap(aData, aPixel, aMapData);
2866 aPixel.Data.a := PWord(aData)^;
2870 constructor TfdLuminanceAlpha_US2.Create;
2876 fglFormat := GL_LUMINANCE_ALPHA;
2877 fglDataFormat := GL_UNSIGNED_SHORT;
2880 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2881 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2882 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2883 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2885 PWord(aData)^ := aPixel.Data.r;
2887 PWord(aData)^ := aPixel.Data.g;
2889 PWord(aData)^ := aPixel.Data.b;
2893 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2895 aPixel.Data.r := PWord(aData)^;
2897 aPixel.Data.g := PWord(aData)^;
2899 aPixel.Data.b := PWord(aData)^;
2904 constructor TfdRGB_US3.Create;
2914 fglFormat := GL_RGB;
2915 fglDataFormat := GL_UNSIGNED_SHORT;
2918 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2919 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2920 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2921 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2923 PWord(aData)^ := aPixel.Data.b;
2925 PWord(aData)^ := aPixel.Data.g;
2927 PWord(aData)^ := aPixel.Data.r;
2931 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2933 aPixel.Data.b := PWord(aData)^;
2935 aPixel.Data.g := PWord(aData)^;
2937 aPixel.Data.r := PWord(aData)^;
2942 constructor TfdBGR_US3.Create;
2952 fglFormat := GL_BGR;
2953 fglDataFormat := GL_UNSIGNED_SHORT;
2956 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2957 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2958 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2959 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2961 inherited Map(aPixel, aData, aMapData);
2962 PWord(aData)^ := aPixel.Data.a;
2966 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2968 inherited Unmap(aData, aPixel, aMapData);
2969 aPixel.Data.a := PWord(aData)^;
2973 constructor TfdRGBA_US4.Create;
2979 fglFormat := GL_RGBA;
2980 fglDataFormat := GL_UNSIGNED_SHORT;
2983 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2984 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2985 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2986 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2988 inherited Map(aPixel, aData, aMapData);
2989 PWord(aData)^ := aPixel.Data.a;
2993 procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2995 inherited Unmap(aData, aPixel, aMapData);
2996 aPixel.Data.a := PWord(aData)^;
3000 constructor TfdBGRA_US4.Create;
3006 fglFormat := GL_BGRA;
3007 fglDataFormat := GL_UNSIGNED_SHORT;
3010 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3011 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3012 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3013 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3017 PCardinal(aData)^ := 0;
3019 if (fRange.arr[i] > 0) then
3020 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
3024 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3029 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
3033 constructor TfdUniversal_UI1.Create;
3039 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3040 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3041 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3042 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3044 PCardinal(aData)^ := DepthWeight(aPixel);
3048 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3050 aPixel.Data.r := PCardinal(aData)^;
3051 aPixel.Data.g := PCardinal(aData)^;
3052 aPixel.Data.b := PCardinal(aData)^;
3057 constructor TfdDepth_UI1.Create;
3061 fRange.r := $FFFFFFFF;
3062 fRange.g := $FFFFFFFF;
3063 fRange.b := $FFFFFFFF;
3064 fglFormat := GL_DEPTH_COMPONENT;
3065 fglDataFormat := GL_UNSIGNED_INT;
3068 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3069 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3070 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3071 constructor TfdAlpha4.Create;
3074 fFormat := tfAlpha4;
3075 fWithAlpha := tfAlpha4;
3076 fglInternalFormat := GL_ALPHA4;
3079 constructor TfdAlpha8.Create;
3082 fFormat := tfAlpha8;
3083 fWithAlpha := tfAlpha8;
3084 fglInternalFormat := GL_ALPHA8;
3087 constructor TfdAlpha12.Create;
3090 fFormat := tfAlpha12;
3091 fWithAlpha := tfAlpha12;
3092 fglInternalFormat := GL_ALPHA12;
3095 constructor TfdAlpha16.Create;
3098 fFormat := tfAlpha16;
3099 fWithAlpha := tfAlpha16;
3100 fglInternalFormat := GL_ALPHA16;
3103 constructor TfdLuminance4.Create;
3106 fFormat := tfLuminance4;
3107 fWithAlpha := tfLuminance4Alpha4;
3108 fWithoutAlpha := tfLuminance4;
3109 fglInternalFormat := GL_LUMINANCE4;
3112 constructor TfdLuminance8.Create;
3115 fFormat := tfLuminance8;
3116 fWithAlpha := tfLuminance8Alpha8;
3117 fWithoutAlpha := tfLuminance8;
3118 fglInternalFormat := GL_LUMINANCE8;
3121 constructor TfdLuminance12.Create;
3124 fFormat := tfLuminance12;
3125 fWithAlpha := tfLuminance12Alpha12;
3126 fWithoutAlpha := tfLuminance12;
3127 fglInternalFormat := GL_LUMINANCE12;
3130 constructor TfdLuminance16.Create;
3133 fFormat := tfLuminance16;
3134 fWithAlpha := tfLuminance16Alpha16;
3135 fWithoutAlpha := tfLuminance16;
3136 fglInternalFormat := GL_LUMINANCE16;
3139 constructor TfdLuminance4Alpha4.Create;
3142 fFormat := tfLuminance4Alpha4;
3143 fWithAlpha := tfLuminance4Alpha4;
3144 fWithoutAlpha := tfLuminance4;
3145 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3148 constructor TfdLuminance6Alpha2.Create;
3151 fFormat := tfLuminance6Alpha2;
3152 fWithAlpha := tfLuminance6Alpha2;
3153 fWithoutAlpha := tfLuminance8;
3154 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3157 constructor TfdLuminance8Alpha8.Create;
3160 fFormat := tfLuminance8Alpha8;
3161 fWithAlpha := tfLuminance8Alpha8;
3162 fWithoutAlpha := tfLuminance8;
3163 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3166 constructor TfdLuminance12Alpha4.Create;
3169 fFormat := tfLuminance12Alpha4;
3170 fWithAlpha := tfLuminance12Alpha4;
3171 fWithoutAlpha := tfLuminance12;
3172 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3175 constructor TfdLuminance12Alpha12.Create;
3178 fFormat := tfLuminance12Alpha12;
3179 fWithAlpha := tfLuminance12Alpha12;
3180 fWithoutAlpha := tfLuminance12;
3181 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3184 constructor TfdLuminance16Alpha16.Create;
3187 fFormat := tfLuminance16Alpha16;
3188 fWithAlpha := tfLuminance16Alpha16;
3189 fWithoutAlpha := tfLuminance16;
3190 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3193 constructor TfdR3G3B2.Create;
3196 fFormat := tfR3G3B2;
3197 fWithAlpha := tfRGBA2;
3198 fWithoutAlpha := tfR3G3B2;
3205 fglFormat := GL_RGB;
3206 fglInternalFormat := GL_R3_G3_B2;
3207 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3210 constructor TfdRGB4.Create;
3214 fWithAlpha := tfRGBA4;
3215 fWithoutAlpha := tfRGB4;
3216 fRGBInverted := tfBGR4;
3223 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3224 fglInternalFormat := GL_RGB4;
3225 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3228 constructor TfdR5G6B5.Create;
3231 fFormat := tfR5G6B5;
3232 fWithAlpha := tfRGBA4;
3233 fWithoutAlpha := tfR5G6B5;
3234 fRGBInverted := tfB5G6R5;
3241 fglFormat := GL_RGB;
3242 fglInternalFormat := GL_RGB565;
3243 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3246 constructor TfdRGB5.Create;
3250 fWithAlpha := tfRGB5A1;
3251 fWithoutAlpha := tfRGB5;
3252 fRGBInverted := tfBGR5;
3259 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3260 fglInternalFormat := GL_RGB5;
3261 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3264 constructor TfdRGB8.Create;
3268 fWithAlpha := tfRGBA8;
3269 fWithoutAlpha := tfRGB8;
3270 fRGBInverted := tfBGR8;
3271 fglInternalFormat := GL_RGB8;
3274 constructor TfdRGB10.Create;
3278 fWithAlpha := tfRGB10A2;
3279 fWithoutAlpha := tfRGB10;
3280 fRGBInverted := tfBGR10;
3287 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3288 fglInternalFormat := GL_RGB10;
3289 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3292 constructor TfdRGB12.Create;
3296 fWithAlpha := tfRGBA12;
3297 fWithoutAlpha := tfRGB12;
3298 fRGBInverted := tfBGR12;
3299 fglInternalFormat := GL_RGB12;
3302 constructor TfdRGB16.Create;
3306 fWithAlpha := tfRGBA16;
3307 fWithoutAlpha := tfRGB16;
3308 fRGBInverted := tfBGR16;
3309 fglInternalFormat := GL_RGB16;
3312 constructor TfdRGBA2.Create;
3316 fWithAlpha := tfRGBA2;
3317 fWithoutAlpha := tfR3G3B2;
3318 fRGBInverted := tfBGRA2;
3319 fglInternalFormat := GL_RGBA2;
3322 constructor TfdRGBA4.Create;
3326 fWithAlpha := tfRGBA4;
3327 fWithoutAlpha := tfRGB4;
3328 fRGBInverted := tfBGRA4;
3337 fglFormat := GL_RGBA;
3338 fglInternalFormat := GL_RGBA4;
3339 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3342 constructor TfdRGB5A1.Create;
3345 fFormat := tfRGB5A1;
3346 fWithAlpha := tfRGB5A1;
3347 fWithoutAlpha := tfRGB5;
3348 fRGBInverted := tfBGR5A1;
3357 fglFormat := GL_RGBA;
3358 fglInternalFormat := GL_RGB5_A1;
3359 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3362 constructor TfdRGBA8.Create;
3366 fWithAlpha := tfRGBA8;
3367 fWithoutAlpha := tfRGB8;
3368 fRGBInverted := tfBGRA8;
3369 fglInternalFormat := GL_RGBA8;
3372 constructor TfdRGB10A2.Create;
3375 fFormat := tfRGB10A2;
3376 fWithAlpha := tfRGB10A2;
3377 fWithoutAlpha := tfRGB10;
3378 fRGBInverted := tfBGR10A2;
3387 fglFormat := GL_RGBA;
3388 fglInternalFormat := GL_RGB10_A2;
3389 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3392 constructor TfdRGBA12.Create;
3395 fFormat := tfRGBA12;
3396 fWithAlpha := tfRGBA12;
3397 fWithoutAlpha := tfRGB12;
3398 fRGBInverted := tfBGRA12;
3399 fglInternalFormat := GL_RGBA12;
3402 constructor TfdRGBA16.Create;
3405 fFormat := tfRGBA16;
3406 fWithAlpha := tfRGBA16;
3407 fWithoutAlpha := tfRGB16;
3408 fRGBInverted := tfBGRA16;
3409 fglInternalFormat := GL_RGBA16;
3412 constructor TfdBGR4.Create;
3417 fWithAlpha := tfBGRA4;
3418 fWithoutAlpha := tfBGR4;
3419 fRGBInverted := tfRGB4;
3428 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3429 fglInternalFormat := GL_RGB4;
3430 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3433 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3434 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3435 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3436 constructor TfdB5G6R5.Create;
3439 fFormat := tfB5G6R5;
3440 fWithAlpha := tfBGRA4;
3441 fWithoutAlpha := tfB5G6R5;
3442 fRGBInverted := tfR5G6B5;
3449 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3450 fglInternalFormat := GL_RGB8;
3451 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3454 constructor TfdBGR5.Create;
3459 fWithAlpha := tfBGR5A1;
3460 fWithoutAlpha := tfBGR5;
3461 fRGBInverted := tfRGB5;
3470 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3471 fglInternalFormat := GL_RGB5;
3472 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3475 constructor TfdBGR8.Create;
3479 fWithAlpha := tfBGRA8;
3480 fWithoutAlpha := tfBGR8;
3481 fRGBInverted := tfRGB8;
3482 fglInternalFormat := GL_RGB8;
3485 constructor TfdBGR10.Create;
3489 fWithAlpha := tfBGR10A2;
3490 fWithoutAlpha := tfBGR10;
3491 fRGBInverted := tfRGB10;
3500 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3501 fglInternalFormat := GL_RGB10;
3502 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3505 constructor TfdBGR12.Create;
3509 fWithAlpha := tfBGRA12;
3510 fWithoutAlpha := tfBGR12;
3511 fRGBInverted := tfRGB12;
3512 fglInternalFormat := GL_RGB12;
3515 constructor TfdBGR16.Create;
3519 fWithAlpha := tfBGRA16;
3520 fWithoutAlpha := tfBGR16;
3521 fRGBInverted := tfRGB16;
3522 fglInternalFormat := GL_RGB16;
3525 constructor TfdBGRA2.Create;
3529 fWithAlpha := tfBGRA4;
3530 fWithoutAlpha := tfBGR4;
3531 fRGBInverted := tfRGBA2;
3532 fglInternalFormat := GL_RGBA2;
3535 constructor TfdBGRA4.Create;
3539 fWithAlpha := tfBGRA4;
3540 fWithoutAlpha := tfBGR4;
3541 fRGBInverted := tfRGBA4;
3550 fglFormat := GL_BGRA;
3551 fglInternalFormat := GL_RGBA4;
3552 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3555 constructor TfdBGR5A1.Create;
3558 fFormat := tfBGR5A1;
3559 fWithAlpha := tfBGR5A1;
3560 fWithoutAlpha := tfBGR5;
3561 fRGBInverted := tfRGB5A1;
3570 fglFormat := GL_BGRA;
3571 fglInternalFormat := GL_RGB5_A1;
3572 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3575 constructor TfdBGRA8.Create;
3579 fWithAlpha := tfBGRA8;
3580 fWithoutAlpha := tfBGR8;
3581 fRGBInverted := tfRGBA8;
3582 fglInternalFormat := GL_RGBA8;
3585 constructor TfdBGR10A2.Create;
3588 fFormat := tfBGR10A2;
3589 fWithAlpha := tfBGR10A2;
3590 fWithoutAlpha := tfBGR10;
3591 fRGBInverted := tfRGB10A2;
3600 fglFormat := GL_BGRA;
3601 fglInternalFormat := GL_RGB10_A2;
3602 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3605 constructor TfdBGRA12.Create;
3608 fFormat := tfBGRA12;
3609 fWithAlpha := tfBGRA12;
3610 fWithoutAlpha := tfBGR12;
3611 fRGBInverted := tfRGBA12;
3612 fglInternalFormat := GL_RGBA12;
3615 constructor TfdBGRA16.Create;
3618 fFormat := tfBGRA16;
3619 fWithAlpha := tfBGRA16;
3620 fWithoutAlpha := tfBGR16;
3621 fRGBInverted := tfRGBA16;
3622 fglInternalFormat := GL_RGBA16;
3625 constructor TfdDepth16.Create;
3628 fFormat := tfDepth16;
3629 fWithAlpha := tfEmpty;
3630 fWithoutAlpha := tfDepth16;
3631 fglInternalFormat := GL_DEPTH_COMPONENT16;
3634 constructor TfdDepth24.Create;
3637 fFormat := tfDepth24;
3638 fWithAlpha := tfEmpty;
3639 fWithoutAlpha := tfDepth24;
3640 fglInternalFormat := GL_DEPTH_COMPONENT24;
3643 constructor TfdDepth32.Create;
3646 fFormat := tfDepth32;
3647 fWithAlpha := tfEmpty;
3648 fWithoutAlpha := tfDepth32;
3649 fglInternalFormat := GL_DEPTH_COMPONENT32;
3652 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3653 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3654 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3655 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3657 raise EglBitmap.Create('mapping for compressed formats is not supported');
3660 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3662 raise EglBitmap.Create('mapping for compressed formats is not supported');
3665 constructor TfdS3tcDtx1RGBA.Create;
3668 fFormat := tfS3tcDtx1RGBA;
3669 fWithAlpha := tfS3tcDtx1RGBA;
3670 fUncompressed := tfRGB5A1;
3672 fIsCompressed := true;
3673 fglFormat := GL_COMPRESSED_RGBA;
3674 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3675 fglDataFormat := GL_UNSIGNED_BYTE;
3678 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3679 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3680 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3681 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3683 raise EglBitmap.Create('mapping for compressed formats is not supported');
3686 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3688 raise EglBitmap.Create('mapping for compressed formats is not supported');
3691 constructor TfdS3tcDtx3RGBA.Create;
3694 fFormat := tfS3tcDtx3RGBA;
3695 fWithAlpha := tfS3tcDtx3RGBA;
3696 fUncompressed := tfRGBA8;
3698 fIsCompressed := true;
3699 fglFormat := GL_COMPRESSED_RGBA;
3700 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3701 fglDataFormat := GL_UNSIGNED_BYTE;
3704 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3705 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3706 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3707 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3709 raise EglBitmap.Create('mapping for compressed formats is not supported');
3712 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3714 raise EglBitmap.Create('mapping for compressed formats is not supported');
3717 constructor TfdS3tcDtx5RGBA.Create;
3720 fFormat := tfS3tcDtx3RGBA;
3721 fWithAlpha := tfS3tcDtx3RGBA;
3722 fUncompressed := tfRGBA8;
3724 fIsCompressed := true;
3725 fglFormat := GL_COMPRESSED_RGBA;
3726 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3727 fglDataFormat := GL_UNSIGNED_BYTE;
3730 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3731 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3732 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3733 class function TglBitmapFormatDescriptor.GetByFormat(const aInternalFormat: GLenum): TglBitmapFormatDescriptor;
3737 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
3738 result := TFormatDescriptor.Get(f);
3739 if (result.glInternalFormat = aInternalFormat) then
3742 result := TFormatDescriptor.Get(tfEmpty);
3745 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3746 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3747 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3748 class procedure TFormatDescriptor.Init;
3750 if not Assigned(FormatDescriptorCS) then
3751 FormatDescriptorCS := TCriticalSection.Create;
3754 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3755 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3757 FormatDescriptorCS.Enter;
3759 result := FormatDescriptors[aFormat];
3760 if not Assigned(result) then begin
3761 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3762 FormatDescriptors[aFormat] := result;
3765 FormatDescriptorCS.Leave;
3769 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3770 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3772 result := Get(Get(aFormat).WithAlpha);
3775 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3776 class procedure TFormatDescriptor.Clear;
3780 FormatDescriptorCS.Enter;
3782 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3783 FreeAndNil(FormatDescriptors[f]);
3785 FormatDescriptorCS.Leave;
3789 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3790 class procedure TFormatDescriptor.Finalize;
3793 FreeAndNil(FormatDescriptorCS);
3796 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3797 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3798 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3799 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3801 Update(aValue, fRange.r, fShift.r);
3804 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3805 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3807 Update(aValue, fRange.g, fShift.g);
3810 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3811 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3813 Update(aValue, fRange.b, fShift.b);
3816 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3817 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3819 Update(aValue, fRange.a, fShift.a);
3822 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3823 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3830 while (aMask > 0) and ((aMask and 1) = 0) do begin
3832 aMask := aMask shr 1;
3835 while (aMask > 0) do begin
3836 aRange := aRange shl 1;
3837 aMask := aMask shr 1;
3841 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3844 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3845 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3851 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3852 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3853 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3854 ((aPixel.Data.a and fRange.a) shl fShift.a);
3855 s := Round(fPixelSize);
3858 2: PWord(aData)^ := data;
3859 4: PCardinal(aData)^ := data;
3860 8: PQWord(aData)^ := data;
3862 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3867 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3868 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3873 s := Round(fPixelSize);
3876 2: data := PWord(aData)^;
3877 4: data := PCardinal(aData)^;
3878 8: data := PQWord(aData)^;
3880 raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3883 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3887 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3888 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3889 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3890 procedure TbmpColorTableFormat.CreateColorTable;
3894 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3895 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3897 if (Format = tfLuminance4) then
3898 SetLength(fColorTable, 16)
3900 SetLength(fColorTable, 256);
3904 for i := 0 to High(fColorTable) do begin
3905 fColorTable[i].r := 16 * i;
3906 fColorTable[i].g := 16 * i;
3907 fColorTable[i].b := 16 * i;
3908 fColorTable[i].a := 0;
3913 for i := 0 to High(fColorTable) do begin
3914 fColorTable[i].r := i;
3915 fColorTable[i].g := i;
3916 fColorTable[i].b := i;
3917 fColorTable[i].a := 0;
3922 for i := 0 to High(fColorTable) do begin
3923 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3924 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3925 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3926 fColorTable[i].a := 0;
3932 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3933 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3937 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3938 raise EglBitmap.Create(UNSUPPORTED_FORMAT);
3942 if (aMapData = nil) then
3944 d := LuminanceWeight(aPixel) and Range.r;
3945 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3946 inc(PByte(aMapData), 4);
3947 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3954 aData^ := LuminanceWeight(aPixel) and Range.r;
3960 ((aPixel.Data.r and Range.r) shl Shift.r) or
3961 ((aPixel.Data.g and Range.g) shl Shift.g) or
3962 ((aPixel.Data.b and Range.b) shl Shift.b));
3968 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3969 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3976 s := Trunc(fPixelSize);
3977 f := fPixelSize - s;
3978 bits := Round(8 * f);
3980 0: idx := (aData^ shr (8 - bits - {%H-}PtrInt(aMapData))) and ((1 shl bits) - 1);
3982 2: idx := PWord(aData)^;
3983 4: idx := PCardinal(aData)^;
3984 8: idx := PQWord(aData)^;
3986 raise EglBitmap.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3988 if (idx >= Length(fColorTable)) then
3989 raise EglBitmap.CreateFmt('invalid color index: %d', [idx]);
3990 with fColorTable[idx] do begin
3996 inc(PByte(aMapData), bits);
3997 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3999 dec(PByte(aMapData), 8);
4004 destructor TbmpColorTableFormat.Destroy;
4006 SetLength(fColorTable, 0);
4010 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4011 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4012 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4013 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
4017 for i := 0 to 3 do begin
4018 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
4019 if (aSourceFD.Range.arr[i] > 0) then
4020 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
4022 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
4027 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4028 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
4030 with aFuncRec do begin
4031 if (Source.Range.r > 0) then
4032 Dest.Data.r := Source.Data.r;
4033 if (Source.Range.g > 0) then
4034 Dest.Data.g := Source.Data.g;
4035 if (Source.Range.b > 0) then
4036 Dest.Data.b := Source.Data.b;
4037 if (Source.Range.a > 0) then
4038 Dest.Data.a := Source.Data.a;
4042 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4043 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4047 with aFuncRec do begin
4049 if (Source.Range.arr[i] > 0) then
4050 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4055 TShiftData = packed record
4057 0: (r, g, b, a: SmallInt);
4058 1: (arr: array[0..3] of SmallInt);
4060 PShiftData = ^TShiftData;
4062 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4063 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4069 if (Source.Range.arr[i] > 0) then
4070 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4073 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4074 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4076 with aFuncRec do begin
4077 Dest.Data := Source.Data;
4078 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4079 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4080 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4081 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4083 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4084 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4089 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4090 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4094 with aFuncRec do begin
4096 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4100 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4101 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4105 with FuncRec do begin
4106 if (FuncRec.Args = nil) then begin //source has no alpha
4108 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4109 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4110 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4111 Dest.Data.a := Round(Dest.Range.a * Temp);
4113 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4117 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4118 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4120 PglBitmapPixelData = ^TglBitmapPixelData;
4122 with FuncRec do begin
4123 Dest.Data.r := Source.Data.r;
4124 Dest.Data.g := Source.Data.g;
4125 Dest.Data.b := Source.Data.b;
4127 with PglBitmapPixelData(Args)^ do
4128 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4129 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4130 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4133 Dest.Data.a := Dest.Range.a;
4137 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4138 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4140 with FuncRec do begin
4141 Dest.Data.r := Source.Data.r;
4142 Dest.Data.g := Source.Data.g;
4143 Dest.Data.b := Source.Data.b;
4144 Dest.Data.a := PCardinal(Args)^;
4148 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4149 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4152 TRGBPix = array [0..2] of byte;
4156 while aWidth > 0 do begin
4157 Temp := PRGBPix(aData)^[0];
4158 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4159 PRGBPix(aData)^[2] := Temp;
4169 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4170 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4171 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4172 function TglBitmap.GetFormatDesc: TglBitmapFormatDescriptor;
4174 result := TFormatDescriptor.Get(Format);
4177 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4178 function TglBitmap.GetWidth: Integer;
4180 if (ffX in fDimension.Fields) then
4181 result := fDimension.X
4186 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4187 function TglBitmap.GetHeight: Integer;
4189 if (ffY in fDimension.Fields) then
4190 result := fDimension.Y
4195 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4196 function TglBitmap.GetFileWidth: Integer;
4198 result := Max(1, Width);
4201 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4202 function TglBitmap.GetFileHeight: Integer;
4204 result := Max(1, Height);
4207 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4208 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4210 if fCustomData = aValue then
4212 fCustomData := aValue;
4215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4216 procedure TglBitmap.SetCustomName(const aValue: String);
4218 if fCustomName = aValue then
4220 fCustomName := aValue;
4223 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4224 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4226 if fCustomNameW = aValue then
4228 fCustomNameW := aValue;
4231 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4232 procedure TglBitmap.SetFreeDataOnDestroy(const aValue: Boolean);
4234 if fFreeDataOnDestroy = aValue then
4236 fFreeDataOnDestroy := aValue;
4239 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4240 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4242 if fDeleteTextureOnFree = aValue then
4244 fDeleteTextureOnFree := aValue;
4247 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4248 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4250 if fFormat = aValue then
4252 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4253 raise EglBitmapUnsupportedFormat.Create(Format);
4254 SetDataPointer(fData, aValue, Width, Height); //be careful, Data could be freed by this method
4257 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4258 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4260 if fFreeDataAfterGenTexture = aValue then
4262 fFreeDataAfterGenTexture := aValue;
4265 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4266 procedure TglBitmap.SetID(const aValue: Cardinal);
4268 if fID = aValue then
4273 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4274 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4276 if fMipMap = aValue then
4281 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4282 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4284 if fTarget = aValue then
4289 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4290 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4292 MaxAnisotropic: Integer;
4294 fAnisotropic := aValue;
4295 if (ID > 0) then begin
4296 if GL_EXT_texture_filter_anisotropic then begin
4297 if fAnisotropic > 0 then begin
4299 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4300 if aValue > MaxAnisotropic then
4301 fAnisotropic := MaxAnisotropic;
4302 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4310 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4311 procedure TglBitmap.CreateID;
4314 glDeleteTextures(1, @fID);
4315 glGenTextures(1, @fID);
4319 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4320 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4322 // Set Up Parameters
4323 SetWrap(fWrapS, fWrapT, fWrapR);
4324 SetFilter(fFilterMin, fFilterMag);
4325 SetAnisotropic(fAnisotropic);
4326 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4328 if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
4329 SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4331 // Mip Maps Generation Mode
4332 aBuildWithGlu := false;
4333 if (MipMap = mmMipmap) then begin
4334 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4335 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4337 aBuildWithGlu := true;
4338 end else if (MipMap = mmMipmapGlu) then
4339 aBuildWithGlu := true;
4342 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4343 procedure TglBitmap.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
4344 const aWidth: Integer; const aHeight: Integer);
4348 if (Data <> aData) then begin
4349 if (Assigned(Data)) then
4354 if not Assigned(fData) then begin
4358 FillChar(fDimension, SizeOf(fDimension), 0);
4359 if aWidth <> -1 then begin
4360 fDimension.Fields := fDimension.Fields + [ffX];
4361 fDimension.X := aWidth;
4364 if aHeight <> -1 then begin
4365 fDimension.Fields := fDimension.Fields + [ffY];
4366 fDimension.Y := aHeight;
4369 s := TFormatDescriptor.Get(aFormat).PixelSize;
4371 fPixelSize := Ceil(s);
4372 fRowSize := Ceil(s * aWidth);
4376 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4377 function TglBitmap.FlipHorz: Boolean;
4382 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4383 function TglBitmap.FlipVert: Boolean;
4388 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4389 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4390 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4391 procedure TglBitmap.AfterConstruction;
4393 inherited AfterConstruction;
4397 fIsResident := false;
4399 fMipMap := glBitmapDefaultMipmap;
4400 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4401 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4403 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4404 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4405 glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]);
4408 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4409 procedure TglBitmap.BeforeDestruction;
4413 if fFreeDataOnDestroy then begin
4415 SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
4417 if (fID > 0) and fDeleteTextureOnFree then
4418 glDeleteTextures(1, @fID);
4419 inherited BeforeDestruction;
4422 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4423 procedure TglBitmap.PrepareResType(var aResource: String; var aResType: PChar);
4427 if not Assigned(aResType) then begin
4428 TempPos := Pos('.', aResource);
4429 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4430 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4434 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4435 procedure TglBitmap.LoadFromFile(const aFilename: String);
4439 if not FileExists(aFilename) then
4440 raise EglBitmap.Create('file does not exist: ' + aFilename);
4441 fFilename := aFilename;
4442 fs := TFileStream.Create(fFilename, fmOpenRead);
4451 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4452 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4454 {$IFDEF GLB_SUPPORT_PNG_READ}
4455 if not LoadPNG(aStream) then
4457 {$IFDEF GLB_SUPPORT_JPEG_READ}
4458 if not LoadJPEG(aStream) then
4460 if not LoadDDS(aStream) then
4461 if not LoadTGA(aStream) then
4462 if not LoadBMP(aStream) then
4463 raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4466 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4467 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4468 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4473 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4474 GetMem(tmpData, size);
4476 FillChar(tmpData^, size, #$FF);
4477 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
4479 if Assigned(tmpData) then
4483 AddFunc(Self, aFunc, false, aFormat, aArgs);
4486 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4487 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
4489 rs: TResourceStream;
4491 PrepareResType(aResource, aResType);
4492 rs := TResourceStream.Create(aInstance, aResource, aResType);
4500 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4501 procedure TglBitmap.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4503 rs: TResourceStream;
4505 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
4513 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4514 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4518 fs := TFileStream.Create(aFileName, fmCreate);
4521 SaveToStream(fs, aFileType);
4527 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4528 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4531 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4532 ftPNG: SavePNG(aStream);
4534 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4535 ftJPEG: SaveJPEG(aStream);
4537 ftDDS: SaveDDS(aStream);
4538 ftTGA: SaveTGA(aStream);
4539 ftBMP: SaveBMP(aStream);
4543 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4544 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4546 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4549 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4550 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4551 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4553 DestData, TmpData, SourceData: pByte;
4554 TempHeight, TempWidth: Integer;
4555 SourceFD, DestFD: TFormatDescriptor;
4556 SourceMD, DestMD: Pointer;
4558 FuncRec: TglBitmapFunctionRec;
4560 Assert(Assigned(Data));
4561 Assert(Assigned(aSource));
4562 Assert(Assigned(aSource.Data));
4565 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4566 SourceFD := TFormatDescriptor.Get(aSource.Format);
4567 DestFD := TFormatDescriptor.Get(aFormat);
4569 if (SourceFD.IsCompressed) then
4570 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
4571 if (DestFD.IsCompressed) then
4572 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
4574 // inkompatible Formats so CreateTemp
4575 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4576 aCreateTemp := true;
4579 TempHeight := Max(1, aSource.Height);
4580 TempWidth := Max(1, aSource.Width);
4582 FuncRec.Sender := Self;
4583 FuncRec.Args := aArgs;
4586 if aCreateTemp then begin
4587 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
4588 DestData := TmpData;
4593 SourceFD.PreparePixel(FuncRec.Source);
4594 DestFD.PreparePixel (FuncRec.Dest);
4596 SourceMD := SourceFD.CreateMappingData;
4597 DestMD := DestFD.CreateMappingData;
4599 FuncRec.Size := aSource.Dimension;
4600 FuncRec.Position.Fields := FuncRec.Size.Fields;
4603 SourceData := aSource.Data;
4604 FuncRec.Position.Y := 0;
4605 while FuncRec.Position.Y < TempHeight do begin
4606 FuncRec.Position.X := 0;
4607 while FuncRec.Position.X < TempWidth do begin
4608 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4610 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4611 inc(FuncRec.Position.X);
4613 inc(FuncRec.Position.Y);
4616 // Updating Image or InternalFormat
4618 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) //be careful, Data could be freed by this method
4619 else if (aFormat <> fFormat) then
4624 SourceFD.FreeMappingData(SourceMD);
4625 DestFD.FreeMappingData(DestMD);
4628 if aCreateTemp and Assigned(TmpData) then
4636 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4637 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4639 Row, RowSize: Integer;
4640 SourceData, TmpData: PByte;
4642 FormatDesc: TFormatDescriptor;
4644 function GetRowPointer(Row: Integer): pByte;
4646 result := aSurface.pixels;
4647 Inc(result, Row * RowSize);
4653 FormatDesc := TFormatDescriptor.Get(Format);
4654 if FormatDesc.IsCompressed then
4655 raise EglBitmapUnsupportedFormat.Create(Format);
4657 if Assigned(Data) then begin
4658 case Trunc(FormatDesc.PixelSize) of
4664 raise EglBitmapUnsupportedFormat.Create(Format);
4667 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4668 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4670 RowSize := FormatDesc.GetSize(FileWidth, 1);
4672 for Row := 0 to FileHeight-1 do begin
4673 TmpData := GetRowPointer(Row);
4674 if Assigned(TmpData) then begin
4675 Move(SourceData^, TmpData^, RowSize);
4676 inc(SourceData, RowSize);
4683 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4684 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4686 pSource, pData, pTempData: PByte;
4687 Row, RowSize, TempWidth, TempHeight: Integer;
4688 IntFormat: TglBitmapFormat;
4689 FormatDesc: TFormatDescriptor;
4691 function GetRowPointer(Row: Integer): pByte;
4693 result := aSurface^.pixels;
4694 Inc(result, Row * RowSize);
4699 if (Assigned(aSurface)) then begin
4700 with aSurface^.format^ do begin
4701 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4702 FormatDesc := TFormatDescriptor.Get(IntFormat);
4703 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4706 if (IntFormat = tfEmpty) then
4707 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4710 TempWidth := aSurface^.w;
4711 TempHeight := aSurface^.h;
4712 RowSize := FormatDesc.GetSize(TempWidth, 1);
4713 GetMem(pData, TempHeight * RowSize);
4716 for Row := 0 to TempHeight -1 do begin
4717 pSource := GetRowPointer(Row);
4718 if (Assigned(pSource)) then begin
4719 Move(pSource^, pTempData^, RowSize);
4720 Inc(pTempData, RowSize);
4723 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4726 if Assigned(pData) then
4733 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4734 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4736 Row, Col, AlphaInterleave: Integer;
4737 pSource, pDest: PByte;
4739 function GetRowPointer(Row: Integer): pByte;
4741 result := aSurface.pixels;
4742 Inc(result, Row * Width);
4747 if Assigned(Data) then begin
4748 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4749 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4751 AlphaInterleave := 0;
4754 AlphaInterleave := 1;
4756 AlphaInterleave := 3;
4760 for Row := 0 to Height -1 do begin
4761 pDest := GetRowPointer(Row);
4762 if Assigned(pDest) then begin
4763 for Col := 0 to Width -1 do begin
4764 Inc(pSource, AlphaInterleave);
4776 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4777 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4781 bmp := TglBitmap2D.Create;
4783 bmp.AssignFromSurface(aSurface);
4784 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4792 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4793 function CreateGrayPalette: HPALETTE;
4798 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
4800 Pal.palVersion := $300;
4801 Pal.palNumEntries := 256;
4803 for Idx := 0 to Pal.palNumEntries - 1 do begin
4804 Pal.palPalEntry[Idx].peRed := Idx;
4805 Pal.palPalEntry[Idx].peGreen := Idx;
4806 Pal.palPalEntry[Idx].peBlue := Idx;
4807 Pal.palPalEntry[Idx].peFlags := 0;
4809 Result := CreatePalette(Pal^);
4813 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4814 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4817 pSource, pData: PByte;
4820 if Assigned(Data) then begin
4821 if Assigned(aBitmap) then begin
4822 aBitmap.Width := Width;
4823 aBitmap.Height := Height;
4826 tfAlpha8, tfLuminance8: begin
4827 aBitmap.PixelFormat := pf8bit;
4828 aBitmap.Palette := CreateGrayPalette;
4831 aBitmap.PixelFormat := pf15bit;
4833 aBitmap.PixelFormat := pf16bit;
4835 aBitmap.PixelFormat := pf24bit;
4837 aBitmap.PixelFormat := pf32bit;
4839 raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.');
4843 for Row := 0 to FileHeight -1 do begin
4844 pData := aBitmap.Scanline[Row];
4845 Move(pSource^, pData^, fRowSize);
4846 Inc(pSource, fRowSize);
4847 if (Format in [tfRGB8, tfRGBA8]) then // swap RGB(A) to BGR(A)
4848 SwapRGB(pData, FileWidth, Format = tfRGBA8);
4855 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4856 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4858 pSource, pData, pTempData: PByte;
4859 Row, RowSize, TempWidth, TempHeight: Integer;
4860 IntFormat: TglBitmapFormat;
4864 if (Assigned(aBitmap)) then begin
4865 case aBitmap.PixelFormat of
4867 IntFormat := tfLuminance8;
4869 IntFormat := tfRGB5A1;
4871 IntFormat := tfR5G6B5;
4873 IntFormat := tfBGR8;
4875 IntFormat := tfBGRA8;
4877 raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.');
4880 TempWidth := aBitmap.Width;
4881 TempHeight := aBitmap.Height;
4882 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
4883 GetMem(pData, TempHeight * RowSize);
4886 for Row := 0 to TempHeight -1 do begin
4887 pSource := aBitmap.Scanline[Row];
4888 if (Assigned(pSource)) then begin
4889 Move(pSource^, pTempData^, RowSize);
4890 Inc(pTempData, RowSize);
4893 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4896 if Assigned(pData) then
4903 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4904 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4906 Row, Col, AlphaInterleave: Integer;
4907 pSource, pDest: PByte;
4911 if Assigned(Data) then begin
4912 if (Format in [tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8]) then begin
4913 if Assigned(aBitmap) then begin
4914 aBitmap.PixelFormat := pf8bit;
4915 aBitmap.Palette := CreateGrayPalette;
4916 aBitmap.Width := Width;
4917 aBitmap.Height := Height;
4921 AlphaInterleave := 1;
4923 AlphaInterleave := 3;
4925 AlphaInterleave := 0;
4931 for Row := 0 to Height -1 do begin
4932 pDest := aBitmap.Scanline[Row];
4933 if Assigned(pDest) then begin
4934 for Col := 0 to Width -1 do begin
4935 Inc(pSource, AlphaInterleave);
4948 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4949 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4953 tex := TglBitmap2D.Create;
4955 tex.AssignFromBitmap(ABitmap);
4956 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4963 {$IFDEF GLB_LAZARUS}
4964 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4965 function TglBitmap.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4967 rid: TRawImageDescription;
4968 FormatDesc: TFormatDescriptor;
4971 if not Assigned(aImage) or (Format = tfEmpty) then
4973 FormatDesc := TFormatDescriptor.Get(Format);
4974 if FormatDesc.IsCompressed then
4977 FillChar(rid{%H-}, SizeOf(rid), 0);
4979 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
4980 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
4981 tfLuminance4Alpha4, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16]) then
4982 rid.Format := ricfGray
4984 rid.Format := ricfRGBA;
4987 rid.Height := Height;
4988 rid.Depth := CountSetBits(FormatDesc.RedMask or FormatDesc.GreenMask or FormatDesc.BlueMask or FormatDesc.AlphaMask);
4989 rid.BitOrder := riboBitsInOrder;
4990 rid.ByteOrder := riboLSBFirst;
4991 rid.LineOrder := riloTopToBottom;
4992 rid.LineEnd := rileTight;
4993 rid.BitsPerPixel := Round(8 * FormatDesc.PixelSize);
4994 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
4995 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
4996 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
4997 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
4998 rid.RedShift := FormatDesc.Shift.r;
4999 rid.GreenShift := FormatDesc.Shift.g;
5000 rid.BlueShift := FormatDesc.Shift.b;
5001 rid.AlphaShift := FormatDesc.Shift.a;
5003 rid.MaskBitsPerPixel := 0;
5004 rid.PaletteColorCount := 0;
5006 aImage.DataDescription := rid;
5009 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
5014 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5015 function TglBitmap.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
5018 FormatDesc: TFormatDescriptor;
5023 procedure CopyConvert;
5025 bfFormat: TbmpBitfieldFormat;
5026 pSourceLine, pDestLine: PByte;
5027 pSourceMD, pDestMD: Pointer;
5029 pixel: TglBitmapPixelData;
5031 bfFormat := TbmpBitfieldFormat.Create;
5032 with aImage.DataDescription do begin
5033 bfFormat.RedMask := ((1 shl RedPrec) - 1) shl RedShift;
5034 bfFormat.GreenMask := ((1 shl GreenPrec) - 1) shl GreenShift;
5035 bfFormat.BlueMask := ((1 shl BluePrec) - 1) shl BlueShift;
5036 bfFormat.AlphaMask := ((1 shl AlphaPrec) - 1) shl AlphaShift;
5037 bfFormat.PixelSize := BitsPerPixel / 8;
5039 pSourceMD := bfFormat.CreateMappingData;
5040 pDestMD := FormatDesc.CreateMappingData;
5042 for y := 0 to aImage.Height-1 do begin
5043 pSourceLine := aImage.PixelData + y {%H-}* aImage.DataDescription.BytesPerLine;
5044 pDestLine := ImageData + y * Round(FormatDesc.PixelSize * aImage.Width);
5045 for x := 0 to aImage.Width-1 do begin
5046 bfFormat.Unmap(pSourceLine, pixel, pSourceMD);
5047 FormatDesc.Map(pixel, pDestLine, pDestMD);
5051 FormatDesc.FreeMappingData(pDestMD);
5052 bfFormat.FreeMappingData(pSourceMD);
5059 if not Assigned(aImage) then
5061 for f := High(f) downto Low(f) do begin
5062 FormatDesc := TFormatDescriptor.Get(f);
5063 with aImage.DataDescription do
5064 if FormatDesc.MaskMatch(
5065 (QWord(1 shl RedPrec )-1) shl RedShift,
5066 (QWord(1 shl GreenPrec)-1) shl GreenShift,
5067 (QWord(1 shl BluePrec )-1) shl BlueShift,
5068 (QWord(1 shl AlphaPrec)-1) shl AlphaShift) then
5072 if (f = tfEmpty) then
5076 (Round(FormatDesc.PixelSize * 8) = aImage.DataDescription.Depth) and
5077 (aImage.DataDescription.BitsPerPixel = aImage.DataDescription.Depth);
5079 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
5080 ImageData := GetMem(ImageSize);
5083 Move(aImage.PixelData^, ImageData^, ImageSize)
5086 SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method
5088 if Assigned(ImageData) then
5096 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5097 function TglBitmap.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
5099 rid: TRawImageDescription;
5100 FormatDesc: TFormatDescriptor;
5101 Pixel: TglBitmapPixelData;
5107 if not Assigned(aImage) or (Format = tfEmpty) then
5109 FormatDesc := TFormatDescriptor.Get(Format);
5110 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5113 FillChar(rid{%H-}, SizeOf(rid), 0);
5114 rid.Format := ricfGray;
5116 rid.Height := Height;
5117 rid.Depth := CountSetBits(FormatDesc.Range.a);
5118 rid.BitOrder := riboBitsInOrder;
5119 rid.ByteOrder := riboLSBFirst;
5120 rid.LineOrder := riloTopToBottom;
5121 rid.LineEnd := rileTight;
5122 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
5123 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
5128 rid.GreenShift := 0;
5130 rid.AlphaShift := 0;
5132 rid.MaskBitsPerPixel := 0;
5133 rid.PaletteColorCount := 0;
5135 aImage.DataDescription := rid;
5138 srcMD := FormatDesc.CreateMappingData;
5140 FormatDesc.PreparePixel(Pixel);
5142 dst := aImage.PixelData;
5143 for y := 0 to Height-1 do
5144 for x := 0 to Width-1 do begin
5145 FormatDesc.Unmap(src, Pixel, srcMD);
5146 case rid.BitsPerPixel of
5148 dst^ := Pixel.Data.a;
5152 PWord(dst)^ := Pixel.Data.a;
5156 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
5157 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
5158 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
5162 PCardinal(dst)^ := Pixel.Data.a;
5166 raise EglBitmapUnsupportedFormat.Create(Format);
5170 FormatDesc.FreeMappingData(srcMD);
5175 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5176 function TglBitmap.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5180 tex := TglBitmap2D.Create;
5182 tex.AssignFromLazIntfImage(aImage);
5183 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5190 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5191 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
5192 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5194 rs: TResourceStream;
5196 PrepareResType(aResource, aResType);
5197 rs := TResourceStream.Create(aInstance, aResource, aResType);
5199 result := AddAlphaFromStream(rs, aFunc, aArgs);
5205 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5206 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
5207 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5209 rs: TResourceStream;
5211 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
5213 result := AddAlphaFromStream(rs, aFunc, aArgs);
5219 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5220 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5222 if TFormatDescriptor.Get(Format).IsCompressed then
5223 raise EglBitmapUnsupportedFormat.Create(Format);
5224 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
5227 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5228 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5232 FS := TFileStream.Create(aFileName, fmOpenRead);
5234 result := AddAlphaFromStream(FS, aFunc, aArgs);
5240 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5241 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5245 tex := TglBitmap2D.Create(aStream);
5247 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5253 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5254 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5256 DestData, DestData2, SourceData: pByte;
5257 TempHeight, TempWidth: Integer;
5258 SourceFD, DestFD: TFormatDescriptor;
5259 SourceMD, DestMD, DestMD2: Pointer;
5261 FuncRec: TglBitmapFunctionRec;
5265 Assert(Assigned(Data));
5266 Assert(Assigned(aBitmap));
5267 Assert(Assigned(aBitmap.Data));
5269 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
5270 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
5272 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
5273 DestFD := TFormatDescriptor.Get(Format);
5275 if not Assigned(aFunc) then begin
5276 aFunc := glBitmapAlphaFunc;
5277 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5279 FuncRec.Args := aArgs;
5282 TempHeight := aBitmap.FileHeight;
5283 TempWidth := aBitmap.FileWidth;
5285 FuncRec.Sender := Self;
5286 FuncRec.Size := Dimension;
5287 FuncRec.Position.Fields := FuncRec.Size.Fields;
5291 SourceData := aBitmap.Data;
5294 SourceFD.PreparePixel(FuncRec.Source);
5295 DestFD.PreparePixel (FuncRec.Dest);
5297 SourceMD := SourceFD.CreateMappingData;
5298 DestMD := DestFD.CreateMappingData;
5299 DestMD2 := DestFD.CreateMappingData;
5301 FuncRec.Position.Y := 0;
5302 while FuncRec.Position.Y < TempHeight do begin
5303 FuncRec.Position.X := 0;
5304 while FuncRec.Position.X < TempWidth do begin
5305 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5306 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5308 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5309 inc(FuncRec.Position.X);
5311 inc(FuncRec.Position.Y);
5314 SourceFD.FreeMappingData(SourceMD);
5315 DestFD.FreeMappingData(DestMD);
5316 DestFD.FreeMappingData(DestMD2);
5321 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5322 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5324 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5327 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5328 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5330 PixelData: TglBitmapPixelData;
5332 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5333 result := AddAlphaFromColorKeyFloat(
5334 aRed / PixelData.Range.r,
5335 aGreen / PixelData.Range.g,
5336 aBlue / PixelData.Range.b,
5337 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5340 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5341 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5343 values: array[0..2] of Single;
5346 PixelData: TglBitmapPixelData;
5348 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5349 with PixelData do begin
5351 values[1] := aGreen;
5354 for i := 0 to 2 do begin
5355 tmp := Trunc(Range.arr[i] * aDeviation);
5356 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5357 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5362 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5365 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5366 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5368 result := AddAlphaFromValueFloat(aAlpha / $FF);
5371 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5372 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5374 PixelData: TglBitmapPixelData;
5376 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5377 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5380 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5381 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5383 PixelData: TglBitmapPixelData;
5385 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5387 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5388 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5391 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5392 function TglBitmap.RemoveAlpha: Boolean;
5394 FormatDesc: TFormatDescriptor;
5397 FormatDesc := TFormatDescriptor.Get(Format);
5398 if Assigned(Data) then begin
5399 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5400 raise EglBitmapUnsupportedFormat.Create(Format);
5401 result := ConvertTo(FormatDesc.WithoutAlpha);
5405 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5406 function TglBitmap.Clone: TglBitmap;
5413 Temp := (ClassType.Create as TglBitmap);
5415 // copy texture data if assigned
5416 if Assigned(Data) then begin
5417 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5418 GetMem(TempPtr, Size);
5420 Move(Data^, TempPtr^, Size);
5421 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5423 if Assigned(TempPtr) then
5429 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5434 Temp.fTarget := Target;
5435 Temp.fFormat := Format;
5436 Temp.fMipMap := MipMap;
5437 Temp.fAnisotropic := Anisotropic;
5438 Temp.fBorderColor := fBorderColor;
5439 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5440 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5441 Temp.fFilterMin := fFilterMin;
5442 Temp.fFilterMag := fFilterMag;
5443 Temp.fWrapS := fWrapS;
5444 Temp.fWrapT := fWrapT;
5445 Temp.fWrapR := fWrapR;
5446 Temp.fFilename := fFilename;
5447 Temp.fCustomName := fCustomName;
5448 Temp.fCustomNameW := fCustomNameW;
5449 Temp.fCustomData := fCustomData;
5458 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5459 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5461 SourceFD, DestFD: TFormatDescriptor;
5462 SourcePD, DestPD: TglBitmapPixelData;
5463 ShiftData: TShiftData;
5465 function CanCopyDirect: Boolean;
5468 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5469 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5470 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5471 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5474 function CanShift: Boolean;
5477 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5478 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5479 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5480 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5483 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5486 while (aSource > aDest) and (aSource > 0) do begin
5488 aSource := aSource shr 1;
5493 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5494 SourceFD := TFormatDescriptor.Get(Format);
5495 DestFD := TFormatDescriptor.Get(aFormat);
5497 SourceFD.PreparePixel(SourcePD);
5498 DestFD.PreparePixel (DestPD);
5500 if CanCopyDirect then
5501 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5502 else if CanShift then begin
5503 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5504 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5505 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5506 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5507 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5509 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5514 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5515 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5517 if aUseRGB or aUseAlpha then
5518 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5519 ((Byte(aUseAlpha) and 1) shl 1) or
5520 (Byte(aUseRGB) and 1) ));
5523 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5524 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5526 fBorderColor[0] := aRed;
5527 fBorderColor[1] := aGreen;
5528 fBorderColor[2] := aBlue;
5529 fBorderColor[3] := aAlpha;
5530 if (ID > 0) then begin
5532 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5536 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5537 procedure TglBitmap.FreeData;
5542 SetDataPointer(TempPtr, tfEmpty); //be careful, Data could be freed by this method
5545 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5546 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5547 const aAlpha: Byte);
5549 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5552 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5553 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5555 PixelData: TglBitmapPixelData;
5557 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5559 aRed / PixelData.Range.r,
5560 aGreen / PixelData.Range.g,
5561 aBlue / PixelData.Range.b,
5562 aAlpha / PixelData.Range.a);
5565 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5566 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5568 PixelData: TglBitmapPixelData;
5570 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5571 with PixelData do begin
5572 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5573 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5574 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5575 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5577 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5580 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5581 procedure TglBitmap.SetFilter(const aMin, aMag: GLenum);
5586 fFilterMin := GL_NEAREST;
5588 fFilterMin := GL_LINEAR;
5589 GL_NEAREST_MIPMAP_NEAREST:
5590 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5591 GL_LINEAR_MIPMAP_NEAREST:
5592 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5593 GL_NEAREST_MIPMAP_LINEAR:
5594 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5595 GL_LINEAR_MIPMAP_LINEAR:
5596 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5598 raise EglBitmap.Create('SetFilter - Unknow MIN filter.');
5604 fFilterMag := GL_NEAREST;
5606 fFilterMag := GL_LINEAR;
5608 raise EglBitmap.Create('SetFilter - Unknow MAG filter.');
5612 if (ID > 0) then begin
5614 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5616 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5618 GL_NEAREST, GL_LINEAR:
5619 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5620 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5621 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5622 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5623 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5626 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5630 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5631 procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum);
5633 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5637 aTarget := GL_CLAMP;
5640 aTarget := GL_REPEAT;
5642 GL_CLAMP_TO_EDGE: begin
5643 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5644 aTarget := GL_CLAMP_TO_EDGE
5646 aTarget := GL_CLAMP;
5649 GL_CLAMP_TO_BORDER: begin
5650 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5651 aTarget := GL_CLAMP_TO_BORDER
5653 aTarget := GL_CLAMP;
5656 GL_MIRRORED_REPEAT: begin
5657 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5658 aTarget := GL_MIRRORED_REPEAT
5660 raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5663 raise EglBitmap.Create('SetWrap - Unknow Texturewrap');
5668 CheckAndSetWrap(S, fWrapS);
5669 CheckAndSetWrap(T, fWrapT);
5670 CheckAndSetWrap(R, fWrapR);
5672 if (ID > 0) then begin
5674 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5675 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5676 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5680 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5681 procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum);
5683 procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer);
5685 if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or
5686 (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then
5687 fSwizzle[aIndex] := aValue
5689 raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value');
5693 if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then
5694 raise EglBitmapNotSupported.Create('texture swizzle is not supported');
5695 CheckAndSetValue(r, 0);
5696 CheckAndSetValue(g, 1);
5697 CheckAndSetValue(b, 2);
5698 CheckAndSetValue(a, 3);
5700 if (ID > 0) then begin
5702 glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, PGLint(@fSwizzle[0]));
5706 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5707 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5709 if aEnableTextureUnit then
5712 glBindTexture(Target, ID);
5715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5716 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5718 if aDisableTextureUnit then
5720 glBindTexture(Target, 0);
5723 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5724 constructor TglBitmap.Create;
5726 if (ClassType = TglBitmap) then
5727 raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5728 {$IFDEF GLB_NATIVE_OGL}
5729 glbReadOpenGLExtensions;
5732 fFormat := glBitmapGetDefaultFormat;
5733 fFreeDataOnDestroy := true;
5736 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5737 constructor TglBitmap.Create(const aFileName: String);
5740 LoadFromFile(aFileName);
5743 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5744 constructor TglBitmap.Create(const aStream: TStream);
5747 LoadFromStream(aStream);
5750 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5751 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte);
5756 if not Assigned(aData) then begin
5757 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5758 GetMem(aData, ImageSize);
5760 FillChar(aData^, ImageSize, #$FF);
5761 SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5763 if Assigned(aData) then
5768 SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5769 fFreeDataOnDestroy := false;
5773 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5774 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer);
5777 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5780 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5781 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5784 LoadFromResource(aInstance, aResource, aResType);
5787 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5788 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5791 LoadFromResourceID(aInstance, aResourceID, aResType);
5794 {$IFDEF GLB_SUPPORT_PNG_READ}
5795 {$IF DEFINED(GLB_LAZ_PNG)}
5796 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5797 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5798 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5799 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5802 PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A;
5804 reader: TLazReaderPNG;
5805 intf: TLazIntfImage;
5807 magic: String[MAGIC_LEN];
5810 StreamPos := aStream.Position;
5812 SetLength(magic, MAGIC_LEN);
5813 aStream.Read(magic[1], MAGIC_LEN);
5814 aStream.Position := StreamPos;
5815 if (magic <> PNG_MAGIC) then begin
5820 intf := TLazIntfImage.Create(0, 0);
5821 reader := TLazReaderPNG.Create;
5823 reader.UpdateDescription := true;
5824 reader.ImageRead(aStream, intf);
5825 AssignFromLazIntfImage(intf);
5828 aStream.Position := StreamPos;
5837 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
5838 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5839 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5841 Surface: PSDL_Surface;
5845 RWops := glBitmapCreateRWops(aStream);
5847 if IMG_isPNG(RWops) > 0 then begin
5848 Surface := IMG_LoadPNG_RW(RWops);
5850 AssignFromSurface(Surface);
5853 SDL_FreeSurface(Surface);
5861 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5862 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5863 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5865 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5868 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5869 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5872 signature: array [0..7] of byte;
5874 png_info: png_infop;
5876 TempHeight, TempWidth: Integer;
5877 Format: TglBitmapFormat;
5880 png_rows: array of pByte;
5881 Row, LineSize: Integer;
5885 if not init_libPNG then
5886 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5890 StreamPos := aStream.Position;
5891 aStream.Read(signature{%H-}, 8);
5892 aStream.Position := StreamPos;
5894 if png_check_sig(@signature, 8) <> 0 then begin
5896 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5898 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5901 png_info := png_create_info_struct(png);
5902 if png_info = nil then begin
5903 png_destroy_read_struct(@png, nil, nil);
5904 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5907 // set read callback
5908 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5910 // read informations
5911 png_read_info(png, png_info);
5914 TempHeight := png_get_image_height(png, png_info);
5915 TempWidth := png_get_image_width(png, png_info);
5918 case png_get_color_type(png, png_info) of
5919 PNG_COLOR_TYPE_GRAY:
5920 Format := tfLuminance8;
5921 PNG_COLOR_TYPE_GRAY_ALPHA:
5922 Format := tfLuminance8Alpha8;
5925 PNG_COLOR_TYPE_RGB_ALPHA:
5928 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5931 // cut upper 8 bit from 16 bit formats
5932 if png_get_bit_depth(png, png_info) > 8 then
5933 png_set_strip_16(png);
5935 // expand bitdepth smaller than 8
5936 if png_get_bit_depth(png, png_info) < 8 then
5937 png_set_expand(png);
5939 // allocating mem for scanlines
5940 LineSize := png_get_rowbytes(png, png_info);
5941 GetMem(png_data, TempHeight * LineSize);
5943 SetLength(png_rows, TempHeight);
5944 for Row := Low(png_rows) to High(png_rows) do begin
5945 png_rows[Row] := png_data;
5946 Inc(png_rows[Row], Row * LineSize);
5949 // read complete image into scanlines
5950 png_read_image(png, @png_rows[0]);
5953 png_read_end(png, png_info);
5955 // destroy read struct
5956 png_destroy_read_struct(@png, @png_info, nil);
5958 SetLength(png_rows, 0);
5961 SetDataPointer(png_data, Format, TempWidth, TempHeight); //be careful, Data could be freed by this method
5965 if Assigned(png_data) then
5975 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5976 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5977 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5982 Row, Col, PixSize, LineSize: Integer;
5983 NewImage, pSource, pDest, pAlpha: pByte;
5984 PngFormat: TglBitmapFormat;
5985 FormatDesc: TFormatDescriptor;
5988 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
5993 StreamPos := aStream.Position;
5994 aStream.Read(Header[0], SizeOf(Header));
5995 aStream.Position := StreamPos;
5997 {Test if the header matches}
5998 if Header = PngHeader then begin
5999 Png := TPNGObject.Create;
6001 Png.LoadFromStream(aStream);
6003 case Png.Header.ColorType of
6005 PngFormat := tfLuminance8;
6006 COLOR_GRAYSCALEALPHA:
6007 PngFormat := tfLuminance8Alpha8;
6009 PngFormat := tfBGR8;
6011 PngFormat := tfBGRA8;
6013 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
6016 FormatDesc := TFormatDescriptor.Get(PngFormat);
6017 PixSize := Round(FormatDesc.PixelSize);
6018 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
6020 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
6024 case Png.Header.ColorType of
6025 COLOR_RGB, COLOR_GRAYSCALE:
6027 for Row := 0 to Png.Height -1 do begin
6028 Move (Png.Scanline[Row]^, pDest^, LineSize);
6029 Inc(pDest, LineSize);
6032 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
6034 PixSize := PixSize -1;
6036 for Row := 0 to Png.Height -1 do begin
6037 pSource := Png.Scanline[Row];
6038 pAlpha := pByte(Png.AlphaScanline[Row]);
6040 for Col := 0 to Png.Width -1 do begin
6041 Move (pSource^, pDest^, PixSize);
6042 Inc(pSource, PixSize);
6043 Inc(pDest, PixSize);
6052 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
6055 SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); //be careful, Data could be freed by this method
6059 if Assigned(NewImage) then
6071 {$IFDEF GLB_SUPPORT_PNG_WRITE}
6072 {$IFDEF GLB_LIB_PNG}
6073 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6074 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
6076 TStream(png_get_io_ptr(png)).Write(buffer^, size);
6080 {$IF DEFINED(GLB_LAZ_PNG)}
6081 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6082 procedure TglBitmap.SavePNG(const aStream: TStream);
6084 png: TPortableNetworkGraphic;
6085 intf: TLazIntfImage;
6088 png := TPortableNetworkGraphic.Create;
6089 intf := TLazIntfImage.Create(0, 0);
6091 if not AssignToLazIntfImage(intf) then
6092 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6093 intf.GetRawImage(raw);
6094 png.LoadFromRawImage(raw, false);
6095 png.SaveToStream(aStream);
6102 {$ELSEIF DEFINED(GLB_LIB_PNG)}
6103 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6104 procedure TglBitmap.SavePNG(const aStream: TStream);
6107 png_info: png_infop;
6108 png_rows: array of pByte;
6112 FormatDesc: TFormatDescriptor;
6114 if not (ftPNG in FormatGetSupportedFiles(Format)) then
6115 raise EglBitmapUnsupportedFormat.Create(Format);
6117 if not init_libPNG then
6118 raise Exception.Create('unable to initialize libPNG.');
6122 tfAlpha8, tfLuminance8:
6123 ColorType := PNG_COLOR_TYPE_GRAY;
6125 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
6127 ColorType := PNG_COLOR_TYPE_RGB;
6129 ColorType := PNG_COLOR_TYPE_RGBA;
6131 raise EglBitmapUnsupportedFormat.Create(Format);
6134 FormatDesc := TFormatDescriptor.Get(Format);
6135 LineSize := FormatDesc.GetSize(Width, 1);
6137 // creating array for scanline
6138 SetLength(png_rows, Height);
6140 for Row := 0 to Height - 1 do begin
6141 png_rows[Row] := Data;
6142 Inc(png_rows[Row], Row * LineSize)
6146 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
6148 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
6151 png_info := png_create_info_struct(png);
6152 if png_info = nil then begin
6153 png_destroy_write_struct(@png, nil);
6154 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
6157 // set read callback
6158 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
6161 png_set_compression_level(png, 6);
6163 if Format in [tfBGR8, tfBGRA8] then
6166 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
6167 png_write_info(png, png_info);
6168 png_write_image(png, @png_rows[0]);
6169 png_write_end(png, png_info);
6170 png_destroy_write_struct(@png, @png_info);
6172 SetLength(png_rows, 0);
6179 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
6180 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6181 procedure TglBitmap.SavePNG(const aStream: TStream);
6185 pSource, pDest: pByte;
6186 X, Y, PixSize: Integer;
6187 ColorType: Cardinal;
6193 if not (ftPNG in FormatGetSupportedFiles (Format)) then
6194 raise EglBitmapUnsupportedFormat.Create(Format);
6197 tfAlpha8, tfLuminance8: begin
6198 ColorType := COLOR_GRAYSCALE;
6202 tfLuminance8Alpha8: begin
6203 ColorType := COLOR_GRAYSCALEALPHA;
6207 tfBGR8, tfRGB8: begin
6208 ColorType := COLOR_RGB;
6212 tfBGRA8, tfRGBA8: begin
6213 ColorType := COLOR_RGBALPHA;
6218 raise EglBitmapUnsupportedFormat.Create(Format);
6221 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
6225 for Y := 0 to Height -1 do begin
6226 pDest := png.ScanLine[Y];
6227 for X := 0 to Width -1 do begin
6228 Move(pSource^, pDest^, PixSize);
6229 Inc(pDest, PixSize);
6230 Inc(pSource, PixSize);
6232 png.AlphaScanline[Y]^[X] := pSource^;
6237 // convert RGB line to BGR
6238 if Format in [tfRGB8, tfRGBA8] then begin
6239 pTemp := png.ScanLine[Y];
6240 for X := 0 to Width -1 do begin
6241 Temp := pByteArray(pTemp)^[0];
6242 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
6243 pByteArray(pTemp)^[2] := Temp;
6250 Png.CompressionLevel := 6;
6251 Png.SaveToStream(aStream);
6259 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6260 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6261 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6262 {$IFDEF GLB_LIB_JPEG}
6264 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
6265 glBitmap_libJPEG_source_mgr = record
6266 pub: jpeg_source_mgr;
6269 SrcBuffer: array [1..4096] of byte;
6272 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
6273 glBitmap_libJPEG_dest_mgr = record
6274 pub: jpeg_destination_mgr;
6276 DestStream: TStream;
6277 DestBuffer: array [1..4096] of byte;
6280 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
6286 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
6292 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
6297 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
6303 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
6309 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6310 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
6312 src: glBitmap_libJPEG_source_mgr_ptr;
6315 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6317 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
6318 if (bytes <= 0) then begin
6319 src^.SrcBuffer[1] := $FF;
6320 src^.SrcBuffer[2] := JPEG_EOI;
6324 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
6325 src^.pub.bytes_in_buffer := bytes;
6330 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6331 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
6333 src: glBitmap_libJPEG_source_mgr_ptr;
6335 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
6337 if num_bytes > 0 then begin
6338 // wanted byte isn't in buffer so set stream position and read buffer
6339 if num_bytes > src^.pub.bytes_in_buffer then begin
6340 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
6341 src^.pub.fill_input_buffer(cinfo);
6343 // wanted byte is in buffer so only skip
6344 inc(src^.pub.next_input_byte, num_bytes);
6345 dec(src^.pub.bytes_in_buffer, num_bytes);
6350 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6351 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
6353 dest: glBitmap_libJPEG_dest_mgr_ptr;
6355 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6357 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
6358 // write complete buffer
6359 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
6362 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
6363 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
6369 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6370 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
6373 dest: glBitmap_libJPEG_dest_mgr_ptr;
6375 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6377 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6378 // check for endblock
6379 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6381 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6386 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6391 {$IFDEF GLB_SUPPORT_JPEG_READ}
6392 {$IF DEFINED(GLB_LAZ_JPEG)}
6393 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6394 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6397 JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
6399 intf: TLazIntfImage;
6400 reader: TFPReaderJPEG;
6402 magic: String[MAGIC_LEN];
6405 StreamPos := aStream.Position;
6407 SetLength(magic, MAGIC_LEN);
6408 aStream.Read(magic[1], MAGIC_LEN);
6409 aStream.Position := StreamPos;
6410 if (magic <> JPEG_MAGIC) then begin
6415 reader := TFPReaderJPEG.Create;
6416 intf := TLazIntfImage.Create(0, 0);
6418 intf.DataDescription := GetDescriptionFromDevice(0, 0, 0);
6419 reader.ImageRead(aStream, intf);
6420 AssignFromLazIntfImage(intf);
6423 aStream.Position := StreamPos;
6432 {$ELSEIF DEFINED(GLB_SDL_IMAGE)}
6433 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6434 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6436 Surface: PSDL_Surface;
6441 RWops := glBitmapCreateRWops(aStream);
6443 if IMG_isJPG(RWops) > 0 then begin
6444 Surface := IMG_LoadJPG_RW(RWops);
6446 AssignFromSurface(Surface);
6449 SDL_FreeSurface(Surface);
6457 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6458 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6459 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6462 Temp: array[0..1]of Byte;
6464 jpeg: jpeg_decompress_struct;
6465 jpeg_err: jpeg_error_mgr;
6467 IntFormat: TglBitmapFormat;
6469 TempHeight, TempWidth: Integer;
6474 FormatDesc: TFormatDescriptor;
6478 if not init_libJPEG then
6479 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6482 // reading first two bytes to test file and set cursor back to begin
6483 StreamPos := aStream.Position;
6484 aStream.Read({%H-}Temp[0], 2);
6485 aStream.Position := StreamPos;
6487 // if Bitmap then read file.
6488 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6489 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6490 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6493 jpeg.err := jpeg_std_error(@jpeg_err);
6494 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6495 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6497 // decompression struct
6498 jpeg_create_decompress(@jpeg);
6500 // allocation space for streaming methods
6501 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6503 // seeting up custom functions
6504 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6505 pub.init_source := glBitmap_libJPEG_init_source;
6506 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6507 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6508 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6509 pub.term_source := glBitmap_libJPEG_term_source;
6511 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6512 pub.next_input_byte := nil; // until buffer loaded
6514 SrcStream := aStream;
6517 // set global decoding state
6518 jpeg.global_state := DSTATE_START;
6520 // read header of jpeg
6521 jpeg_read_header(@jpeg, false);
6523 // setting output parameter
6524 case jpeg.jpeg_color_space of
6527 jpeg.out_color_space := JCS_GRAYSCALE;
6528 IntFormat := tfLuminance8;
6531 jpeg.out_color_space := JCS_RGB;
6532 IntFormat := tfRGB8;
6536 jpeg_start_decompress(@jpeg);
6538 TempHeight := jpeg.output_height;
6539 TempWidth := jpeg.output_width;
6541 FormatDesc := TFormatDescriptor.Get(IntFormat);
6543 // creating new image
6544 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6548 for Row := 0 to TempHeight -1 do begin
6549 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6550 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6553 // finish decompression
6554 jpeg_finish_decompress(@jpeg);
6556 // destroy decompression
6557 jpeg_destroy_decompress(@jpeg);
6559 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
6563 if Assigned(pImage) then
6573 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6574 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6575 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6580 Temp: array[0..1]of Byte;
6584 // reading first two bytes to test file and set cursor back to begin
6585 StreamPos := aStream.Position;
6586 aStream.Read(Temp[0], 2);
6587 aStream.Position := StreamPos;
6589 // if Bitmap then read file.
6590 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6591 bmp := TBitmap.Create;
6593 jpg := TJPEGImage.Create;
6595 jpg.LoadFromStream(aStream);
6597 result := AssignFromBitmap(bmp);
6609 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6610 {$IF DEFINED(GLB_LAZ_JPEG)}
6611 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6612 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6615 intf: TLazIntfImage;
6618 jpeg := TJPEGImage.Create;
6619 intf := TLazIntfImage.Create(0, 0);
6621 if not AssignToLazIntfImage(intf) then
6622 raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
6623 intf.GetRawImage(raw);
6624 jpeg.LoadFromRawImage(raw, false);
6625 jpeg.SaveToStream(aStream);
6632 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6633 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6634 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6636 jpeg: jpeg_compress_struct;
6637 jpeg_err: jpeg_error_mgr;
6639 pTemp, pTemp2: pByte;
6641 procedure CopyRow(pDest, pSource: pByte);
6645 for X := 0 to Width - 1 do begin
6646 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6647 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6648 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6655 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6656 raise EglBitmapUnsupportedFormat.Create(Format);
6658 if not init_libJPEG then
6659 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6662 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6663 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6666 jpeg.err := jpeg_std_error(@jpeg_err);
6667 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6668 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6670 // compression struct
6671 jpeg_create_compress(@jpeg);
6673 // allocation space for streaming methods
6674 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6676 // seeting up custom functions
6677 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6678 pub.init_destination := glBitmap_libJPEG_init_destination;
6679 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6680 pub.term_destination := glBitmap_libJPEG_term_destination;
6682 pub.next_output_byte := @DestBuffer[1];
6683 pub.free_in_buffer := Length(DestBuffer);
6685 DestStream := aStream;
6688 // very important state
6689 jpeg.global_state := CSTATE_START;
6690 jpeg.image_width := Width;
6691 jpeg.image_height := Height;
6693 tfAlpha8, tfLuminance8: begin
6694 jpeg.input_components := 1;
6695 jpeg.in_color_space := JCS_GRAYSCALE;
6697 tfRGB8, tfBGR8: begin
6698 jpeg.input_components := 3;
6699 jpeg.in_color_space := JCS_RGB;
6703 jpeg_set_defaults(@jpeg);
6704 jpeg_set_quality(@jpeg, 95, true);
6705 jpeg_start_compress(@jpeg, true);
6708 if Format = tfBGR8 then
6709 GetMem(pTemp2, fRowSize)
6714 for Row := 0 to jpeg.image_height -1 do begin
6716 if Format = tfBGR8 then
6717 CopyRow(pTemp2, pTemp)
6722 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6723 inc(pTemp, fRowSize);
6727 if Format = tfBGR8 then
6730 jpeg_finish_compress(@jpeg);
6731 jpeg_destroy_compress(@jpeg);
6737 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6738 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6739 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6744 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6745 raise EglBitmapUnsupportedFormat.Create(Format);
6747 Bmp := TBitmap.Create;
6749 Jpg := TJPEGImage.Create;
6751 AssignToBitmap(Bmp);
6752 if (Format in [tfAlpha8, tfLuminance8]) then begin
6753 Jpg.Grayscale := true;
6754 Jpg.PixelFormat := jf8Bit;
6757 Jpg.SaveToStream(aStream);
6768 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6769 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6770 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6777 BMP_COMP_BITFIELDS = 3;
6780 TBMPHeader = packed record
6785 bfOffBits: Cardinal;
6788 TBMPInfo = packed record
6794 biCompression: Cardinal;
6795 biSizeImage: Cardinal;
6796 biXPelsPerMeter: Longint;
6797 biYPelsPerMeter: Longint;
6798 biClrUsed: Cardinal;
6799 biClrImportant: Cardinal;
6802 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6803 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6805 //////////////////////////////////////////////////////////////////////////////////////////////////
6806 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6809 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6810 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6813 case aInfo.biCompression of
6815 BMP_COMP_RLE8: begin
6816 raise EglBitmap.Create('RLE compression is not supported');
6818 BMP_COMP_BITFIELDS: begin
6819 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6820 aStream.Read(aMask.r, SizeOf(aMask.r));
6821 aStream.Read(aMask.g, SizeOf(aMask.g));
6822 aStream.Read(aMask.b, SizeOf(aMask.b));
6823 aStream.Read(aMask.a, SizeOf(aMask.a));
6825 raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats');
6829 //get suitable format
6830 case aInfo.biBitCount of
6831 8: result := tfLuminance8;
6832 16: result := tfBGR5;
6833 24: result := tfBGR8;
6834 32: result := tfBGRA8;
6838 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6841 ColorTable: TbmpColorTable;
6844 if (aInfo.biBitCount >= 16) then
6846 aFormat := tfLuminance8;
6847 c := aInfo.biClrUsed;
6849 c := 1 shl aInfo.biBitCount;
6850 SetLength(ColorTable, c);
6851 for i := 0 to c-1 do begin
6852 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6853 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6857 result := TbmpColorTableFormat.Create;
6858 result.PixelSize := aInfo.biBitCount / 8;
6859 result.ColorTable := ColorTable;
6860 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6863 //////////////////////////////////////////////////////////////////////////////////////////////////
6864 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6865 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6867 TmpFormat: TglBitmapFormat;
6868 FormatDesc: TFormatDescriptor;
6871 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6872 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6873 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6874 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6875 aFormat := FormatDesc.Format;
6880 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6881 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6882 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6883 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6885 result := TbmpBitfieldFormat.Create;
6886 result.PixelSize := aInfo.biBitCount / 8;
6887 result.RedMask := aMask.r;
6888 result.GreenMask := aMask.g;
6889 result.BlueMask := aMask.b;
6890 result.AlphaMask := aMask.a;
6897 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6898 PaddingBuff: Cardinal;
6899 LineBuf, ImageData, TmpData: PByte;
6900 SourceMD, DestMD: Pointer;
6901 BmpFormat: TglBitmapFormat;
6904 Mask: TglBitmapColorRec;
6909 SpecialFormat: TFormatDescriptor;
6910 FormatDesc: TFormatDescriptor;
6912 //////////////////////////////////////////////////////////////////////////////////////////////////
6913 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6916 Pixel: TglBitmapPixelData;
6918 aStream.Read(aLineBuf^, rbLineSize);
6919 SpecialFormat.PreparePixel(Pixel);
6920 for i := 0 to Info.biWidth-1 do begin
6921 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6922 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6923 FormatDesc.Map(Pixel, aData, DestMD);
6929 BmpFormat := tfEmpty;
6930 SpecialFormat := nil;
6936 StartPos := aStream.Position;
6937 aStream.Read(Header{%H-}, SizeOf(Header));
6939 if Header.bfType = BMP_MAGIC then begin
6941 BmpFormat := ReadInfo(Info, Mask);
6942 SpecialFormat := ReadColorTable(BmpFormat, Info);
6943 if not Assigned(SpecialFormat) then
6944 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6945 aStream.Position := StartPos + Header.bfOffBits;
6947 if (BmpFormat <> tfEmpty) then begin
6948 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6949 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6950 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6951 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6954 DestMD := FormatDesc.CreateMappingData;
6955 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6956 GetMem(ImageData, ImageSize);
6957 if Assigned(SpecialFormat) then begin
6958 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6959 SourceMD := SpecialFormat.CreateMappingData;
6964 FillChar(ImageData^, ImageSize, $FF);
6965 TmpData := ImageData;
6966 if (Info.biHeight > 0) then
6967 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6968 for i := 0 to Abs(Info.biHeight)-1 do begin
6969 if Assigned(SpecialFormat) then
6970 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6972 aStream.Read(TmpData^, wbLineSize); //else only read data
6973 if (Info.biHeight > 0) then
6974 dec(TmpData, wbLineSize)
6976 inc(TmpData, wbLineSize);
6977 aStream.Read(PaddingBuff{%H-}, Padding);
6979 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method
6982 if Assigned(LineBuf) then
6984 if Assigned(SourceMD) then
6985 SpecialFormat.FreeMappingData(SourceMD);
6986 FormatDesc.FreeMappingData(DestMD);
6989 if Assigned(ImageData) then
6994 raise EglBitmap.Create('LoadBMP - No suitable format found');
6996 aStream.Position := StartPos;
7000 FreeAndNil(SpecialFormat);
7003 else aStream.Position := StartPos;
7006 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7007 procedure TglBitmap.SaveBMP(const aStream: TStream);
7011 Converter: TFormatDescriptor;
7012 FormatDesc: TFormatDescriptor;
7013 SourceFD, DestFD: Pointer;
7014 pData, srcData, dstData, ConvertBuffer: pByte;
7016 Pixel: TglBitmapPixelData;
7017 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
7018 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
7020 PaddingBuff: Cardinal;
7022 function GetLineWidth : Integer;
7024 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
7028 if not (ftBMP in FormatGetSupportedFiles(Format)) then
7029 raise EglBitmapUnsupportedFormat.Create(Format);
7032 FormatDesc := TFormatDescriptor.Get(Format);
7033 ImageSize := FormatDesc.GetSize(Dimension);
7035 FillChar(Header{%H-}, SizeOf(Header), 0);
7036 Header.bfType := BMP_MAGIC;
7037 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
7038 Header.bfReserved1 := 0;
7039 Header.bfReserved2 := 0;
7040 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
7042 FillChar(Info{%H-}, SizeOf(Info), 0);
7043 Info.biSize := SizeOf(Info);
7044 Info.biWidth := Width;
7045 Info.biHeight := Height;
7047 Info.biCompression := BMP_COMP_RGB;
7048 Info.biSizeImage := ImageSize;
7053 Info.biBitCount := 4;
7054 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
7055 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
7056 Converter := TbmpColorTableFormat.Create;
7057 with (Converter as TbmpColorTableFormat) do begin
7060 Range := glBitmapColorRec($F, $F, $F, $0);
7065 tfR3G3B2, tfLuminance8: begin
7066 Info.biBitCount := 8;
7067 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
7068 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
7069 Converter := TbmpColorTableFormat.Create;
7070 with (Converter as TbmpColorTableFormat) do begin
7073 if (Format = tfR3G3B2) then begin
7074 Range := glBitmapColorRec($7, $7, $3, $0);
7075 Shift := glBitmapShiftRec(0, 3, 6, 0);
7077 Range := glBitmapColorRec($FF, $FF, $FF, $0);
7082 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
7083 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
7084 Info.biBitCount := 16;
7085 Info.biCompression := BMP_COMP_BITFIELDS;
7088 tfBGR8, tfRGB8: begin
7089 Info.biBitCount := 24;
7090 if (Format = tfRGB8) then
7091 Converter := TfdBGR8.Create; //use BGR8 Format Descriptor to Swap RGB Values
7094 tfRGB10, tfRGB10A2, tfRGBA8,
7095 tfBGR10, tfBGR10A2, tfBGRA8: begin
7096 Info.biBitCount := 32;
7097 Info.biCompression := BMP_COMP_BITFIELDS;
7100 raise EglBitmapUnsupportedFormat.Create(Format);
7102 Info.biXPelsPerMeter := 2835;
7103 Info.biYPelsPerMeter := 2835;
7106 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7107 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
7108 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
7110 RedMask := FormatDesc.RedMask;
7111 GreenMask := FormatDesc.GreenMask;
7112 BlueMask := FormatDesc.BlueMask;
7113 AlphaMask := FormatDesc.AlphaMask;
7117 aStream.Write(Header, SizeOf(Header));
7118 aStream.Write(Info, SizeOf(Info));
7121 if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
7122 with (Converter as TbmpColorTableFormat) do
7123 aStream.Write(ColorTable[0].b,
7124 SizeOf(TbmpColorTableEnty) * Length(ColorTable));
7127 if Info.biCompression = BMP_COMP_BITFIELDS then begin
7128 aStream.Write(RedMask, SizeOf(Cardinal));
7129 aStream.Write(GreenMask, SizeOf(Cardinal));
7130 aStream.Write(BlueMask, SizeOf(Cardinal));
7131 aStream.Write(AlphaMask, SizeOf(Cardinal));
7135 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
7136 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
7137 Padding := GetLineWidth - wbLineSize;
7141 inc(pData, (Height-1) * rbLineSize);
7143 // prepare row buffer. But only for RGB because RGBA supports color masks
7144 // so it's possible to change color within the image.
7145 if Assigned(Converter) then begin
7146 FormatDesc.PreparePixel(Pixel);
7147 GetMem(ConvertBuffer, wbLineSize);
7148 SourceFD := FormatDesc.CreateMappingData;
7149 DestFD := Converter.CreateMappingData;
7151 ConvertBuffer := nil;
7154 for LineIdx := 0 to Height - 1 do begin
7156 if Assigned(Converter) then begin
7158 dstData := ConvertBuffer;
7159 for PixelIdx := 0 to Info.biWidth-1 do begin
7160 FormatDesc.Unmap(srcData, Pixel, SourceFD);
7161 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
7162 Converter.Map(Pixel, dstData, DestFD);
7164 aStream.Write(ConvertBuffer^, wbLineSize);
7166 aStream.Write(pData^, rbLineSize);
7168 dec(pData, rbLineSize);
7169 if (Padding > 0) then
7170 aStream.Write(PaddingBuff, Padding);
7173 // destroy row buffer
7174 if Assigned(ConvertBuffer) then begin
7175 FormatDesc.FreeMappingData(SourceFD);
7176 Converter.FreeMappingData(DestFD);
7177 FreeMem(ConvertBuffer);
7181 if Assigned(Converter) then
7186 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7187 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7188 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7190 TTGAHeader = packed record
7194 //ColorMapSpec: Array[0..4] of Byte;
7195 ColorMapStart: Word;
7196 ColorMapLength: Word;
7197 ColorMapEntrySize: Byte;
7207 TGA_UNCOMPRESSED_RGB = 2;
7208 TGA_UNCOMPRESSED_GRAY = 3;
7209 TGA_COMPRESSED_RGB = 10;
7210 TGA_COMPRESSED_GRAY = 11;
7212 TGA_NONE_COLOR_TABLE = 0;
7214 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7215 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
7218 ImageData: System.PByte;
7219 StartPosition: Int64;
7220 PixelSize, LineSize: Integer;
7221 tgaFormat: TglBitmapFormat;
7222 FormatDesc: TFormatDescriptor;
7223 Counter: packed record
7225 low, high, dir: Integer;
7232 ////////////////////////////////////////////////////////////////////////////////////////
7233 procedure ReadUncompressed;
7236 buf, tmp1, tmp2: System.PByte;
7239 if (Counter.X.dir < 0) then
7240 GetMem(buf, LineSize);
7242 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
7244 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
7245 if (Counter.X.dir < 0) then begin //flip X
7246 aStream.Read(buf^, LineSize);
7248 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
7249 for i := 0 to Header.Width-1 do begin //for all pixels in line
7250 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
7255 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
7258 aStream.Read(tmp1^, LineSize);
7259 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
7262 if Assigned(buf) then
7267 ////////////////////////////////////////////////////////////////////////////////////////
7268 procedure ReadCompressed;
7270 /////////////////////////////////////////////////////////////////
7272 TmpData: System.PByte;
7273 LinePixelsRead: Integer;
7274 procedure CheckLine;
7276 if (LinePixelsRead >= Header.Width) then begin
7277 LinePixelsRead := 0;
7278 inc(Counter.Y.low, Counter.Y.dir); //next line index
7279 TmpData := ImageData;
7280 inc(TmpData, Counter.Y.low * LineSize); //set line
7281 if (Counter.X.dir < 0) then //if x flipped then
7282 inc(TmpData, LineSize - PixelSize); //set last pixel
7286 /////////////////////////////////////////////////////////////////
7289 CacheSize, CachePos: Integer;
7290 procedure CachedRead(out Buffer; Count: Integer);
7294 if (CachePos + Count > CacheSize) then begin
7295 //if buffer overflow save non read bytes
7297 if (CacheSize - CachePos > 0) then begin
7298 BytesRead := CacheSize - CachePos;
7299 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
7300 inc(CachePos, BytesRead);
7303 //load cache from file
7304 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
7305 aStream.Read(Cache^, CacheSize);
7308 //read rest of requested bytes
7309 if (Count - BytesRead > 0) then begin
7310 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
7311 inc(CachePos, Count - BytesRead);
7314 //if no buffer overflow just read the data
7315 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
7316 inc(CachePos, Count);
7320 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
7325 inc(aBuffer, Counter.X.dir);
7328 PWord(aBuffer)^ := PWord(aData)^;
7329 inc(aBuffer, 2 * Counter.X.dir);
7332 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
7333 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
7334 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
7335 inc(aBuffer, 3 * Counter.X.dir);
7338 PCardinal(aBuffer)^ := PCardinal(aData)^;
7339 inc(aBuffer, 4 * Counter.X.dir);
7345 TotalPixelsToRead, TotalPixelsRead: Integer;
7347 buf: array [0..3] of Byte; //1 pixel is max 32bit long
7348 PixelRepeat: Boolean;
7349 PixelsToRead, PixelCount: Integer;
7354 TotalPixelsToRead := Header.Width * Header.Height;
7355 TotalPixelsRead := 0;
7356 LinePixelsRead := 0;
7358 GetMem(Cache, CACHE_SIZE);
7360 TmpData := ImageData;
7361 inc(TmpData, Counter.Y.low * LineSize); //set line
7362 if (Counter.X.dir < 0) then //if x flipped then
7363 inc(TmpData, LineSize - PixelSize); //set last pixel
7367 CachedRead(Temp, 1);
7368 PixelRepeat := (Temp and $80) > 0;
7369 PixelsToRead := (Temp and $7F) + 1;
7370 inc(TotalPixelsRead, PixelsToRead);
7373 CachedRead(buf[0], PixelSize);
7374 while (PixelsToRead > 0) do begin
7376 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
7377 while (PixelCount > 0) do begin
7378 if not PixelRepeat then
7379 CachedRead(buf[0], PixelSize);
7380 PixelToBuffer(@buf[0], TmpData);
7381 inc(LinePixelsRead);
7386 until (TotalPixelsRead >= TotalPixelsToRead);
7392 function IsGrayFormat: Boolean;
7394 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
7400 // reading header to test file and set cursor back to begin
7401 StartPosition := aStream.Position;
7402 aStream.Read(Header{%H-}, SizeOf(Header));
7404 // no colormapped files
7405 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
7406 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
7409 if Header.ImageID <> 0 then // skip image ID
7410 aStream.Position := aStream.Position + Header.ImageID;
7412 tgaFormat := tfEmpty;
7414 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
7415 0: tgaFormat := tfLuminance8;
7416 8: tgaFormat := tfAlpha8;
7419 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
7420 0: tgaFormat := tfLuminance16;
7421 8: tgaFormat := tfLuminance8Alpha8;
7422 end else case (Header.ImageDesc and $F) of
7423 0: tgaFormat := tfBGR5;
7424 1: tgaFormat := tfBGR5A1;
7425 4: tgaFormat := tfBGRA4;
7428 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7429 0: tgaFormat := tfBGR8;
7432 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7433 2: tgaFormat := tfBGR10A2;
7434 8: tgaFormat := tfBGRA8;
7438 if (tgaFormat = tfEmpty) then
7439 raise EglBitmap.Create('LoadTga - unsupported format');
7441 FormatDesc := TFormatDescriptor.Get(tgaFormat);
7442 PixelSize := FormatDesc.GetSize(1, 1);
7443 LineSize := FormatDesc.GetSize(Header.Width, 1);
7445 GetMem(ImageData, LineSize * Header.Height);
7448 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7449 Counter.X.low := Header.Height-1;;
7450 Counter.X.high := 0;
7451 Counter.X.dir := -1;
7454 Counter.X.high := Header.Height-1;
7459 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7461 Counter.Y.high := Header.Height-1;
7464 Counter.Y.low := Header.Height-1;;
7465 Counter.Y.high := 0;
7466 Counter.Y.dir := -1;
7470 case Header.ImageType of
7471 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7473 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7477 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method
7480 if Assigned(ImageData) then
7485 aStream.Position := StartPosition;
7488 else aStream.Position := StartPosition;
7491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7492 procedure TglBitmap.SaveTGA(const aStream: TStream);
7495 LineSize, Size, x, y: Integer;
7496 Pixel: TglBitmapPixelData;
7497 LineBuf, SourceData, DestData: PByte;
7498 SourceMD, DestMD: Pointer;
7499 FormatDesc: TFormatDescriptor;
7500 Converter: TFormatDescriptor;
7502 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7503 raise EglBitmapUnsupportedFormat.Create(Format);
7506 FillChar(Header{%H-}, SizeOf(Header), 0);
7509 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7510 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7511 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7513 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7516 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7518 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7519 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7521 else if (Format in [tfBGR8, tfRGB8]) then
7529 Header.ImageDesc := 1 and $F;
7530 tfRGB10A2, tfBGR10A2:
7531 Header.ImageDesc := 2 and $F;
7533 Header.ImageDesc := 4 and $F;
7534 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7535 Header.ImageDesc := 8 and $F;
7538 Header.Width := Width;
7539 Header.Height := Height;
7540 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7541 aStream.Write(Header, SizeOf(Header));
7543 // convert RGB(A) to BGR(A)
7545 FormatDesc := TFormatDescriptor.Get(Format);
7546 Size := FormatDesc.GetSize(Dimension);
7547 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7548 if (FormatDesc.RGBInverted = tfEmpty) then
7549 raise EglBitmap.Create('inverted RGB format is empty');
7550 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7551 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7552 (Converter.PixelSize <> FormatDesc.PixelSize) then
7553 raise EglBitmap.Create('invalid inverted RGB format');
7556 if Assigned(Converter) then begin
7557 LineSize := FormatDesc.GetSize(Width, 1);
7558 GetMem(LineBuf, LineSize);
7559 SourceMD := FormatDesc.CreateMappingData;
7560 DestMD := Converter.CreateMappingData;
7563 for y := 0 to Height-1 do begin
7564 DestData := LineBuf;
7565 for x := 0 to Width-1 do begin
7566 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7567 Converter.Map(Pixel, DestData, DestMD);
7569 aStream.Write(LineBuf^, LineSize);
7573 FormatDesc.FreeMappingData(SourceMD);
7574 FormatDesc.FreeMappingData(DestMD);
7577 aStream.Write(Data^, Size);
7580 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7581 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7582 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7584 DDS_MAGIC: Cardinal = $20534444;
7586 // DDS_header.dwFlags
7587 DDSD_CAPS = $00000001;
7588 DDSD_HEIGHT = $00000002;
7589 DDSD_WIDTH = $00000004;
7590 DDSD_PIXELFORMAT = $00001000;
7592 // DDS_header.sPixelFormat.dwFlags
7593 DDPF_ALPHAPIXELS = $00000001;
7594 DDPF_ALPHA = $00000002;
7595 DDPF_FOURCC = $00000004;
7596 DDPF_RGB = $00000040;
7597 DDPF_LUMINANCE = $00020000;
7599 // DDS_header.sCaps.dwCaps1
7600 DDSCAPS_TEXTURE = $00001000;
7602 // DDS_header.sCaps.dwCaps2
7603 DDSCAPS2_CUBEMAP = $00000200;
7605 D3DFMT_DXT1 = $31545844;
7606 D3DFMT_DXT3 = $33545844;
7607 D3DFMT_DXT5 = $35545844;
7610 TDDSPixelFormat = packed record
7614 dwRGBBitCount: Cardinal;
7615 dwRBitMask: Cardinal;
7616 dwGBitMask: Cardinal;
7617 dwBBitMask: Cardinal;
7618 dwABitMask: Cardinal;
7621 TDDSCaps = packed record
7625 dwReserved: Cardinal;
7628 TDDSHeader = packed record
7633 dwPitchOrLinearSize: Cardinal;
7635 dwMipMapCount: Cardinal;
7636 dwReserved: array[0..10] of Cardinal;
7637 PixelFormat: TDDSPixelFormat;
7639 dwReserved2: Cardinal;
7642 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7643 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7646 Converter: TbmpBitfieldFormat;
7648 function GetDDSFormat: TglBitmapFormat;
7650 fd: TFormatDescriptor;
7652 Range: TglBitmapColorRec;
7656 with Header.PixelFormat do begin
7658 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7659 case Header.PixelFormat.dwFourCC of
7660 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7661 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7662 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7664 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7666 //find matching format
7667 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7668 fd := TFormatDescriptor.Get(result);
7669 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7670 (8 * fd.PixelSize = dwRGBBitCount) then
7674 //find format with same Range
7675 Range.r := dwRBitMask;
7676 Range.g := dwGBitMask;
7677 Range.b := dwBBitMask;
7678 Range.a := dwABitMask;
7679 for i := 0 to 3 do begin
7680 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7681 Range.arr[i] := Range.arr[i] shr 1;
7683 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7684 fd := TFormatDescriptor.Get(result);
7687 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7695 //no format with same range found -> use default
7696 if (result = tfEmpty) then begin
7697 if (dwABitMask > 0) then
7703 Converter := TbmpBitfieldFormat.Create;
7704 Converter.RedMask := dwRBitMask;
7705 Converter.GreenMask := dwGBitMask;
7706 Converter.BlueMask := dwBBitMask;
7707 Converter.AlphaMask := dwABitMask;
7708 Converter.PixelSize := dwRGBBitCount / 8;
7715 x, y, LineSize, RowSize, Magic: Cardinal;
7716 NewImage, TmpData, RowData, SrcData: System.PByte;
7717 SourceMD, DestMD: Pointer;
7718 Pixel: TglBitmapPixelData;
7719 ddsFormat: TglBitmapFormat;
7720 FormatDesc: TFormatDescriptor;
7725 StreamPos := aStream.Position;
7728 aStream.Read(Magic{%H-}, sizeof(Magic));
7729 if (Magic <> DDS_MAGIC) then begin
7730 aStream.Position := StreamPos;
7735 aStream.Read(Header{%H-}, sizeof(Header));
7736 if (Header.dwSize <> SizeOf(Header)) or
7737 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7738 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7740 aStream.Position := StreamPos;
7744 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7745 raise EglBitmap.Create('LoadDDS - CubeMaps are not supported');
7747 ddsFormat := GetDDSFormat;
7749 if (ddsFormat = tfEmpty) then
7750 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7752 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7753 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7754 GetMem(NewImage, Header.dwHeight * LineSize);
7756 TmpData := NewImage;
7759 if Assigned(Converter) then begin
7760 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7761 GetMem(RowData, RowSize);
7762 SourceMD := Converter.CreateMappingData;
7763 DestMD := FormatDesc.CreateMappingData;
7765 for y := 0 to Header.dwHeight-1 do begin
7766 TmpData := NewImage;
7767 inc(TmpData, y * LineSize);
7769 aStream.Read(SrcData^, RowSize);
7770 for x := 0 to Header.dwWidth-1 do begin
7771 Converter.Unmap(SrcData, Pixel, SourceMD);
7772 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7773 FormatDesc.Map(Pixel, TmpData, DestMD);
7777 Converter.FreeMappingData(SourceMD);
7778 FormatDesc.FreeMappingData(DestMD);
7784 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7785 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7786 for Y := 0 to Header.dwHeight-1 do begin
7787 aStream.Read(TmpData^, RowSize);
7788 Inc(TmpData, LineSize);
7793 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7794 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7795 for Y := 0 to Header.dwHeight-1 do begin
7796 aStream.Read(TmpData^, RowSize);
7797 Inc(TmpData, LineSize);
7800 raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.');
7802 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method
7805 if Assigned(NewImage) then
7810 FreeAndNil(Converter);
7814 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7815 procedure TglBitmap.SaveDDS(const aStream: TStream);
7818 FormatDesc: TFormatDescriptor;
7820 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7821 raise EglBitmapUnsupportedFormat.Create(Format);
7823 FormatDesc := TFormatDescriptor.Get(Format);
7826 FillChar(Header{%H-}, SizeOf(Header), 0);
7827 Header.dwSize := SizeOf(Header);
7828 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7830 Header.dwWidth := Max(1, Width);
7831 Header.dwHeight := Max(1, Height);
7834 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7837 Header.PixelFormat.dwSize := sizeof(Header);
7838 if (FormatDesc.IsCompressed) then begin
7839 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7841 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7842 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7843 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7845 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7846 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7847 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7848 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7849 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7850 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7851 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7852 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7853 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7855 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7856 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7857 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7858 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7859 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7860 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7863 if (FormatDesc.HasAlpha) then
7864 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7866 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7867 aStream.Write(Header, SizeOf(Header));
7868 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7871 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7872 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7873 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7874 procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7875 const aWidth: Integer; const aHeight: Integer);
7880 if (aHeight > 1) then begin
7881 Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1);
7882 GetMem(pTemp, Size);
7884 Move(aData^, pTemp^, Size);
7893 inherited SetDataPointer(pTemp, aFormat, aWidth);
7896 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7897 function TglBitmap1D.FlipHorz: Boolean;
7900 pTempDest, pDest, pSource: PByte;
7902 result := inherited FlipHorz;
7903 if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin
7905 GetMem(pDest, fRowSize);
7908 Inc(pTempDest, fRowSize);
7909 for Col := 0 to Width-1 do begin
7910 dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data
7911 Move(pSource^, pTempDest^, fPixelSize);
7912 Inc(pSource, fPixelSize);
7914 SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method
7917 if Assigned(pDest) then
7924 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7925 procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean);
7927 FormatDesc: TFormatDescriptor;
7930 FormatDesc := TFormatDescriptor.Get(Format);
7931 if FormatDesc.IsCompressed then begin
7932 if not Assigned(glCompressedTexImage1D) then
7933 raise EglBitmap.Create('compressed formats not supported by video adapter');
7934 glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
7935 end else if aBuildWithGlu then
7936 gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7938 glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7941 if (FreeDataAfterGenTexture) then
7945 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7946 procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean);
7948 BuildWithGlu, TexRec: Boolean;
7951 if Assigned(Data) then begin
7952 // Check Texture Size
7953 if (aTestTextureSize) then begin
7954 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7956 if (Width > TexSize) then
7957 raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7959 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7960 (Target = GL_TEXTURE_RECTANGLE);
7961 if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7962 raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7966 SetupParameters(BuildWithGlu);
7967 UploadData(BuildWithGlu);
7968 glAreTexturesResident(1, @fID, @fIsResident);
7972 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7973 procedure TglBitmap1D.AfterConstruction;
7976 Target := GL_TEXTURE_1D;
7979 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7980 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7981 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7982 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7984 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7985 result := fLines[aIndex]
7990 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7991 procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7992 const aWidth: Integer; const aHeight: Integer);
7994 Idx, LineWidth: Integer;
7996 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7998 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
8000 if Assigned(Data) then begin
8001 SetLength(fLines, GetHeight);
8002 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
8004 for Idx := 0 to GetHeight-1 do begin
8005 fLines[Idx] := Data;
8006 Inc(fLines[Idx], Idx * LineWidth);
8009 else SetLength(fLines, 0);
8011 SetLength(fLines, 0);
8015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8016 procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
8018 FormatDesc: TFormatDescriptor;
8020 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
8022 FormatDesc := TFormatDescriptor.Get(Format);
8023 if FormatDesc.IsCompressed then begin
8024 if not Assigned(glCompressedTexImage2D) then
8025 raise EglBitmap.Create('compressed formats not supported by video adapter');
8026 glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
8027 end else if aBuildWithGlu then begin
8028 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
8029 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
8031 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
8032 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
8036 if (FreeDataAfterGenTexture) then
8040 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8041 procedure TglBitmap2D.AfterConstruction;
8044 Target := GL_TEXTURE_2D;
8047 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8048 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
8051 Size, w, h: Integer;
8052 FormatDesc: TFormatDescriptor;
8054 FormatDesc := TFormatDescriptor.Get(aFormat);
8055 if FormatDesc.IsCompressed then
8056 raise EglBitmapUnsupportedFormat.Create(aFormat);
8058 w := aRight - aLeft;
8059 h := aBottom - aTop;
8060 Size := FormatDesc.GetSize(w, h);
8063 glPixelStorei(GL_PACK_ALIGNMENT, 1);
8064 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8065 SetDataPointer(Temp, aFormat, w, h); //be careful, Data could be freed by this method
8068 if Assigned(Temp) then
8074 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8075 procedure TglBitmap2D.GetDataFromTexture;
8078 TempWidth, TempHeight: Integer;
8079 TempIntFormat: GLint;
8080 IntFormat: TglBitmapFormat;
8081 FormatDesc: TFormatDescriptor;
8086 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
8087 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
8088 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
8090 IntFormat := tfEmpty;
8091 FormatDesc := (TglBitmapFormatDescriptor.GetByFormat(TempIntFormat) as TFormatDescriptor);
8092 IntFormat := FormatDesc.Format;
8094 // Getting data from OpenGL
8095 FormatDesc := TFormatDescriptor.Get(IntFormat);
8096 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
8098 if FormatDesc.IsCompressed then begin
8099 if not Assigned(glGetCompressedTexImage) then
8100 raise EglBitmap.Create('compressed formats not supported by video adapter');
8101 glGetCompressedTexImage(Target, 0, Temp)
8103 glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
8104 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
8106 if Assigned(Temp) then
8112 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8113 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
8115 BuildWithGlu, PotTex, TexRec: Boolean;
8118 if Assigned(Data) then begin
8119 // Check Texture Size
8120 if (aTestTextureSize) then begin
8121 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8123 if ((Height > TexSize) or (Width > TexSize)) then
8124 raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8126 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
8127 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
8128 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8129 raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8133 SetupParameters(BuildWithGlu);
8134 UploadData(Target, BuildWithGlu);
8135 glAreTexturesResident(1, @fID, @fIsResident);
8139 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8140 function TglBitmap2D.FlipHorz: Boolean;
8143 TempDestData, DestData, SourceData: PByte;
8146 result := inherited FlipHorz;
8147 if Assigned(Data) then begin
8149 ImgSize := Height * fRowSize;
8150 GetMem(DestData, ImgSize);
8152 TempDestData := DestData;
8153 Dec(TempDestData, fRowSize + fPixelSize);
8154 for Row := 0 to Height -1 do begin
8155 Inc(TempDestData, fRowSize * 2);
8156 for Col := 0 to Width -1 do begin
8157 Move(SourceData^, TempDestData^, fPixelSize);
8158 Inc(SourceData, fPixelSize);
8159 Dec(TempDestData, fPixelSize);
8162 SetDataPointer(DestData, Format, Width, Height); //be careful, Data could be freed by this method
8165 if Assigned(DestData) then
8172 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8173 function TglBitmap2D.FlipVert: Boolean;
8176 TempDestData, DestData, SourceData: PByte;
8178 result := inherited FlipVert;
8179 if Assigned(Data) then begin
8181 GetMem(DestData, Height * fRowSize);
8183 TempDestData := DestData;
8184 Inc(TempDestData, Width * (Height -1) * fPixelSize);
8185 for Row := 0 to Height -1 do begin
8186 Move(SourceData^, TempDestData^, fRowSize);
8187 Dec(TempDestData, fRowSize);
8188 Inc(SourceData, fRowSize);
8190 SetDataPointer(DestData, Format, Width, Height); //be careful, Data could be freed by this method
8193 if Assigned(DestData) then
8200 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8201 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8202 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8204 TMatrixItem = record
8209 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
8210 TglBitmapToNormalMapRec = Record
8212 Heights: array of Single;
8213 MatrixU : array of TMatrixItem;
8214 MatrixV : array of TMatrixItem;
8218 ONE_OVER_255 = 1 / 255;
8220 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8221 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
8225 with FuncRec do begin
8227 Source.Data.r * LUMINANCE_WEIGHT_R +
8228 Source.Data.g * LUMINANCE_WEIGHT_G +
8229 Source.Data.b * LUMINANCE_WEIGHT_B;
8230 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
8234 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8235 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
8238 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
8241 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8242 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
8244 TVec = Array[0..2] of Single;
8251 function GetHeight(X, Y: Integer): Single;
8253 with FuncRec do begin
8254 X := Max(0, Min(Size.X -1, X));
8255 Y := Max(0, Min(Size.Y -1, Y));
8256 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
8261 with FuncRec do begin
8262 with PglBitmapToNormalMapRec(Args)^ do begin
8264 for Idx := Low(MatrixU) to High(MatrixU) do
8265 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
8268 for Idx := Low(MatrixU) to High(MatrixU) do
8269 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
8271 Vec[0] := -du * Scale;
8272 Vec[1] := -dv * Scale;
8277 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8278 if Len <> 0 then begin
8279 Vec[0] := Vec[0] * Len;
8280 Vec[1] := Vec[1] * Len;
8281 Vec[2] := Vec[2] * Len;
8285 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
8286 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
8287 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
8291 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8292 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
8294 Rec: TglBitmapToNormalMapRec;
8296 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
8298 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
8299 Matrix[Index].X := X;
8300 Matrix[Index].Y := Y;
8301 Matrix[Index].W := W;
8306 if TFormatDescriptor.Get(Format).IsCompressed then
8307 raise EglBitmapUnsupportedFormat.Create(Format);
8309 if aScale > 100 then
8311 else if aScale < -100 then
8314 Rec.Scale := aScale;
8316 SetLength(Rec.Heights, Width * Height);
8320 SetLength(Rec.MatrixU, 2);
8321 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
8322 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
8324 SetLength(Rec.MatrixV, 2);
8325 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
8326 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
8330 SetLength(Rec.MatrixU, 6);
8331 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
8332 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
8333 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
8334 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
8335 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
8336 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
8338 SetLength(Rec.MatrixV, 6);
8339 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
8340 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
8341 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
8342 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
8343 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
8344 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
8348 SetLength(Rec.MatrixU, 6);
8349 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
8350 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
8351 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
8352 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
8353 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
8354 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
8356 SetLength(Rec.MatrixV, 6);
8357 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
8358 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
8359 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
8360 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
8361 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
8362 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
8366 SetLength(Rec.MatrixU, 20);
8367 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
8368 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
8369 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
8370 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
8371 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
8372 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
8373 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
8374 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
8375 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
8376 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
8377 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
8378 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
8379 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
8380 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
8381 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
8382 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
8383 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
8384 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
8385 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
8386 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
8388 SetLength(Rec.MatrixV, 20);
8389 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
8390 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
8391 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
8392 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
8393 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
8394 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
8395 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
8396 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
8397 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
8398 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
8399 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
8400 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
8401 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
8402 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
8403 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
8404 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
8405 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
8406 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
8407 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
8408 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
8413 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
8414 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
8416 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
8417 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
8419 SetLength(Rec.Heights, 0);
8423 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8424 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8426 procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean);
8428 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8431 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8432 procedure TglBitmapCubeMap.AfterConstruction;
8436 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8437 raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8440 Target := GL_TEXTURE_CUBE_MAP;
8441 fGenMode := GL_REFLECTION_MAP;
8444 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8445 procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean);
8447 BuildWithGlu: Boolean;
8450 if (aTestTextureSize) then begin
8451 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8453 if (Height > TexSize) or (Width > TexSize) then
8454 raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8456 if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8457 raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8462 SetupParameters(BuildWithGlu);
8463 UploadData(aCubeTarget, BuildWithGlu);
8466 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8467 procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean);
8469 inherited Bind (aEnableTextureUnit);
8470 if aEnableTexCoordsGen then begin
8471 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8472 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8473 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8474 glEnable(GL_TEXTURE_GEN_S);
8475 glEnable(GL_TEXTURE_GEN_T);
8476 glEnable(GL_TEXTURE_GEN_R);
8480 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8481 procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean);
8483 inherited Unbind(aDisableTextureUnit);
8484 if aDisableTexCoordsGen then begin
8485 glDisable(GL_TEXTURE_GEN_S);
8486 glDisable(GL_TEXTURE_GEN_T);
8487 glDisable(GL_TEXTURE_GEN_R);
8491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8492 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8493 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8495 TVec = Array[0..2] of Single;
8496 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8498 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8499 TglBitmapNormalMapRec = record
8501 Func: TglBitmapNormalMapGetVectorFunc;
8504 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8505 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8507 aVec[0] := aHalfSize;
8508 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8509 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8512 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8513 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8515 aVec[0] := - aHalfSize;
8516 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8517 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8520 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8521 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8523 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8524 aVec[1] := aHalfSize;
8525 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8528 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8529 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8531 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8532 aVec[1] := - aHalfSize;
8533 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8536 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8537 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8539 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8540 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8541 aVec[2] := aHalfSize;
8544 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8545 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8547 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8548 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8549 aVec[2] := - aHalfSize;
8552 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8553 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8559 with FuncRec do begin
8560 with PglBitmapNormalMapRec(Args)^ do begin
8561 Func(Vec, Position, HalfSize);
8564 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8565 if Len <> 0 then begin
8566 Vec[0] := Vec[0] * Len;
8567 Vec[1] := Vec[1] * Len;
8568 Vec[2] := Vec[2] * Len;
8571 // Scale Vector and AddVectro
8572 Vec[0] := Vec[0] * 0.5 + 0.5;
8573 Vec[1] := Vec[1] * 0.5 + 0.5;
8574 Vec[2] := Vec[2] * 0.5 + 0.5;
8579 Dest.Data.arr[i] := Round(Vec[i] * 255);
8583 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8584 procedure TglBitmapNormalMap.AfterConstruction;
8587 fGenMode := GL_NORMAL_MAP;
8590 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8591 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean);
8593 Rec: TglBitmapNormalMapRec;
8594 SizeRec: TglBitmapPixelPosition;
8596 Rec.HalfSize := aSize div 2;
8597 FreeDataAfterGenTexture := false;
8599 SizeRec.Fields := [ffX, ffY];
8604 Rec.Func := glBitmapNormalMapPosX;
8605 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8606 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize);
8609 Rec.Func := glBitmapNormalMapNegX;
8610 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8611 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize);
8614 Rec.Func := glBitmapNormalMapPosY;
8615 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8616 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize);
8619 Rec.Func := glBitmapNormalMapNegY;
8620 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8621 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize);
8624 Rec.Func := glBitmapNormalMapPosZ;
8625 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8626 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize);
8629 Rec.Func := glBitmapNormalMapNegZ;
8630 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8631 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize);
8636 glBitmapSetDefaultFormat (tfEmpty);
8637 glBitmapSetDefaultMipmap (mmMipmap);
8638 glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8639 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8640 glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA);
8642 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8643 glBitmapSetDefaultDeleteTextureOnFree (true);
8645 TFormatDescriptor.Init;
8647 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8648 OpenGLInitialized := false;
8649 InitOpenGLCS := TCriticalSection.Create;
8653 TFormatDescriptor.Finalize;
8655 {$IFDEF GLB_NATIVE_OGL}
8656 if Assigned(GL_LibHandle) then
8657 glbFreeLibrary(GL_LibHandle);
8659 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8660 if Assigned(GLU_LibHandle) then
8661 glbFreeLibrary(GLU_LibHandle);
8662 FreeAndNil(InitOpenGLCS);