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/)
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 - The define GLB_DELPHI dosn't check versions anymore. If you say you are using delphi
19 then it's your problem if that isn't true. This prevents the unit for incompatibility
20 with newer versions of Delphi.
21 - Problems with D2009+ resolved (Thanks noeska and all i forgot)
22 - GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson)
24 - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson)
25 - Additional Datapointer for functioninterface now has the name CustomData
27 - AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson)
28 - If you load an texture from an file the property Filename will be set to the name of the file
29 - Three new properties to attach custom data to the Texture objects
30 - CustomName (free for use string)
31 - CustomNameW (free for use widestring)
32 - CustomDataPointer (free for use pointer to attach other objects or complex structures)
34 - RLE TGAs loaded much faster
36 - fixed some problem with reading RLE TGAs.
38 - function clone now only copys data if it's assigned and now it also copies the ID
39 - it seems that lazarus dont like comments in comments.
41 - It's possible to set the id of the texture
42 - define GLB_NO_NATIVE_GL deactivated by default
44 - Now supports the following libraries
48 - Linux compatibillity via free pascal compatibility (delphi sources optional)
49 - BMPs now loaded manuel
51 - Property DataPtr now has the name Data
52 - Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR
53 - Unused Depth removed
54 - Function FreeData to freeing image data added
56 - ImageID flag of TGAs was ignored. (Thanks Zwoetzen)
58 - Function SetBorderColor implemented (only used by opengl if wrap is set to GL_CLAMP_TO_BORDER)
59 - Function AddAlphaFromValue implemented to use an fixed Value as Alphachannel
60 - Function ReadOpenGLExtension is now only intern
62 - pngimage now disabled by default like all other versions.
64 - Setting up an anisotropic filter of 0 isnt allowed by nvidia (Thanks Ogridi)
66 - Fixed some Problem with Delphi 5
67 - Now uses the newest version of pngimage. Makes saving pngs much easier.
69 - Property IsCompressed and Size removed. Not really supported by Spec (Thanks Ogridi)
71 - Internal Format ifDepth8 added
72 - function GrabScreen now supports all uncompressed formats
74 - AddAlphaFromglBitmap implemented
76 - LoadFromResource and LoadFromResourceId now needs an Instance and an ResourceType (for ID)
78 - Width, Height and Depth internal changed to TglBitmapPixelPosition.
79 property Width, Height, Depth are still existing and new property Dimension are avail
81 - Added native OpenGL Support. Breaking the dglOpenGL "barrier".
83 - Added function GrabScreen to class TglBitmap2D
85 - Added support to Save images
86 - Added function Clone to Clone Instance
88 - Functions now works with Cardinals for each channel. Up to 32 Bits per channel.
90 - Several speed optimizations
92 - Internal structure change. Loading of TGA, PNG and DDS improved.
93 Data, format and size will now set directly with SetDataPtr.
94 - AddFunc now works with all Types of Images and Formats
95 - Some Funtions moved to Baseclass TglBitmap
97 - Added Support to decompress DXT3 and DXT5 compressed Images.
98 - Added Mapping to convert data from one format into an other.
100 - Added method ConvertTo in Class TglBitmap2D. Method allows to convert every
101 supported Input format (supported by GetPixel) into any uncompresed Format
102 - Added Support to decompress DXT1 compressed Images.
103 - SwapColors replaced by ConvertTo
105 - Added Support for compressed DDSs
106 - Added new internal formats (DXT1, DXT3, DXT5)
108 - Parameter Components renamed to InternalFormat
110 - Some AllocMem replaced with GetMem (little speed change)
111 - better exception handling. Better protection from memory leaks.
113 - Added support for Direct Draw Surfaces (.DDS) (uncompressed images only)
114 - Added new internal formats (RGB8, RGBA8, RGBA4, RGB5A1, RGB10A2, R5G6B5)
116 - Added support for Grayscale textures
117 - Added internal formats (Alpha, Luminance, LuminanceAlpha, BGR8, BGRA8)
119 - Added support for GL_VERSION_2_0
120 - Added support for GL_EXT_texture_filter_anisotropic
122 - Function FillWithColor fills the Image with one Color
123 - Function LoadNormalMap added
125 - ToNormalMap allows to Create an NormalMap from the Alphachannel
126 - ToNormalMap now supports Sobel (nmSobel) function.
128 - support for RLE Compressed RGB TGAs added
130 - Class TglBitmapNormalMap added to support Normalmap generation
131 - Added function ToNormalMap in class TglBitmap2D to genereate normal maps from textures.
132 3 Filters are supported. (4 Samples, 3x3 and 5x5)
134 - Method LoadCubeMapClass removed
135 - LoadCubeMap returnvalue is now the Texture paramter. Such as LoadTextures
136 - virtual abstract method GenTexture in class TglBitmap now is protected
138 - now support DescriptionFlag in LoadTga. Allows vertical flipped images to be loaded as normal
140 - little enhancement for IsPowerOfTwo
141 - TglBitmap1D.GenTexture now tests NPOT Textures
143 - some little name changes. All properties or function with Texture in name are
144 now without texture in name. We have allways texture so we dosn't name it.
146 - GenTexture now tests if texture is NPOT and NPOT-Texture are supported or
147 TextureTarget is GL_TEXTURE_RECTANGLE. Else it raised an exception.
149 - added support for GL_ARB_texture_rectangle, GL_EXT_texture_rectangle and GL_NV_texture_rectangle
151 - Function Unbind added
152 - call of SetFilter or SetTextureWrap if TextureID exists results in setting properties to opengl texture.
154 - class TglBitmapCubeMap added (allows to Create Cubemaps)
156 - Added Support for PNG Images. (http://pngdelphi.sourceforge.net/)
157 To Enable png's use the define pngimage
159 - New Functioninterface added
160 - Function GetPixel added
162 - Property BuildMipMaps renamed to MipMap
164 - property Name removed.
165 - BuildMipMaps is now a set of 3 values. None, GluBuildMipmaps and SGIS_generate_mipmap
167 - property name added. Only used in glForms!
169 - property FreeDataAfterGenTexture is now available as default (default = true)
170 - BuildMipmaps now implemented in TglBitmap1D (i've forgotten it)
171 - function MoveMemory replaced with function Move (little speed change)
172 - several calculations stored in variables (little speed change)
174 - property BuildMipsMaps added (default = true)
175 if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps
176 - property FreeDataAfterGenTexture added (default = true)
177 if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated.
178 - parameter DisableOtherTextureUnits of Bind removed
179 - parameter FreeDataAfterGeneration of GenTextures removed
181 - TglBitmap dosn't delete data if class was destroyed (fixed)
183 - Bind now enables TextureUnits (by params)
184 - GenTextures can leave data (by param)
185 - LoadTextures now optimal
187 - Performance optimization in AddFunc
188 - procedure Bind moved to subclasses
189 - Added new Class TglBitmap1D to support real OpenGL 1D Textures
191 - Texturefilter and texturewrap now also as defaults
192 Minfilter = GL_LINEAR_MIPMAP_LINEAR
193 Magfilter = GL_LINEAR
194 Wrap(str) = GL_CLAMP_TO_EDGE
195 - Added new format tfCompressed to create a compressed texture.
196 - propertys IsCompressed, TextureSize and IsResident added
197 IsCompressed and TextureSize only contains data from level 0
199 - Added function AddFunc to add PerPixelEffects to Image
200 - LoadFromFunc now based on AddFunc
201 - Invert now based on AddFunc
202 - SwapColors now based on AddFunc
204 - Added function FlipHorz
206 - Added function LaodFromFunc to create images with function
207 - Added function FlipVert
208 - Added internal format RGB(A) if GL_EXT_bgra or OpenGL 1.2 isn't supported
210 - Added Alphafunctions to calculate alpha per function
211 - Added Alpha from ColorKey using alphafunctions
213 - First full functionally Version of glBitmap
214 - Support for 24Bit and 32Bit TGA Pictures added
216 - begin of programming
217 ***********************************************************}
220 // Please uncomment the defines below to configure the glBitmap to your preferences.
221 // If you have configured the unit you can uncomment the warning above.
222 {$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
225 // Preferences ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
227 // activate to enable build-in OpenGL support with statically linked methods
228 // use dglOpenGL.pas if not enabled
229 {.$DEFINE GLB_NATIVE_OGL_STATIC}
231 // activate to enable build-in OpenGL support with dynamically linked methods
232 // use dglOpenGL.pas if not enabled
233 {.$DEFINE GLB_NATIVE_OGL_DYNAMIC}
236 // activate to enable the support for SDL_surfaces
239 // activate to enable the support for TBitmap from Delphi (not lazarus)
240 {.$DEFINE GLB_DELPHI}
242 // activate to enable the support for TLazIntfImage from Lazarus
243 {$DEFINE GLB_LAZARUS}
247 // activate to enable the support of SDL_image to load files. (READ ONLY)
248 // If you enable SDL_image all other libraries will be ignored!
249 {.$DEFINE GLB_SDL_IMAGE}
253 // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/
254 // if you enable pngimage the libPNG will be ignored
255 {.$DEFINE GLB_PNGIMAGE}
257 // activate to use the libPNG -> http://www.libpng.org/
258 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libpng
259 {.$DEFINE GLB_LIB_PNG}
263 // if you enable delphi jpegs the libJPEG will be ignored
264 {.$DEFINE GLB_DELPHI_JPEG}
266 // activate to use the libJPEG -> http://www.ijg.org/
267 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libjpeg
268 {.$DEFINE GLB_LIB_JPEG}
271 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
272 // PRIVATE: do not change anything! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
273 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
289 {$IF DEFINED(WIN32) or DEFINED(WIN64) or DEFINED(WINDOWS)}
291 {$ELSEIF DEFINED(LINUX)}
295 // native OpenGL Support
296 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) OR DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
297 {$DEFINE GLB_NATIVE_OGL}
300 // checking define combinations
302 {$IFDEF GLB_SDL_IMAGE}
304 {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
307 {$IFDEF GLB_PNGIMAGE}
308 {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
309 {$undef GLB_PNGIMAGE}
311 {$IFDEF GLB_DELPHI_JPEG}
312 {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
313 {$undef GLB_DELPHI_JPEG}
316 {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
319 {$IFDEF GLB_LIB_JPEG}
320 {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
321 {$undef GLB_LIB_JPEG}
324 {$DEFINE GLB_SUPPORT_PNG_READ}
325 {$DEFINE GLB_SUPPORT_JPEG_READ}
329 {$IFDEF GLB_PNGIMAGE}
331 {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'}
335 {$DEFINE GLB_SUPPORT_PNG_READ}
336 {$DEFINE GLB_SUPPORT_PNG_WRITE}
341 {$DEFINE GLB_SUPPORT_PNG_READ}
342 {$DEFINE GLB_SUPPORT_PNG_WRITE}
346 {$IFDEF GLB_DELPHI_JPEG}
347 {$IFDEF GLB_LIB_JPEG}
348 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
349 {$undef GLB_LIB_JPEG}
352 {$DEFINE GLB_SUPPORT_JPEG_READ}
353 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
357 {$IFDEF GLB_LIB_JPEG}
358 {$DEFINE GLB_SUPPORT_JPEG_READ}
359 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
363 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) AND DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
364 {$MESSAGE warn 'GLB_NATIVE_OGL_STATIC will be ignored because you enabled GLB_NATIVE_OGL_DYNAMIC'}
378 {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF}
379 {$IF DEFINED(GLB_WIN) AND
380 DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND}
382 {$IFDEF GLB_SDL} SDL, {$ENDIF}
383 {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, {$ENDIF}
384 {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF}
386 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
388 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
389 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
391 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
392 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
396 {$IFDEF GLB_NATIVE_OGL}
402 GL_EXTENSIONS = $1F03;
404 GL_TEXTURE_1D = $0DE0;
405 GL_TEXTURE_2D = $0DE1;
406 GL_TEXTURE_RECTANGLE = $84F5;
408 GL_TEXTURE_WIDTH = $1000;
409 GL_TEXTURE_HEIGHT = $1001;
410 GL_TEXTURE_INTERNAL_FORMAT = $1003;
418 GL_LUMINANCE = $1909;
419 GL_LUMINANCE4 = $803F;
420 GL_LUMINANCE8 = $8040;
421 GL_LUMINANCE12 = $8041;
422 GL_LUMINANCE16 = $8042;
424 GL_LUMINANCE_ALPHA = $190A;
425 GL_LUMINANCE4_ALPHA4 = $8043;
426 GL_LUMINANCE6_ALPHA2 = $8044;
427 GL_LUMINANCE8_ALPHA8 = $8045;
428 GL_LUMINANCE12_ALPHA4 = $8046;
429 GL_LUMINANCE12_ALPHA12 = $8047;
430 GL_LUMINANCE16_ALPHA16 = $8048;
453 GL_DEPTH_COMPONENT = $1902;
454 GL_DEPTH_COMPONENT16 = $81A5;
455 GL_DEPTH_COMPONENT24 = $81A6;
456 GL_DEPTH_COMPONENT32 = $81A7;
458 GL_COMPRESSED_RGB = $84ED;
459 GL_COMPRESSED_RGBA = $84EE;
460 GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
461 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
462 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
463 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
465 GL_UNSIGNED_BYTE = $1401;
466 GL_UNSIGNED_BYTE_3_3_2 = $8032;
467 GL_UNSIGNED_BYTE_2_3_3_REV = $8362;
469 GL_UNSIGNED_SHORT = $1403;
470 GL_UNSIGNED_SHORT_5_6_5 = $8363;
471 GL_UNSIGNED_SHORT_4_4_4_4 = $8033;
472 GL_UNSIGNED_SHORT_5_5_5_1 = $8034;
473 GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
474 GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
475 GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
477 GL_UNSIGNED_INT = $1405;
478 GL_UNSIGNED_INT_8_8_8_8 = $8035;
479 GL_UNSIGNED_INT_10_10_10_2 = $8036;
480 GL_UNSIGNED_INT_8_8_8_8_REV = $8367;
481 GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
484 GL_TEXTURE_MAG_FILTER = $2800;
485 GL_TEXTURE_MIN_FILTER = $2801;
487 GL_NEAREST_MIPMAP_NEAREST = $2700;
488 GL_NEAREST_MIPMAP_LINEAR = $2702;
490 GL_LINEAR_MIPMAP_NEAREST = $2701;
491 GL_LINEAR_MIPMAP_LINEAR = $2703;
494 GL_TEXTURE_WRAP_S = $2802;
495 GL_TEXTURE_WRAP_T = $2803;
496 GL_TEXTURE_WRAP_R = $8072;
499 GL_CLAMP_TO_EDGE = $812F;
500 GL_CLAMP_TO_BORDER = $812D;
501 GL_MIRRORED_REPEAT = $8370;
504 GL_GENERATE_MIPMAP = $8191;
505 GL_TEXTURE_BORDER_COLOR = $1004;
506 GL_MAX_TEXTURE_SIZE = $0D33;
507 GL_PACK_ALIGNMENT = $0D05;
508 GL_UNPACK_ALIGNMENT = $0CF5;
510 GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
511 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
513 {$IF DEFINED(GLB_WIN)}
514 libglu = 'glu32.dll';
515 libopengl = 'opengl32.dll';
516 {$ELSEIF DEFINED(GLB_LINUX)}
517 libglu = 'libGLU.so.1';
518 libopengl = 'libGL.so.1';
522 GLboolean = BYTEBOOL;
530 PGLboolean = ^GLboolean;
535 TglCompressedTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
536 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}
537 TglGetCompressedTexImage = procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
539 {$IF DEFINED(GLB_WIN)}
540 TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall;
541 {$ELSEIF DEFINED(GLB_LINUX)}
542 TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl;
543 TglXGetProcAddressARB = function(const name: PAnsiChar): pointer; cdecl;
546 {$IF DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
547 TglEnable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
548 TglDisable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
550 TglGetString = function(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
551 TglGetIntegerv = procedure(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
553 TglTexParameteri = procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
554 TglTexParameterfv = procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
555 TglGetTexParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
556 TglGetTexParameterfv = procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
557 TglGetTexLevelParameteriv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
558 TglGetTexLevelParameterfv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
560 TglGenTextures = procedure(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
561 TglBindTexture = procedure(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
562 TglDeleteTextures = procedure(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
564 TglAreTexturesResident = function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
565 TglReadPixels = procedure(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
566 TglPixelStorei = procedure(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
568 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}
569 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}
570 TglGetTexImage = procedure(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
572 TgluBuild1DMipmaps = function(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
573 TgluBuild2DMipmaps = function(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
575 {$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)}
576 procedure glEnable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
577 procedure glDisable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
579 function glGetString(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
580 procedure glGetIntegerv(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
582 procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
583 procedure glTexParameterfv(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
584 procedure glGetTexParameteriv(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
585 procedure glGetTexParameterfv(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
586 procedure glGetTexLevelParameteriv(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
587 procedure glGetTexLevelParameterfv(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
589 procedure glGenTextures(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
590 procedure glBindTexture(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
591 procedure glDeleteTextures(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
593 function glAreTexturesResident(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
594 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;
595 procedure glPixelStorei(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
597 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;
598 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;
599 procedure glGetTexImage(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
601 function gluBuild1DMipmaps(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
602 function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
611 GL_SGIS_generate_mipmap,
613 GL_ARB_texture_border_clamp,
614 GL_ARB_texture_mirrored_repeat,
615 GL_ARB_texture_rectangle,
616 GL_ARB_texture_non_power_of_two,
618 GL_IBM_texture_mirrored_repeat,
620 GL_NV_texture_rectangle,
622 GL_EXT_texture_edge_clamp,
623 GL_EXT_texture_rectangle,
624 GL_EXT_texture_filter_anisotropic: Boolean;
626 glCompressedTexImage1D: TglCompressedTexImage1D;
627 glCompressedTexImage2D: TglCompressedTexImage2D;
628 glGetCompressedTexImage: TglGetCompressedTexImage;
630 {$IF DEFINED(GLB_WIN)}
631 wglGetProcAddress: TwglGetProcAddress;
632 {$ELSEIF DEFINED(GLB_LINUX)}
633 glXGetProcAddress: TglXGetProcAddress;
634 glXGetProcAddressARB: TglXGetProcAddress;
637 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
639 glDisable: TglDisable;
641 glGetString: TglGetString;
642 glGetIntegerv: TglGetIntegerv;
644 glTexParameteri: TglTexParameteri;
645 glTexParameterfv: TglTexParameterfv;
646 glGetTexParameteriv: TglGetTexParameteriv;
647 glGetTexParameterfv: TglGetTexParameterfv;
648 glGetTexLevelParameteriv: TglGetTexLevelParameteriv;
649 glGetTexLevelParameterfv: TglGetTexLevelParameterfv;
651 glGenTextures: TglGenTextures;
652 glBindTexture: TglBindTexture;
653 glDeleteTextures: TglDeleteTextures;
655 glAreTexturesResident: TglAreTexturesResident;
656 glReadPixels: TglReadPixels;
657 glPixelStorei: TglPixelStorei;
659 glTexImage1D: TglTexImage1D;
660 glTexImage2D: TglTexImage2D;
661 glGetTexImage: TglGetTexImage;
663 gluBuild1DMipmaps: TgluBuild1DMipmaps;
664 gluBuild2DMipmaps: TgluBuild2DMipmaps;
669 ////////////////////////////////////////////////////////////////////////////////////////////////////
671 tfEmpty = 0, //must be smallest value!
687 tfLuminance12Alpha12,
688 tfLuminance16Alpha16,
732 TglBitmapFileType = (
733 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
734 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
738 TglBitmapFileTypes = set of TglBitmapFileType;
745 TglBitmapNormalMapFunc = (
751 ////////////////////////////////////////////////////////////////////////////////////////////////////
752 EglBitmapException = class(Exception);
753 EglBitmapSizeToLargeException = class(EglBitmapException);
754 EglBitmapNonPowerOfTwoException = class(EglBitmapException);
755 EglBitmapUnsupportedFormat = class(EglBitmapException)
756 constructor Create(const aFormat: TglBitmapFormat); overload;
757 constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload;
760 ////////////////////////////////////////////////////////////////////////////////////////////////////
761 TglBitmapColorRec = packed record
763 0: (r, g, b, a: Cardinal);
764 1: (arr: array[0..3] of Cardinal);
767 TglBitmapPixelData = packed record
768 Data, Range: TglBitmapColorRec;
769 Format: TglBitmapFormat;
771 PglBitmapPixelData = ^TglBitmapPixelData;
773 ////////////////////////////////////////////////////////////////////////////////////////////////////
774 TglBitmapPixelPositionFields = set of (ffX, ffY);
775 TglBitmapPixelPosition = record
776 Fields : TglBitmapPixelPositionFields;
781 ////////////////////////////////////////////////////////////////////////////////////////////////////
783 TglBitmapFunctionRec = record
785 Size: TglBitmapPixelPosition;
786 Position: TglBitmapPixelPosition;
787 Source: TglBitmapPixelData;
788 Dest: TglBitmapPixelData;
791 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
793 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
798 fAnisotropic: Integer;
799 fDeleteTextureOnFree: Boolean;
800 fFreeDataAfterGenTexture: Boolean;
802 fIsResident: Boolean;
803 fBorderColor: array[0..3] of Single;
805 fDimension: TglBitmapPixelPosition;
806 fMipMap: TglBitmapMipMap;
807 fFormat: TglBitmapFormat;
814 fFilterMin: Cardinal;
815 fFilterMag: Cardinal;
825 fCustomNameW: WideString;
826 fCustomData: Pointer;
829 function GetWidth: Integer; virtual;
830 function GetHeight: Integer; virtual;
832 function GetFileWidth: Integer; virtual;
833 function GetFileHeight: Integer; virtual;
836 procedure SetCustomData(const aValue: Pointer);
837 procedure SetCustomName(const aValue: String);
838 procedure SetCustomNameW(const aValue: WideString);
839 procedure SetDeleteTextureOnFree(const aValue: Boolean);
840 procedure SetFormat(const aValue: TglBitmapFormat);
841 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
842 procedure SetID(const aValue: Cardinal);
843 procedure SetMipMap(const aValue: TglBitmapMipMap);
844 procedure SetTarget(const aValue: Cardinal);
845 procedure SetAnisotropic(const aValue: Integer);
848 procedure SetupParameters(out aBuildWithGlu: Boolean);
849 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
850 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; //be careful, aData could be freed by this method
851 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
853 function FlipHorz: Boolean; virtual;
854 function FlipVert: Boolean; virtual;
856 property Width: Integer read GetWidth;
857 property Height: Integer read GetHeight;
859 property FileWidth: Integer read GetFileWidth;
860 property FileHeight: Integer read GetFileHeight;
863 property ID: Cardinal read fID write SetID;
864 property Target: Cardinal read fTarget write SetTarget;
865 property Format: TglBitmapFormat read fFormat write SetFormat;
866 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
867 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
869 property Filename: String read fFilename;
870 property CustomName: String read fCustomName write SetCustomName;
871 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
872 property CustomData: Pointer read fCustomData write SetCustomData;
874 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
875 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
877 property Dimension: TglBitmapPixelPosition read fDimension;
878 property Data: PByte read fData;
879 property IsResident: Boolean read fIsResident;
881 procedure AfterConstruction; override;
882 procedure BeforeDestruction; override;
884 procedure PrepareResType(var aResource: String; var aResType: PChar);
887 procedure LoadFromFile(const aFilename: String);
888 procedure LoadFromStream(const aStream: TStream); virtual;
889 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
890 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil);
891 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil);
892 procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
895 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
896 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
899 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
900 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
901 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
905 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
906 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
907 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
908 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
909 const aArgs: Pointer = nil): Boolean;
913 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
914 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
915 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
916 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
917 const aArgs: Pointer = nil): Boolean;
921 function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
922 function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
923 function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
924 function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil;
925 const aArgs: Pointer = nil): Boolean;
928 function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil;
929 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
930 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
931 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
933 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
934 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
935 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
936 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
938 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
939 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
940 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
942 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
943 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
944 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
946 function RemoveAlpha: Boolean; virtual;
949 function Clone: TglBitmap;
950 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
951 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
952 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
956 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
957 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
958 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
961 procedure SetFilter(const aMin, aMag: Cardinal);
963 const S: Cardinal = GL_CLAMP_TO_EDGE;
964 const T: Cardinal = GL_CLAMP_TO_EDGE;
965 const R: Cardinal = GL_CLAMP_TO_EDGE);
967 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
968 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
971 constructor Create; overload;
972 constructor Create(const aFileName: String); overload;
973 constructor Create(const aStream: TStream); overload;
974 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload;
975 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
976 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
977 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
979 {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF}
980 {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF}
982 {$IFDEF GLB_SUPPORT_JPEG_READ} function LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF}
983 {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF}
985 function LoadBMP(const aStream: TStream): Boolean; virtual;
986 procedure SaveBMP(const aStream: TStream); virtual;
988 function LoadTGA(const aStream: TStream): Boolean; virtual;
989 procedure SaveTGA(const aStream: TStream); virtual;
991 function LoadDDS(const aStream: TStream): Boolean; virtual;
992 procedure SaveDDS(const aStream: TStream); virtual;
995 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
996 TglBitmap1D = class(TglBitmap)
998 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
999 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1000 procedure UploadData(const aBuildWithGlu: Boolean);
1003 procedure AfterConstruction; override;
1004 function FlipHorz: Boolean; override;
1005 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1008 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1009 TglBitmap2D = class(TglBitmap)
1011 fLines: array of PByte;
1012 function GetScanline(const aIndex: Integer): Pointer;
1013 procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
1014 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1015 procedure UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
1019 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
1021 procedure AfterConstruction; override;
1023 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
1024 procedure GetDataFromTexture;
1025 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1027 function FlipHorz: Boolean; override;
1028 function FlipVert: Boolean; override;
1030 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
1031 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1034 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1035 TglBitmapCubeMap = class(TglBitmap2D)
1038 procedure GenTexture(const aTestTextureSize: Boolean = true); reintroduce;
1040 procedure AfterConstruction; override;
1041 procedure GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean = true);
1042 procedure Bind(const aEnableTexCoordsGen: Boolean = true; const aEnableTextureUnit: Boolean = true); reintroduce; virtual;
1043 procedure Unbind(const aDisableTexCoordsGen: Boolean = true; const aDisableTextureUnit: Boolean = true); reintroduce; virtual;
1046 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1047 TglBitmapNormalMap = class(TglBitmapCubeMap)
1049 procedure AfterConstruction; override;
1050 procedure GenerateNormalMap(const aSize: Integer = 32; const aTestTextureSize: Boolean = true);
1054 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1056 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1057 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1058 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1059 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1060 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1061 procedure glBitmapSetDefaultWrap(
1062 const S: Cardinal = GL_CLAMP_TO_EDGE;
1063 const T: Cardinal = GL_CLAMP_TO_EDGE;
1064 const R: Cardinal = GL_CLAMP_TO_EDGE);
1066 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1067 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1068 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1069 function glBitmapGetDefaultFormat: TglBitmapFormat;
1070 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1071 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1073 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1074 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1075 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1078 glBitmapDefaultDeleteTextureOnFree: Boolean;
1079 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1080 glBitmapDefaultFormat: TglBitmapFormat;
1081 glBitmapDefaultMipmap: TglBitmapMipMap;
1082 glBitmapDefaultFilterMin: Cardinal;
1083 glBitmapDefaultFilterMag: Cardinal;
1084 glBitmapDefaultWrapS: Cardinal;
1085 glBitmapDefaultWrapT: Cardinal;
1086 glBitmapDefaultWrapR: Cardinal;
1089 function CreateGrayPalette: HPALETTE;
1095 Math, syncobjs, typinfo;
1099 QWord = System.UInt64;
1106 ////////////////////////////////////////////////////////////////////////////////////////////////////
1107 TShiftRec = packed record
1109 0: (r, g, b, a: Byte);
1110 1: (arr: array[0..3] of Byte);
1113 TFormatDescriptor = class(TObject)
1115 function GetRedMask: QWord;
1116 function GetGreenMask: QWord;
1117 function GetBlueMask: QWord;
1118 function GetAlphaMask: QWord;
1120 fFormat: TglBitmapFormat;
1121 fWithAlpha: TglBitmapFormat;
1122 fWithoutAlpha: TglBitmapFormat;
1123 fRGBInverted: TglBitmapFormat;
1124 fUncompressed: TglBitmapFormat;
1126 fIsCompressed: Boolean;
1128 fRange: TglBitmapColorRec;
1131 fglFormat: Cardinal;
1132 fglInternalFormat: Cardinal;
1133 fglDataFormat: Cardinal;
1135 function GetComponents: Integer; virtual;
1137 property Format: TglBitmapFormat read fFormat;
1138 property WithAlpha: TglBitmapFormat read fWithAlpha;
1139 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1140 property RGBInverted: TglBitmapFormat read fRGBInverted;
1141 property Components: Integer read GetComponents;
1142 property PixelSize: Single read fPixelSize;
1143 property IsCompressed: Boolean read fIsCompressed;
1145 property glFormat: Cardinal read fglFormat;
1146 property glInternalFormat: Cardinal read fglInternalFormat;
1147 property glDataFormat: Cardinal read fglDataFormat;
1149 property Range: TglBitmapColorRec read fRange;
1150 property Shift: TShiftRec read fShift;
1152 property RedMask: QWord read GetRedMask;
1153 property GreenMask: QWord read GetGreenMask;
1154 property BlueMask: QWord read GetBlueMask;
1155 property AlphaMask: QWord read GetAlphaMask;
1157 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1158 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1160 function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual;
1161 function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
1163 function CreateMappingData: Pointer; virtual;
1164 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1166 function IsEmpty: Boolean; virtual;
1167 function HasAlpha: Boolean; virtual;
1168 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual;
1170 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1172 constructor Create; virtual;
1174 class procedure Init;
1175 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1176 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1177 class procedure Clear;
1178 class procedure Finalize;
1180 TFormatDescriptorClass = class of TFormatDescriptor;
1182 TfdEmpty = class(TFormatDescriptor);
1184 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1185 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1186 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1187 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1188 constructor Create; override;
1191 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1192 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1193 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1194 constructor Create; override;
1197 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1198 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1199 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1200 constructor Create; override;
1203 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1204 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1205 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1206 constructor Create; override;
1209 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1210 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1211 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1212 constructor Create; override;
1215 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1216 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1217 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1218 constructor Create; override;
1221 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1222 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1223 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1224 constructor Create; override;
1227 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1228 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1229 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1230 constructor Create; override;
1233 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1234 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1235 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1236 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1237 constructor Create; override;
1240 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1241 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1242 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1243 constructor Create; override;
1246 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1247 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1248 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1249 constructor Create; override;
1252 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1253 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1254 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1255 constructor Create; override;
1258 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1259 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1260 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1261 constructor Create; override;
1264 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1265 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1266 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1267 constructor Create; override;
1270 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1271 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1272 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1273 constructor Create; override;
1276 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1277 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1278 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1279 constructor Create; override;
1282 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1283 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1284 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1285 constructor Create; override;
1288 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1289 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1290 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1291 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1292 constructor Create; override;
1295 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1296 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1297 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1298 constructor Create; override;
1301 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1302 TfdAlpha4 = class(TfdAlpha_UB1)
1303 constructor Create; override;
1306 TfdAlpha8 = class(TfdAlpha_UB1)
1307 constructor Create; override;
1310 TfdAlpha12 = class(TfdAlpha_US1)
1311 constructor Create; override;
1314 TfdAlpha16 = class(TfdAlpha_US1)
1315 constructor Create; override;
1318 TfdLuminance4 = class(TfdLuminance_UB1)
1319 constructor Create; override;
1322 TfdLuminance8 = class(TfdLuminance_UB1)
1323 constructor Create; override;
1326 TfdLuminance12 = class(TfdLuminance_US1)
1327 constructor Create; override;
1330 TfdLuminance16 = class(TfdLuminance_US1)
1331 constructor Create; override;
1334 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1335 constructor Create; override;
1338 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1339 constructor Create; override;
1342 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1343 constructor Create; override;
1346 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1347 constructor Create; override;
1350 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1351 constructor Create; override;
1354 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1355 constructor Create; override;
1358 TfdR3G3B2 = class(TfdUniversal_UB1)
1359 constructor Create; override;
1362 TfdRGB4 = class(TfdUniversal_US1)
1363 constructor Create; override;
1366 TfdR5G6B5 = class(TfdUniversal_US1)
1367 constructor Create; override;
1370 TfdRGB5 = class(TfdUniversal_US1)
1371 constructor Create; override;
1374 TfdRGB8 = class(TfdRGB_UB3)
1375 constructor Create; override;
1378 TfdRGB10 = class(TfdUniversal_UI1)
1379 constructor Create; override;
1382 TfdRGB12 = class(TfdRGB_US3)
1383 constructor Create; override;
1386 TfdRGB16 = class(TfdRGB_US3)
1387 constructor Create; override;
1390 TfdRGBA2 = class(TfdRGBA_UB4)
1391 constructor Create; override;
1394 TfdRGBA4 = class(TfdUniversal_US1)
1395 constructor Create; override;
1398 TfdRGB5A1 = class(TfdUniversal_US1)
1399 constructor Create; override;
1402 TfdRGBA8 = class(TfdRGBA_UB4)
1403 constructor Create; override;
1406 TfdRGB10A2 = class(TfdUniversal_UI1)
1407 constructor Create; override;
1410 TfdRGBA12 = class(TfdRGBA_US4)
1411 constructor Create; override;
1414 TfdRGBA16 = class(TfdRGBA_US4)
1415 constructor Create; override;
1418 TfdBGR4 = class(TfdUniversal_US1)
1419 constructor Create; override;
1422 TfdB5G6R5 = class(TfdUniversal_US1)
1423 constructor Create; override;
1426 TfdBGR5 = class(TfdUniversal_US1)
1427 constructor Create; override;
1430 TfdBGR8 = class(TfdBGR_UB3)
1431 constructor Create; override;
1434 TfdBGR10 = class(TfdUniversal_UI1)
1435 constructor Create; override;
1438 TfdBGR12 = class(TfdBGR_US3)
1439 constructor Create; override;
1442 TfdBGR16 = class(TfdBGR_US3)
1443 constructor Create; override;
1446 TfdBGRA2 = class(TfdBGRA_UB4)
1447 constructor Create; override;
1450 TfdBGRA4 = class(TfdUniversal_US1)
1451 constructor Create; override;
1454 TfdBGR5A1 = class(TfdUniversal_US1)
1455 constructor Create; override;
1458 TfdBGRA8 = class(TfdBGRA_UB4)
1459 constructor Create; override;
1462 TfdBGR10A2 = class(TfdUniversal_UI1)
1463 constructor Create; override;
1466 TfdBGRA12 = class(TfdBGRA_US4)
1467 constructor Create; override;
1470 TfdBGRA16 = class(TfdBGRA_US4)
1471 constructor Create; override;
1474 TfdDepth16 = class(TfdDepth_US1)
1475 constructor Create; override;
1478 TfdDepth24 = class(TfdDepth_UI1)
1479 constructor Create; override;
1482 TfdDepth32 = class(TfdDepth_UI1)
1483 constructor Create; override;
1486 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1487 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1488 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1489 constructor Create; override;
1492 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1493 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1494 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1495 constructor Create; override;
1498 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1499 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1500 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1501 constructor Create; override;
1504 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1505 TbmpBitfieldFormat = class(TFormatDescriptor)
1507 procedure SetRedMask (const aValue: QWord);
1508 procedure SetGreenMask(const aValue: QWord);
1509 procedure SetBlueMask (const aValue: QWord);
1510 procedure SetAlphaMask(const aValue: QWord);
1512 procedure Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte);
1514 property RedMask: QWord read GetRedMask write SetRedMask;
1515 property GreenMask: QWord read GetGreenMask write SetGreenMask;
1516 property BlueMask: QWord read GetBlueMask write SetBlueMask;
1517 property AlphaMask: QWord read GetAlphaMask write SetAlphaMask;
1519 property PixelSize: Single read fPixelSize write fPixelSize;
1521 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1522 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1525 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1526 TbmpColorTableEnty = packed record
1529 TbmpColorTable = array of TbmpColorTableEnty;
1530 TbmpColorTableFormat = class(TFormatDescriptor)
1532 fColorTable: TbmpColorTable;
1534 property PixelSize: Single read fPixelSize write fPixelSize;
1535 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1536 property Range: TglBitmapColorRec read fRange write fRange;
1537 property Shift: TShiftRec read fShift write fShift;
1538 property Format: TglBitmapFormat read fFormat write fFormat;
1540 procedure CreateColorTable;
1542 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1543 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1544 destructor Destroy; override;
1548 LUMINANCE_WEIGHT_R = 0.30;
1549 LUMINANCE_WEIGHT_G = 0.59;
1550 LUMINANCE_WEIGHT_B = 0.11;
1552 ALPHA_WEIGHT_R = 0.30;
1553 ALPHA_WEIGHT_G = 0.59;
1554 ALPHA_WEIGHT_B = 0.11;
1556 DEPTH_WEIGHT_R = 0.333333333;
1557 DEPTH_WEIGHT_G = 0.333333333;
1558 DEPTH_WEIGHT_B = 0.333333333;
1560 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1562 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1575 TfdLuminance4Alpha4,
1576 TfdLuminance6Alpha2,
1577 TfdLuminance8Alpha8,
1578 TfdLuminance12Alpha4,
1579 TfdLuminance12Alpha12,
1580 TfdLuminance16Alpha16,
1625 FormatDescriptorCS: TCriticalSection;
1626 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1628 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1629 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1631 inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1634 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1635 constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat);
1637 inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1640 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1641 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1643 result.Fields := [];
1646 result.Fields := result.Fields + [ffX];
1648 result.Fields := result.Fields + [ffY];
1650 result.X := Max(0, X);
1651 result.Y := Max(0, Y);
1654 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1655 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1663 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1664 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1669 for i := 0 to high(r1.arr) do
1670 if (r1.arr[i] <> r2.arr[i]) then
1675 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1676 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1684 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1685 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1694 tfR3G3B2, tfLuminance8,
1697 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1698 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1704 tfRGB10, tfRGB10A2, tfRGBA8,
1705 tfBGR10, tfBGR10A2, tfBGRA8]) then
1706 result := result + [ftBMP];
1710 tfLuminance8, tfAlpha8,
1713 tfLuminance16, tfLuminance8Alpha8,
1714 tfRGB5, tfRGB5A1, tfRGBA4,
1715 tfBGR5, tfBGR5A1, tfBGRA4,
1721 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1722 result := result + [ftTGA];
1726 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1727 tfR3G3B2, tfRGBA2, tfBGRA2,
1730 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1731 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1732 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1738 tfLuminance16Alpha16,
1743 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1744 result := result + [ftDDS];
1746 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1748 tfAlpha8, tfLuminance8, tfLuminance8Alpha8,
1750 tfBGR8, tfBGRA8] then
1751 result := result + [ftPNG];
1754 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1755 if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then
1756 result := result + [ftJPEG];
1760 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1761 function IsPowerOfTwo(aNumber: Integer): Boolean;
1763 while (aNumber and 1) = 0 do
1764 aNumber := aNumber shr 1;
1765 result := aNumber = 1;
1768 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1769 function GetTopMostBit(aBitSet: QWord): Integer;
1772 while aBitSet > 0 do begin
1774 aBitSet := aBitSet shr 1;
1778 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1779 function CountSetBits(aBitSet: QWord): Integer;
1782 while aBitSet > 0 do begin
1783 if (aBitSet and 1) = 1 then
1785 aBitSet := aBitSet shr 1;
1789 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1790 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1793 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1794 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1795 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1798 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1799 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1802 DEPTH_WEIGHT_R * aPixel.Data.r +
1803 DEPTH_WEIGHT_G * aPixel.Data.g +
1804 DEPTH_WEIGHT_B * aPixel.Data.b);
1807 {$IFDEF GLB_NATIVE_OGL}
1808 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1809 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1810 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1812 GL_LibHandle: Pointer = nil;
1814 function glbGetProcAddress(aProcName: PChar; aLibHandle: Pointer = nil): Pointer;
1816 if not Assigned(aLibHandle) then
1817 aLibHandle := GL_LibHandle;
1819 {$IF DEFINED(GLB_WIN)}
1820 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1821 if Assigned(result) then
1824 if Assigned(wglGetProcAddress) then
1825 result := wglGetProcAddress(aProcName);
1826 {$ELSEIF DEFINED(GLB_LINUX)}
1827 if Assigned(glXGetProcAddress) then begin
1828 result := glXGetProcAddress(aProcName);
1829 if Assigned(result) then
1833 if Assigned(glXGetProcAddressARB) then begin
1834 result := glXGetProcAddressARB(aProcName);
1835 if Assigned(result) then
1839 result := dlsym(aLibHandle, aProcName);
1841 if not Assigned(result) then
1842 raise EglBitmapException.Create('unable to load procedure form library: ' + aProcName);
1845 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1847 GLU_LibHandle: Pointer = nil;
1848 OpenGLInitialized: Boolean;
1849 InitOpenGLCS: TCriticalSection;
1851 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1852 procedure glbInitOpenGL;
1854 ////////////////////////////////////////////////////////////////////////////////
1855 function glbLoadLibrary(const aName: PChar): Pointer;
1857 {$IF DEFINED(GLB_WIN)}
1858 result := {%H-}Pointer(LoadLibrary(aName));
1859 {$ELSEIF DEFINED(GLB_LINUX)}
1860 result := dlopen(Name, RTLD_LAZY);
1866 ////////////////////////////////////////////////////////////////////////////////
1867 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
1870 if not Assigned(aLibHandle) then
1873 {$IF DEFINED(GLB_WIN)}
1874 Result := FreeLibrary({%H-}HINST(aLibHandle));
1875 {$ELSEIF DEFINED(GLB_LINUX)}
1876 Result := dlclose(aLibHandle) = 0;
1881 if Assigned(GL_LibHandle) then
1882 glbFreeLibrary(GL_LibHandle);
1884 if Assigned(GLU_LibHandle) then
1885 glbFreeLibrary(GLU_LibHandle);
1887 GL_LibHandle := glbLoadLibrary(libopengl);
1888 if not Assigned(GL_LibHandle) then
1889 raise EglBitmapException.Create('unable to load library: ' + libopengl);
1891 GLU_LibHandle := glbLoadLibrary(libglu);
1892 if not Assigned(GLU_LibHandle) then
1893 raise EglBitmapException.Create('unable to load library: ' + libglu);
1896 {$IF DEFINED(GLB_WIN)}
1897 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
1898 {$ELSEIF DEFINED(GLB_LINUX)}
1899 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
1900 glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
1903 glEnable := glbGetProcAddress('glEnable');
1904 glDisable := glbGetProcAddress('glDisable');
1905 glGetString := glbGetProcAddress('glGetString');
1906 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
1907 glTexParameteri := glbGetProcAddress('glTexParameteri');
1908 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
1909 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
1910 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
1911 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
1912 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
1913 glGenTextures := glbGetProcAddress('glGenTextures');
1914 glBindTexture := glbGetProcAddress('glBindTexture');
1915 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
1916 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
1917 glReadPixels := glbGetProcAddress('glReadPixels');
1918 glPixelStorei := glbGetProcAddress('glPixelStorei');
1919 glTexImage1D := glbGetProcAddress('glTexImage1D');
1920 glTexImage2D := glbGetProcAddress('glTexImage2D');
1921 glGetTexImage := glbGetProcAddress('glGetTexImage');
1923 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
1924 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
1926 glbFreeLibrary(GL_LibHandle);
1927 glbFreeLibrary(GLU_LibHandle);
1932 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1933 procedure glbReadOpenGLExtensions;
1936 MajorVersion, MinorVersion: Integer;
1938 ///////////////////////////////////////////////////////////////////////////////////////////
1939 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
1946 Separator := Pos(AnsiString('.'), aBuffer);
1947 if (Separator > 1) and (Separator < Length(aBuffer)) and
1948 (aBuffer[Separator - 1] in ['0'..'9']) and
1949 (aBuffer[Separator + 1] in ['0'..'9']) then begin
1952 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
1955 Delete(aBuffer, 1, Separator);
1956 Separator := Pos(AnsiString('.'), aBuffer) + 1;
1958 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
1961 Delete(aBuffer, Separator, 255);
1962 Separator := Pos(AnsiString('.'), aBuffer);
1964 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
1965 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
1969 ///////////////////////////////////////////////////////////////////////////////////////////
1970 function CheckExtension(const Extension: AnsiString): Boolean;
1974 ExtPos := Pos(Extension, Buffer);
1975 result := ExtPos > 0;
1977 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
1981 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1984 if not OpenGLInitialized then begin
1986 OpenGLInitialized := true;
1994 Buffer := glGetString(GL_VERSION);
1995 TrimVersionString(Buffer, MajorVersion, MinorVersion);
1997 GL_VERSION_1_2 := false;
1998 GL_VERSION_1_3 := false;
1999 GL_VERSION_1_4 := false;
2000 GL_VERSION_2_0 := false;
2001 if MajorVersion = 1 then begin
2002 if MinorVersion >= 2 then
2003 GL_VERSION_1_2 := true;
2005 if MinorVersion >= 3 then
2006 GL_VERSION_1_3 := true;
2008 if MinorVersion >= 4 then
2009 GL_VERSION_1_4 := true;
2010 end else if MajorVersion >= 2 then begin
2011 GL_VERSION_1_2 := true;
2012 GL_VERSION_1_3 := true;
2013 GL_VERSION_1_4 := true;
2014 GL_VERSION_2_0 := true;
2018 Buffer := glGetString(GL_EXTENSIONS);
2019 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2020 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2021 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2022 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2023 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2024 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2025 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2026 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2027 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2028 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2030 if GL_VERSION_1_3 then begin
2031 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2032 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2033 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2035 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB');
2036 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB');
2037 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB');
2042 {$IFDEF GLB_SDL_IMAGE}
2043 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2044 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2045 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2046 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2048 result := TStream(context^.unknown.data1).Seek(offset, whence);
2051 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2053 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2056 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2058 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2061 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2066 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2068 result := SDL_AllocRW;
2070 if result = nil then
2071 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2073 result^.seek := glBitmapRWseek;
2074 result^.read := glBitmapRWread;
2075 result^.write := glBitmapRWwrite;
2076 result^.close := glBitmapRWclose;
2077 result^.unknown.data1 := Stream;
2081 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2082 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2084 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2087 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2088 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2090 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2093 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2094 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2096 glBitmapDefaultMipmap := aValue;
2099 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2100 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2102 glBitmapDefaultFormat := aFormat;
2105 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2106 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2108 glBitmapDefaultFilterMin := aMin;
2109 glBitmapDefaultFilterMag := aMag;
2112 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2113 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2115 glBitmapDefaultWrapS := S;
2116 glBitmapDefaultWrapT := T;
2117 glBitmapDefaultWrapR := R;
2120 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2121 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2123 result := glBitmapDefaultDeleteTextureOnFree;
2126 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2127 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2129 result := glBitmapDefaultFreeDataAfterGenTextures;
2132 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2133 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2135 result := glBitmapDefaultMipmap;
2138 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2139 function glBitmapGetDefaultFormat: TglBitmapFormat;
2141 result := glBitmapDefaultFormat;
2144 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2145 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
2147 aMin := glBitmapDefaultFilterMin;
2148 aMag := glBitmapDefaultFilterMag;
2151 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2152 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
2154 S := glBitmapDefaultWrapS;
2155 T := glBitmapDefaultWrapT;
2156 R := glBitmapDefaultWrapR;
2159 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2160 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2161 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2162 function TFormatDescriptor.GetRedMask: QWord;
2164 result := fRange.r shl fShift.r;
2167 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2168 function TFormatDescriptor.GetGreenMask: QWord;
2170 result := fRange.g shl fShift.g;
2173 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2174 function TFormatDescriptor.GetBlueMask: QWord;
2176 result := fRange.b shl fShift.b;
2179 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2180 function TFormatDescriptor.GetAlphaMask: QWord;
2182 result := fRange.a shl fShift.a;
2185 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2186 function TFormatDescriptor.GetComponents: Integer;
2192 if (fRange.arr[i] > 0) then
2196 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2197 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2201 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2202 w := Max(1, aSize.X);
2203 h := Max(1, aSize.Y);
2204 result := GetSize(w, h);
2209 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2210 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2213 if (aWidth <= 0) or (aHeight <= 0) then
2215 result := Ceil(aWidth * aHeight * fPixelSize);
2218 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2219 function TFormatDescriptor.CreateMappingData: Pointer;
2224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2225 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2230 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2231 function TFormatDescriptor.IsEmpty: Boolean;
2233 result := (fFormat = tfEmpty);
2236 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2237 function TFormatDescriptor.HasAlpha: Boolean;
2239 result := (fRange.a > 0);
2242 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2243 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2246 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2247 raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
2248 if (aRedMask <> RedMask) then
2250 if (aGreenMask <> GreenMask) then
2252 if (aBlueMask <> BlueMask) then
2254 if (aAlphaMask <> AlphaMask) then
2259 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2260 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2262 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2263 aPixel.Data := fRange;
2264 aPixel.Range := fRange;
2265 aPixel.Format := fFormat;
2268 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2269 constructor TFormatDescriptor.Create;
2274 fWithAlpha := tfEmpty;
2275 fWithoutAlpha := tfEmpty;
2276 fRGBInverted := tfEmpty;
2277 fUncompressed := tfEmpty;
2279 fIsCompressed := false;
2282 fglInternalFormat := 0;
2285 FillChar(fRange, 0, SizeOf(fRange));
2286 FillChar(fShift, 0, SizeOf(fShift));
2289 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2290 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2291 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2292 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2294 aData^ := aPixel.Data.a;
2298 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2303 aPixel.Data.a := aData^;
2307 constructor TfdAlpha_UB1.Create;
2312 fglFormat := GL_ALPHA;
2313 fglDataFormat := GL_UNSIGNED_BYTE;
2316 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2317 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2318 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2319 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2321 aData^ := LuminanceWeight(aPixel);
2325 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2327 aPixel.Data.r := aData^;
2328 aPixel.Data.g := aData^;
2329 aPixel.Data.b := aData^;
2334 constructor TfdLuminance_UB1.Create;
2341 fglFormat := GL_LUMINANCE;
2342 fglDataFormat := GL_UNSIGNED_BYTE;
2345 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2346 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2347 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2348 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2354 if (fRange.arr[i] > 0) then
2355 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2359 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2364 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2368 constructor TfdUniversal_UB1.Create;
2374 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2375 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2376 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2377 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2379 inherited Map(aPixel, aData, aMapData);
2380 aData^ := aPixel.Data.a;
2384 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2386 inherited Unmap(aData, aPixel, aMapData);
2387 aPixel.Data.a := aData^;
2391 constructor TfdLuminanceAlpha_UB2.Create;
2397 fglFormat := GL_LUMINANCE_ALPHA;
2398 fglDataFormat := GL_UNSIGNED_BYTE;
2401 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2402 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2403 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2404 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2406 aData^ := aPixel.Data.r;
2408 aData^ := aPixel.Data.g;
2410 aData^ := aPixel.Data.b;
2414 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2416 aPixel.Data.r := aData^;
2418 aPixel.Data.g := aData^;
2420 aPixel.Data.b := aData^;
2425 constructor TfdRGB_UB3.Create;
2435 fglFormat := GL_RGB;
2436 fglDataFormat := GL_UNSIGNED_BYTE;
2439 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2440 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2441 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2442 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2444 aData^ := aPixel.Data.b;
2446 aData^ := aPixel.Data.g;
2448 aData^ := aPixel.Data.r;
2452 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2454 aPixel.Data.b := aData^;
2456 aPixel.Data.g := aData^;
2458 aPixel.Data.r := aData^;
2463 constructor TfdBGR_UB3.Create;
2472 fglFormat := GL_BGR;
2473 fglDataFormat := GL_UNSIGNED_BYTE;
2476 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2477 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2478 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2479 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2481 inherited Map(aPixel, aData, aMapData);
2482 aData^ := aPixel.Data.a;
2486 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2488 inherited Unmap(aData, aPixel, aMapData);
2489 aPixel.Data.a := aData^;
2493 constructor TfdRGBA_UB4.Create;
2499 fglFormat := GL_RGBA;
2500 fglDataFormat := GL_UNSIGNED_BYTE;
2503 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2504 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2505 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2506 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2508 inherited Map(aPixel, aData, aMapData);
2509 aData^ := aPixel.Data.a;
2513 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2515 inherited Unmap(aData, aPixel, aMapData);
2516 aPixel.Data.a := aData^;
2520 constructor TfdBGRA_UB4.Create;
2526 fglFormat := GL_BGRA;
2527 fglDataFormat := GL_UNSIGNED_BYTE;
2530 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2531 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2532 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2533 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2535 PWord(aData)^ := aPixel.Data.a;
2539 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2544 aPixel.Data.a := PWord(aData)^;
2548 constructor TfdAlpha_US1.Create;
2553 fglFormat := GL_ALPHA;
2554 fglDataFormat := GL_UNSIGNED_SHORT;
2557 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2558 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2559 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2560 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2562 PWord(aData)^ := LuminanceWeight(aPixel);
2566 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2568 aPixel.Data.r := PWord(aData)^;
2569 aPixel.Data.g := PWord(aData)^;
2570 aPixel.Data.b := PWord(aData)^;
2575 constructor TfdLuminance_US1.Create;
2582 fglFormat := GL_LUMINANCE;
2583 fglDataFormat := GL_UNSIGNED_SHORT;
2586 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2587 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2588 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2589 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2595 if (fRange.arr[i] > 0) then
2596 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2600 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2605 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2609 constructor TfdUniversal_US1.Create;
2615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2616 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2617 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2618 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2620 PWord(aData)^ := DepthWeight(aPixel);
2624 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2626 aPixel.Data.r := PWord(aData)^;
2627 aPixel.Data.g := PWord(aData)^;
2628 aPixel.Data.b := PWord(aData)^;
2633 constructor TfdDepth_US1.Create;
2640 fglFormat := GL_DEPTH_COMPONENT;
2641 fglDataFormat := GL_UNSIGNED_SHORT;
2644 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2645 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2646 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2647 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2649 inherited Map(aPixel, aData, aMapData);
2650 PWord(aData)^ := aPixel.Data.a;
2654 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2656 inherited Unmap(aData, aPixel, aMapData);
2657 aPixel.Data.a := PWord(aData)^;
2661 constructor TfdLuminanceAlpha_US2.Create;
2667 fglFormat := GL_LUMINANCE_ALPHA;
2668 fglDataFormat := GL_UNSIGNED_SHORT;
2671 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2672 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2673 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2674 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2676 PWord(aData)^ := aPixel.Data.r;
2678 PWord(aData)^ := aPixel.Data.g;
2680 PWord(aData)^ := aPixel.Data.b;
2684 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2686 aPixel.Data.r := PWord(aData)^;
2688 aPixel.Data.g := PWord(aData)^;
2690 aPixel.Data.b := PWord(aData)^;
2695 constructor TfdRGB_US3.Create;
2705 fglFormat := GL_RGB;
2706 fglDataFormat := GL_UNSIGNED_SHORT;
2709 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2710 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2711 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2712 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2714 PWord(aData)^ := aPixel.Data.b;
2716 PWord(aData)^ := aPixel.Data.g;
2718 PWord(aData)^ := aPixel.Data.r;
2722 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2724 aPixel.Data.b := PWord(aData)^;
2726 aPixel.Data.g := PWord(aData)^;
2728 aPixel.Data.r := PWord(aData)^;
2733 constructor TfdBGR_US3.Create;
2743 fglFormat := GL_BGR;
2744 fglDataFormat := GL_UNSIGNED_SHORT;
2747 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2748 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2749 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2750 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2752 inherited Map(aPixel, aData, aMapData);
2753 PWord(aData)^ := aPixel.Data.a;
2757 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2759 inherited Unmap(aData, aPixel, aMapData);
2760 aPixel.Data.a := PWord(aData)^;
2764 constructor TfdRGBA_US4.Create;
2770 fglFormat := GL_RGBA;
2771 fglDataFormat := GL_UNSIGNED_SHORT;
2774 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2775 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2776 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2777 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2779 inherited Map(aPixel, aData, aMapData);
2780 PWord(aData)^ := aPixel.Data.a;
2784 procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2786 inherited Unmap(aData, aPixel, aMapData);
2787 aPixel.Data.a := PWord(aData)^;
2791 constructor TfdBGRA_US4.Create;
2797 fglFormat := GL_BGRA;
2798 fglDataFormat := GL_UNSIGNED_SHORT;
2801 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2802 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2803 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2804 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2808 PCardinal(aData)^ := 0;
2810 if (fRange.arr[i] > 0) then
2811 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2815 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2820 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2824 constructor TfdUniversal_UI1.Create;
2830 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2831 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2832 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2833 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2835 PCardinal(aData)^ := DepthWeight(aPixel);
2839 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2841 aPixel.Data.r := PCardinal(aData)^;
2842 aPixel.Data.g := PCardinal(aData)^;
2843 aPixel.Data.b := PCardinal(aData)^;
2848 constructor TfdDepth_UI1.Create;
2852 fRange.r := $FFFFFFFF;
2853 fRange.g := $FFFFFFFF;
2854 fRange.b := $FFFFFFFF;
2855 fglFormat := GL_DEPTH_COMPONENT;
2856 fglDataFormat := GL_UNSIGNED_INT;
2859 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2860 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2861 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2862 constructor TfdAlpha4.Create;
2865 fFormat := tfAlpha4;
2866 fWithAlpha := tfAlpha4;
2867 fglInternalFormat := GL_ALPHA4;
2870 constructor TfdAlpha8.Create;
2873 fFormat := tfAlpha8;
2874 fWithAlpha := tfAlpha8;
2875 fglInternalFormat := GL_ALPHA8;
2878 constructor TfdAlpha12.Create;
2881 fFormat := tfAlpha12;
2882 fWithAlpha := tfAlpha12;
2883 fglInternalFormat := GL_ALPHA12;
2886 constructor TfdAlpha16.Create;
2889 fFormat := tfAlpha16;
2890 fWithAlpha := tfAlpha16;
2891 fglInternalFormat := GL_ALPHA16;
2894 constructor TfdLuminance4.Create;
2897 fFormat := tfLuminance4;
2898 fWithAlpha := tfLuminance4Alpha4;
2899 fWithoutAlpha := tfLuminance4;
2900 fglInternalFormat := GL_LUMINANCE4;
2903 constructor TfdLuminance8.Create;
2906 fFormat := tfLuminance8;
2907 fWithAlpha := tfLuminance8Alpha8;
2908 fWithoutAlpha := tfLuminance8;
2909 fglInternalFormat := GL_LUMINANCE8;
2912 constructor TfdLuminance12.Create;
2915 fFormat := tfLuminance12;
2916 fWithAlpha := tfLuminance12Alpha12;
2917 fWithoutAlpha := tfLuminance12;
2918 fglInternalFormat := GL_LUMINANCE12;
2921 constructor TfdLuminance16.Create;
2924 fFormat := tfLuminance16;
2925 fWithAlpha := tfLuminance16Alpha16;
2926 fWithoutAlpha := tfLuminance16;
2927 fglInternalFormat := GL_LUMINANCE16;
2930 constructor TfdLuminance4Alpha4.Create;
2933 fFormat := tfLuminance4Alpha4;
2934 fWithAlpha := tfLuminance4Alpha4;
2935 fWithoutAlpha := tfLuminance4;
2936 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
2939 constructor TfdLuminance6Alpha2.Create;
2942 fFormat := tfLuminance6Alpha2;
2943 fWithAlpha := tfLuminance6Alpha2;
2944 fWithoutAlpha := tfLuminance8;
2945 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
2948 constructor TfdLuminance8Alpha8.Create;
2951 fFormat := tfLuminance8Alpha8;
2952 fWithAlpha := tfLuminance8Alpha8;
2953 fWithoutAlpha := tfLuminance8;
2954 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
2957 constructor TfdLuminance12Alpha4.Create;
2960 fFormat := tfLuminance12Alpha4;
2961 fWithAlpha := tfLuminance12Alpha4;
2962 fWithoutAlpha := tfLuminance12;
2963 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
2966 constructor TfdLuminance12Alpha12.Create;
2969 fFormat := tfLuminance12Alpha12;
2970 fWithAlpha := tfLuminance12Alpha12;
2971 fWithoutAlpha := tfLuminance12;
2972 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
2975 constructor TfdLuminance16Alpha16.Create;
2978 fFormat := tfLuminance16Alpha16;
2979 fWithAlpha := tfLuminance16Alpha16;
2980 fWithoutAlpha := tfLuminance16;
2981 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
2984 constructor TfdR3G3B2.Create;
2987 fFormat := tfR3G3B2;
2988 fWithAlpha := tfRGBA2;
2989 fWithoutAlpha := tfR3G3B2;
2996 fglFormat := GL_RGB;
2997 fglInternalFormat := GL_R3_G3_B2;
2998 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3001 constructor TfdRGB4.Create;
3005 fWithAlpha := tfRGBA4;
3006 fWithoutAlpha := tfRGB4;
3007 fRGBInverted := tfBGR4;
3014 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3015 fglInternalFormat := GL_RGB4;
3016 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3019 constructor TfdR5G6B5.Create;
3022 fFormat := tfR5G6B5;
3023 fWithAlpha := tfRGBA4;
3024 fWithoutAlpha := tfR5G6B5;
3025 fRGBInverted := tfB5G6R5;
3032 fglFormat := GL_RGB;
3033 fglInternalFormat := GL_RGB565;
3034 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3037 constructor TfdRGB5.Create;
3041 fWithAlpha := tfRGB5A1;
3042 fWithoutAlpha := tfRGB5;
3043 fRGBInverted := tfBGR5;
3050 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3051 fglInternalFormat := GL_RGB5;
3052 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3055 constructor TfdRGB8.Create;
3059 fWithAlpha := tfRGBA8;
3060 fWithoutAlpha := tfRGB8;
3061 fRGBInverted := tfBGR8;
3062 fglInternalFormat := GL_RGB8;
3065 constructor TfdRGB10.Create;
3069 fWithAlpha := tfRGB10A2;
3070 fWithoutAlpha := tfRGB10;
3071 fRGBInverted := tfBGR10;
3078 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3079 fglInternalFormat := GL_RGB10;
3080 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3083 constructor TfdRGB12.Create;
3087 fWithAlpha := tfRGBA12;
3088 fWithoutAlpha := tfRGB12;
3089 fRGBInverted := tfBGR12;
3090 fglInternalFormat := GL_RGB12;
3093 constructor TfdRGB16.Create;
3097 fWithAlpha := tfRGBA16;
3098 fWithoutAlpha := tfRGB16;
3099 fRGBInverted := tfBGR16;
3100 fglInternalFormat := GL_RGB16;
3103 constructor TfdRGBA2.Create;
3107 fWithAlpha := tfRGBA2;
3108 fWithoutAlpha := tfR3G3B2;
3109 fRGBInverted := tfBGRA2;
3110 fglInternalFormat := GL_RGBA2;
3113 constructor TfdRGBA4.Create;
3117 fWithAlpha := tfRGBA4;
3118 fWithoutAlpha := tfRGB4;
3119 fRGBInverted := tfBGRA4;
3128 fglFormat := GL_RGBA;
3129 fglInternalFormat := GL_RGBA4;
3130 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3133 constructor TfdRGB5A1.Create;
3136 fFormat := tfRGB5A1;
3137 fWithAlpha := tfRGB5A1;
3138 fWithoutAlpha := tfRGB5;
3139 fRGBInverted := tfBGR5A1;
3148 fglFormat := GL_RGBA;
3149 fglInternalFormat := GL_RGB5_A1;
3150 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3153 constructor TfdRGBA8.Create;
3157 fWithAlpha := tfRGBA8;
3158 fWithoutAlpha := tfRGB8;
3159 fRGBInverted := tfBGRA8;
3160 fglInternalFormat := GL_RGBA8;
3163 constructor TfdRGB10A2.Create;
3166 fFormat := tfRGB10A2;
3167 fWithAlpha := tfRGB10A2;
3168 fWithoutAlpha := tfRGB10;
3169 fRGBInverted := tfBGR10A2;
3178 fglFormat := GL_RGBA;
3179 fglInternalFormat := GL_RGB10_A2;
3180 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3183 constructor TfdRGBA12.Create;
3186 fFormat := tfRGBA12;
3187 fWithAlpha := tfRGBA12;
3188 fWithoutAlpha := tfRGB12;
3189 fRGBInverted := tfBGRA12;
3190 fglInternalFormat := GL_RGBA12;
3193 constructor TfdRGBA16.Create;
3196 fFormat := tfRGBA16;
3197 fWithAlpha := tfRGBA16;
3198 fWithoutAlpha := tfRGB16;
3199 fRGBInverted := tfBGRA16;
3200 fglInternalFormat := GL_RGBA16;
3203 constructor TfdBGR4.Create;
3208 fWithAlpha := tfBGRA4;
3209 fWithoutAlpha := tfBGR4;
3210 fRGBInverted := tfRGB4;
3219 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3220 fglInternalFormat := GL_RGB4;
3221 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3227 constructor TfdB5G6R5.Create;
3230 fFormat := tfB5G6R5;
3231 fWithAlpha := tfBGRA4;
3232 fWithoutAlpha := tfB5G6R5;
3233 fRGBInverted := tfR5G6B5;
3240 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3241 fglInternalFormat := GL_RGB8;
3242 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3245 constructor TfdBGR5.Create;
3250 fWithAlpha := tfBGR5A1;
3251 fWithoutAlpha := tfBGR5;
3252 fRGBInverted := tfRGB5;
3261 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3262 fglInternalFormat := GL_RGB5;
3263 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3266 constructor TfdBGR8.Create;
3270 fWithAlpha := tfBGRA8;
3271 fWithoutAlpha := tfBGR8;
3272 fRGBInverted := tfRGB8;
3273 fglInternalFormat := GL_RGB8;
3276 constructor TfdBGR10.Create;
3280 fWithAlpha := tfBGR10A2;
3281 fWithoutAlpha := tfBGR10;
3282 fRGBInverted := tfRGB10;
3291 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3292 fglInternalFormat := GL_RGB10;
3293 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3296 constructor TfdBGR12.Create;
3300 fWithAlpha := tfBGRA12;
3301 fWithoutAlpha := tfBGR12;
3302 fRGBInverted := tfRGB12;
3303 fglInternalFormat := GL_RGB12;
3306 constructor TfdBGR16.Create;
3310 fWithAlpha := tfBGRA16;
3311 fWithoutAlpha := tfBGR16;
3312 fRGBInverted := tfRGB16;
3313 fglInternalFormat := GL_RGB16;
3316 constructor TfdBGRA2.Create;
3320 fWithAlpha := tfBGRA4;
3321 fWithoutAlpha := tfBGR4;
3322 fRGBInverted := tfRGBA2;
3323 fglInternalFormat := GL_RGBA2;
3326 constructor TfdBGRA4.Create;
3330 fWithAlpha := tfBGRA4;
3331 fWithoutAlpha := tfBGR4;
3332 fRGBInverted := tfRGBA4;
3341 fglFormat := GL_BGRA;
3342 fglInternalFormat := GL_RGBA4;
3343 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3346 constructor TfdBGR5A1.Create;
3349 fFormat := tfBGR5A1;
3350 fWithAlpha := tfBGR5A1;
3351 fWithoutAlpha := tfBGR5;
3352 fRGBInverted := tfRGB5A1;
3361 fglFormat := GL_BGRA;
3362 fglInternalFormat := GL_RGB5_A1;
3363 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3366 constructor TfdBGRA8.Create;
3370 fWithAlpha := tfBGRA8;
3371 fWithoutAlpha := tfBGR8;
3372 fRGBInverted := tfRGBA8;
3373 fglInternalFormat := GL_RGBA8;
3376 constructor TfdBGR10A2.Create;
3379 fFormat := tfBGR10A2;
3380 fWithAlpha := tfBGR10A2;
3381 fWithoutAlpha := tfBGR10;
3382 fRGBInverted := tfRGB10A2;
3391 fglFormat := GL_BGRA;
3392 fglInternalFormat := GL_RGB10_A2;
3393 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3396 constructor TfdBGRA12.Create;
3399 fFormat := tfBGRA12;
3400 fWithAlpha := tfBGRA12;
3401 fWithoutAlpha := tfBGR12;
3402 fRGBInverted := tfRGBA12;
3403 fglInternalFormat := GL_RGBA12;
3406 constructor TfdBGRA16.Create;
3409 fFormat := tfBGRA16;
3410 fWithAlpha := tfBGRA16;
3411 fWithoutAlpha := tfBGR16;
3412 fRGBInverted := tfRGBA16;
3413 fglInternalFormat := GL_RGBA16;
3416 constructor TfdDepth16.Create;
3419 fFormat := tfDepth16;
3420 fWithAlpha := tfEmpty;
3421 fWithoutAlpha := tfDepth16;
3422 fglInternalFormat := GL_DEPTH_COMPONENT16;
3425 constructor TfdDepth24.Create;
3428 fFormat := tfDepth24;
3429 fWithAlpha := tfEmpty;
3430 fWithoutAlpha := tfDepth24;
3431 fglInternalFormat := GL_DEPTH_COMPONENT24;
3434 constructor TfdDepth32.Create;
3437 fFormat := tfDepth32;
3438 fWithAlpha := tfEmpty;
3439 fWithoutAlpha := tfDepth32;
3440 fglInternalFormat := GL_DEPTH_COMPONENT32;
3443 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3444 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3445 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3446 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3448 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3451 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3453 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3456 constructor TfdS3tcDtx1RGBA.Create;
3459 fFormat := tfS3tcDtx1RGBA;
3460 fWithAlpha := tfS3tcDtx1RGBA;
3461 fUncompressed := tfRGB5A1;
3463 fIsCompressed := true;
3464 fglFormat := GL_COMPRESSED_RGBA;
3465 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3466 fglDataFormat := GL_UNSIGNED_BYTE;
3469 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3470 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3471 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3472 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3474 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3477 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3479 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3482 constructor TfdS3tcDtx3RGBA.Create;
3485 fFormat := tfS3tcDtx3RGBA;
3486 fWithAlpha := tfS3tcDtx3RGBA;
3487 fUncompressed := tfRGBA8;
3489 fIsCompressed := true;
3490 fglFormat := GL_COMPRESSED_RGBA;
3491 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3492 fglDataFormat := GL_UNSIGNED_BYTE;
3495 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3496 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3497 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3498 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3500 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3503 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3505 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3508 constructor TfdS3tcDtx5RGBA.Create;
3511 fFormat := tfS3tcDtx3RGBA;
3512 fWithAlpha := tfS3tcDtx3RGBA;
3513 fUncompressed := tfRGBA8;
3515 fIsCompressed := true;
3516 fglFormat := GL_COMPRESSED_RGBA;
3517 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3518 fglDataFormat := GL_UNSIGNED_BYTE;
3521 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3522 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3523 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3524 class procedure TFormatDescriptor.Init;
3526 if not Assigned(FormatDescriptorCS) then
3527 FormatDescriptorCS := TCriticalSection.Create;
3530 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3531 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3533 FormatDescriptorCS.Enter;
3535 result := FormatDescriptors[aFormat];
3536 if not Assigned(result) then begin
3537 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3538 FormatDescriptors[aFormat] := result;
3541 FormatDescriptorCS.Leave;
3545 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3546 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3548 result := Get(Get(aFormat).WithAlpha);
3551 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3552 class procedure TFormatDescriptor.Clear;
3556 FormatDescriptorCS.Enter;
3558 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3559 FreeAndNil(FormatDescriptors[f]);
3561 FormatDescriptorCS.Leave;
3565 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3566 class procedure TFormatDescriptor.Finalize;
3569 FreeAndNil(FormatDescriptorCS);
3572 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3573 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3574 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3575 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3577 Update(aValue, fRange.r, fShift.r);
3580 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3581 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3583 Update(aValue, fRange.g, fShift.g);
3586 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3587 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3589 Update(aValue, fRange.b, fShift.b);
3592 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3593 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3595 Update(aValue, fRange.a, fShift.a);
3598 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3599 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3606 while (aMask > 0) and ((aMask and 1) = 0) do begin
3608 aMask := aMask shr 1;
3611 while (aMask > 0) do begin
3612 aRange := aRange shl 1;
3613 aMask := aMask shr 1;
3617 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3620 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3621 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3627 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3628 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3629 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3630 ((aPixel.Data.a and fRange.a) shl fShift.a);
3631 s := Round(fPixelSize);
3634 2: PWord(aData)^ := data;
3635 4: PCardinal(aData)^ := data;
3636 8: PQWord(aData)^ := data;
3638 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3643 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3644 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3649 s := Round(fPixelSize);
3652 2: data := PWord(aData)^;
3653 4: data := PCardinal(aData)^;
3654 8: data := PQWord(aData)^;
3656 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3659 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3663 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3664 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3665 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3666 procedure TbmpColorTableFormat.CreateColorTable;
3670 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3671 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3673 if (Format = tfLuminance4) then
3674 SetLength(fColorTable, 16)
3676 SetLength(fColorTable, 256);
3680 for i := 0 to High(fColorTable) do begin
3681 fColorTable[i].r := 16 * i;
3682 fColorTable[i].g := 16 * i;
3683 fColorTable[i].b := 16 * i;
3684 fColorTable[i].a := 0;
3689 for i := 0 to High(fColorTable) do begin
3690 fColorTable[i].r := i;
3691 fColorTable[i].g := i;
3692 fColorTable[i].b := i;
3693 fColorTable[i].a := 0;
3698 for i := 0 to High(fColorTable) do begin
3699 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3700 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3701 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3702 fColorTable[i].a := 0;
3708 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3709 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3713 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3714 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3718 if (aMapData = nil) then
3720 d := LuminanceWeight(aPixel) and Range.r;
3721 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3722 inc(PByte(aMapData), 4);
3723 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3730 aData^ := LuminanceWeight(aPixel) and Range.r;
3736 ((aPixel.Data.r and Range.r) shl Shift.r) or
3737 ((aPixel.Data.g and Range.g) shl Shift.g) or
3738 ((aPixel.Data.b and Range.b) shl Shift.b));
3744 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3745 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3752 s := Trunc(fPixelSize);
3753 f := fPixelSize - s;
3754 bits := Round(8 * f);
3756 0: idx := (aData^ shr (8 - bits - {%H-}PtrInt(aMapData))) and ((1 shl bits) - 1);
3758 2: idx := PWord(aData)^;
3759 4: idx := PCardinal(aData)^;
3760 8: idx := PQWord(aData)^;
3762 raise EglBitmapException.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3764 if (idx >= Length(fColorTable)) then
3765 raise EglBitmapException.CreateFmt('invalid color index: %d', [idx]);
3766 with fColorTable[idx] do begin
3772 inc(PByte(aMapData), bits);
3773 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3775 dec(PByte(aMapData), 8);
3780 destructor TbmpColorTableFormat.Destroy;
3782 SetLength(fColorTable, 0);
3786 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3787 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3788 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3789 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
3793 for i := 0 to 3 do begin
3794 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
3795 if (aSourceFD.Range.arr[i] > 0) then
3796 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
3798 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
3803 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3804 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
3806 with aFuncRec do begin
3807 if (Source.Range.r > 0) then
3808 Dest.Data.r := Source.Data.r;
3809 if (Source.Range.g > 0) then
3810 Dest.Data.g := Source.Data.g;
3811 if (Source.Range.b > 0) then
3812 Dest.Data.b := Source.Data.b;
3813 if (Source.Range.a > 0) then
3814 Dest.Data.a := Source.Data.a;
3818 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3819 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3823 with aFuncRec do begin
3825 if (Source.Range.arr[i] > 0) then
3826 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
3831 TShiftData = packed record
3833 0: (r, g, b, a: SmallInt);
3834 1: (arr: array[0..3] of SmallInt);
3836 PShiftData = ^TShiftData;
3838 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3839 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3845 if (Source.Range.arr[i] > 0) then
3846 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
3849 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3850 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
3852 with aFuncRec do begin
3853 Dest.Data := Source.Data;
3854 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
3855 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
3856 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
3857 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
3859 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
3860 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
3865 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3866 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
3870 with aFuncRec do begin
3872 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
3876 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3877 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3881 with FuncRec do begin
3882 if (FuncRec.Args = nil) then begin //source has no alpha
3884 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
3885 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
3886 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
3887 Dest.Data.a := Round(Dest.Range.a * Temp);
3889 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
3893 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3894 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3896 PglBitmapPixelData = ^TglBitmapPixelData;
3898 with FuncRec do begin
3899 Dest.Data.r := Source.Data.r;
3900 Dest.Data.g := Source.Data.g;
3901 Dest.Data.b := Source.Data.b;
3903 with PglBitmapPixelData(Args)^ do
3904 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
3905 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
3906 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
3909 Dest.Data.a := Dest.Range.a;
3913 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3914 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3916 with FuncRec do begin
3917 Dest.Data.r := Source.Data.r;
3918 Dest.Data.g := Source.Data.g;
3919 Dest.Data.b := Source.Data.b;
3920 Dest.Data.a := PCardinal(Args)^;
3924 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3925 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
3928 TRGBPix = array [0..2] of byte;
3932 while aWidth > 0 do begin
3933 Temp := PRGBPix(aData)^[0];
3934 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
3935 PRGBPix(aData)^[2] := Temp;
3945 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3946 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3947 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3948 function TglBitmap.GetWidth: Integer;
3950 if (ffX in fDimension.Fields) then
3951 result := fDimension.X
3956 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3957 function TglBitmap.GetHeight: Integer;
3959 if (ffY in fDimension.Fields) then
3960 result := fDimension.Y
3965 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3966 function TglBitmap.GetFileWidth: Integer;
3968 result := Max(1, Width);
3971 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3972 function TglBitmap.GetFileHeight: Integer;
3974 result := Max(1, Height);
3977 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3978 procedure TglBitmap.SetCustomData(const aValue: Pointer);
3980 if fCustomData = aValue then
3982 fCustomData := aValue;
3985 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3986 procedure TglBitmap.SetCustomName(const aValue: String);
3988 if fCustomName = aValue then
3990 fCustomName := aValue;
3993 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3994 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
3996 if fCustomNameW = aValue then
3998 fCustomNameW := aValue;
4001 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4002 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4004 if fDeleteTextureOnFree = aValue then
4006 fDeleteTextureOnFree := aValue;
4009 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4010 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4012 if fFormat = aValue then
4014 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4015 raise EglBitmapUnsupportedFormat.Create(Format);
4016 SetDataPointer(fData, aValue, Width, Height); //be careful, Data could be freed by this method
4019 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4020 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4022 if fFreeDataAfterGenTexture = aValue then
4024 fFreeDataAfterGenTexture := aValue;
4027 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4028 procedure TglBitmap.SetID(const aValue: Cardinal);
4030 if fID = aValue then
4035 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4036 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4038 if fMipMap = aValue then
4043 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4044 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4046 if fTarget = aValue then
4051 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4052 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4054 MaxAnisotropic: Integer;
4056 fAnisotropic := aValue;
4057 if (ID > 0) then begin
4058 if GL_EXT_texture_filter_anisotropic then begin
4059 if fAnisotropic > 0 then begin
4061 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4062 if aValue > MaxAnisotropic then
4063 fAnisotropic := MaxAnisotropic;
4064 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4072 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4073 procedure TglBitmap.CreateID;
4076 glDeleteTextures(1, @fID);
4077 glGenTextures(1, @fID);
4081 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4082 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4084 // Set Up Parameters
4085 SetWrap(fWrapS, fWrapT, fWrapR);
4086 SetFilter(fFilterMin, fFilterMag);
4087 SetAnisotropic(fAnisotropic);
4088 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4090 // Mip Maps Generation Mode
4091 aBuildWithGlu := false;
4092 if (MipMap = mmMipmap) then begin
4093 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4094 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4096 aBuildWithGlu := true;
4097 end else if (MipMap = mmMipmapGlu) then
4098 aBuildWithGlu := true;
4101 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4102 procedure TglBitmap.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
4103 const aWidth: Integer; const aHeight: Integer);
4107 if (Data <> aData) then begin
4108 if (Assigned(Data)) then
4113 FillChar(fDimension, SizeOf(fDimension), 0);
4114 if not Assigned(fData) then begin
4119 if aWidth <> -1 then begin
4120 fDimension.Fields := fDimension.Fields + [ffX];
4121 fDimension.X := aWidth;
4124 if aHeight <> -1 then begin
4125 fDimension.Fields := fDimension.Fields + [ffY];
4126 fDimension.Y := aHeight;
4129 s := TFormatDescriptor.Get(aFormat).PixelSize;
4131 fPixelSize := Ceil(s);
4132 fRowSize := Ceil(s * aWidth);
4136 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4137 function TglBitmap.FlipHorz: Boolean;
4142 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4143 function TglBitmap.FlipVert: Boolean;
4148 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4149 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4150 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4151 procedure TglBitmap.AfterConstruction;
4153 inherited AfterConstruction;
4157 fIsResident := false;
4159 fFormat := glBitmapGetDefaultFormat;
4160 fMipMap := glBitmapDefaultMipmap;
4161 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4162 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4164 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4165 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4168 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4169 procedure TglBitmap.BeforeDestruction;
4174 SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
4175 if (fID > 0) and fDeleteTextureOnFree then
4176 glDeleteTextures(1, @fID);
4177 inherited BeforeDestruction;
4180 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4181 procedure TglBitmap.PrepareResType(var aResource: String; var aResType: PChar);
4185 if not Assigned(aResType) then begin
4186 TempPos := Pos('.', aResource);
4187 aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos)));
4188 aResource := UpperCase(Copy(aResource, 0, TempPos -1));
4192 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4193 procedure TglBitmap.LoadFromFile(const aFilename: String);
4197 if not FileExists(aFilename) then
4198 raise EglBitmapException.Create('file does not exist: ' + aFilename);
4199 fFilename := aFilename;
4200 fs := TFileStream.Create(fFilename, fmOpenRead);
4209 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4210 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4212 {$IFDEF GLB_SUPPORT_PNG_READ}
4213 if not LoadPNG(aStream) then
4215 {$IFDEF GLB_SUPPORT_JPEG_READ}
4216 if not LoadJPEG(aStream) then
4218 if not LoadDDS(aStream) then
4219 if not LoadTGA(aStream) then
4220 if not LoadBMP(aStream) then
4221 raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4225 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4226 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4231 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4232 GetMem(tmpData, size);
4234 FillChar(tmpData^, size, #$FF);
4235 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
4237 if Assigned(tmpData) then
4241 AddFunc(Self, aFunc, false, Format, aArgs);
4244 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4245 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar);
4247 rs: TResourceStream;
4249 PrepareResType(aResource, aResType);
4250 rs := TResourceStream.Create(aInstance, aResource, aResType);
4258 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4259 procedure TglBitmap.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4261 rs: TResourceStream;
4263 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
4271 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4272 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4276 fs := TFileStream.Create(aFileName, fmCreate);
4279 SaveToStream(fs, aFileType);
4285 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4286 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4289 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4290 ftPNG: SavePNG(aStream);
4292 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4293 ftJPEG: SaveJPEG(aStream);
4295 ftDDS: SaveDDS(aStream);
4296 ftTGA: SaveTGA(aStream);
4297 ftBMP: SaveBMP(aStream);
4301 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4302 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4304 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4307 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4308 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4309 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4311 DestData, TmpData, SourceData: pByte;
4312 TempHeight, TempWidth: Integer;
4313 SourceFD, DestFD: TFormatDescriptor;
4314 SourceMD, DestMD: Pointer;
4316 FuncRec: TglBitmapFunctionRec;
4318 Assert(Assigned(Data));
4319 Assert(Assigned(aSource));
4320 Assert(Assigned(aSource.Data));
4323 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4324 SourceFD := TFormatDescriptor.Get(aSource.Format);
4325 DestFD := TFormatDescriptor.Get(aFormat);
4327 if (SourceFD.IsCompressed) then
4328 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format);
4329 if (DestFD.IsCompressed) then
4330 raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format);
4332 // inkompatible Formats so CreateTemp
4333 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4334 aCreateTemp := true;
4337 TempHeight := Max(1, aSource.Height);
4338 TempWidth := Max(1, aSource.Width);
4340 FuncRec.Sender := Self;
4341 FuncRec.Args := aArgs;
4344 if aCreateTemp then begin
4345 GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight));
4346 DestData := TmpData;
4351 SourceFD.PreparePixel(FuncRec.Source);
4352 DestFD.PreparePixel (FuncRec.Dest);
4354 SourceMD := SourceFD.CreateMappingData;
4355 DestMD := DestFD.CreateMappingData;
4357 FuncRec.Size := aSource.Dimension;
4358 FuncRec.Position.Fields := FuncRec.Size.Fields;
4361 SourceData := aSource.Data;
4362 FuncRec.Position.Y := 0;
4363 while FuncRec.Position.Y < TempHeight do begin
4364 FuncRec.Position.X := 0;
4365 while FuncRec.Position.X < TempWidth do begin
4366 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4368 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4369 inc(FuncRec.Position.X);
4371 inc(FuncRec.Position.Y);
4374 // Updating Image or InternalFormat
4376 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) //be careful, Data could be freed by this method
4377 else if (aFormat <> fFormat) then
4382 SourceFD.FreeMappingData(SourceMD);
4383 DestFD.FreeMappingData(DestMD);
4386 if aCreateTemp and Assigned(TmpData) then
4394 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4395 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4397 Row, RowSize: Integer;
4398 SourceData, TmpData: PByte;
4400 FormatDesc: TFormatDescriptor;
4402 function GetRowPointer(Row: Integer): pByte;
4404 result := aSurface.pixels;
4405 Inc(result, Row * RowSize);
4411 FormatDesc := TFormatDescriptor.Get(Format);
4412 if FormatDesc.IsCompressed then
4413 raise EglBitmapUnsupportedFormat.Create(Format);
4415 if Assigned(Data) then begin
4416 case Trunc(FormatDesc.PixelSize) of
4422 raise EglBitmapUnsupportedFormat.Create(Format);
4425 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4426 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4428 RowSize := FormatDesc.GetSize(FileWidth, 1);
4430 for Row := 0 to FileHeight-1 do begin
4431 TmpData := GetRowPointer(Row);
4432 if Assigned(TmpData) then begin
4433 Move(SourceData^, TmpData^, RowSize);
4434 inc(SourceData, RowSize);
4441 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4442 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4444 pSource, pData, pTempData: PByte;
4445 Row, RowSize, TempWidth, TempHeight: Integer;
4446 IntFormat: TglBitmapFormat;
4447 FormatDesc: TFormatDescriptor;
4449 function GetRowPointer(Row: Integer): pByte;
4451 result := aSurface^.pixels;
4452 Inc(result, Row * RowSize);
4457 if (Assigned(aSurface)) then begin
4458 with aSurface^.format^ do begin
4459 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4460 FormatDesc := TFormatDescriptor.Get(IntFormat);
4461 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4464 if (IntFormat = tfEmpty) then
4465 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4468 TempWidth := aSurface^.w;
4469 TempHeight := aSurface^.h;
4470 RowSize := FormatDesc.GetSize(TempWidth, 1);
4471 GetMem(pData, TempHeight * RowSize);
4474 for Row := 0 to TempHeight -1 do begin
4475 pSource := GetRowPointer(Row);
4476 if (Assigned(pSource)) then begin
4477 Move(pSource^, pTempData^, RowSize);
4478 Inc(pTempData, RowSize);
4481 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4484 if Assigned(pData) then
4491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4492 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4494 Row, Col, AlphaInterleave: Integer;
4495 pSource, pDest: PByte;
4497 function GetRowPointer(Row: Integer): pByte;
4499 result := aSurface.pixels;
4500 Inc(result, Row * Width);
4505 if Assigned(Data) then begin
4506 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4507 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4509 AlphaInterleave := 0;
4512 AlphaInterleave := 1;
4514 AlphaInterleave := 3;
4518 for Row := 0 to Height -1 do begin
4519 pDest := GetRowPointer(Row);
4520 if Assigned(pDest) then begin
4521 for Col := 0 to Width -1 do begin
4522 Inc(pSource, AlphaInterleave);
4534 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4535 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4539 bmp := TglBitmap2D.Create;
4541 bmp.AssignFromSurface(aSurface);
4542 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4550 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4551 function CreateGrayPalette: HPALETTE;
4556 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
4558 Pal.palVersion := $300;
4559 Pal.palNumEntries := 256;
4561 for Idx := 0 to Pal.palNumEntries - 1 do begin
4562 Pal.palPalEntry[Idx].peRed := Idx;
4563 Pal.palPalEntry[Idx].peGreen := Idx;
4564 Pal.palPalEntry[Idx].peBlue := Idx;
4565 Pal.palPalEntry[Idx].peFlags := 0;
4567 Result := CreatePalette(Pal^);
4571 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4572 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4575 pSource, pData: PByte;
4578 if Assigned(Data) then begin
4579 if Assigned(aBitmap) then begin
4580 aBitmap.Width := Width;
4581 aBitmap.Height := Height;
4584 tfAlpha8, tfLuminance8: begin
4585 aBitmap.PixelFormat := pf8bit;
4586 aBitmap.Palette := CreateGrayPalette;
4589 aBitmap.PixelFormat := pf15bit;
4591 aBitmap.PixelFormat := pf16bit;
4593 aBitmap.PixelFormat := pf24bit;
4595 aBitmap.PixelFormat := pf32bit;
4597 raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
4601 for Row := 0 to FileHeight -1 do begin
4602 pData := aBitmap.Scanline[Row];
4603 Move(pSource^, pData^, fRowSize);
4604 Inc(pSource, fRowSize);
4605 if (Format in [tfRGB8, tfRGBA8]) then // swap RGB(A) to BGR(A)
4606 SwapRGB(pData, FileWidth, Format = tfRGBA8);
4613 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4614 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4616 pSource, pData, pTempData: PByte;
4617 Row, RowSize, TempWidth, TempHeight: Integer;
4618 IntFormat: TglBitmapFormat;
4622 if (Assigned(aBitmap)) then begin
4623 case aBitmap.PixelFormat of
4625 IntFormat := tfLuminance8;
4627 IntFormat := tfRGB5A1;
4629 IntFormat := tfR5G6B5;
4631 IntFormat := tfBGR8;
4633 IntFormat := tfBGRA8;
4635 raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
4638 TempWidth := aBitmap.Width;
4639 TempHeight := aBitmap.Height;
4640 RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1);
4641 GetMem(pData, TempHeight * RowSize);
4644 for Row := 0 to TempHeight -1 do begin
4645 pSource := aBitmap.Scanline[Row];
4646 if (Assigned(pSource)) then begin
4647 Move(pSource^, pTempData^, RowSize);
4648 Inc(pTempData, RowSize);
4651 SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
4654 if Assigned(pData) then
4661 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4662 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4664 Row, Col, AlphaInterleave: Integer;
4665 pSource, pDest: PByte;
4669 if Assigned(Data) then begin
4670 if (Format in [tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8]) then begin
4671 if Assigned(aBitmap) then begin
4672 aBitmap.PixelFormat := pf8bit;
4673 aBitmap.Palette := CreateGrayPalette;
4674 aBitmap.Width := Width;
4675 aBitmap.Height := Height;
4679 AlphaInterleave := 1;
4681 AlphaInterleave := 3;
4683 AlphaInterleave := 0;
4689 for Row := 0 to Height -1 do begin
4690 pDest := aBitmap.Scanline[Row];
4691 if Assigned(pDest) then begin
4692 for Col := 0 to Width -1 do begin
4693 Inc(pSource, AlphaInterleave);
4706 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4707 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4711 tex := TglBitmap2D.Create;
4713 tex.AssignFromBitmap(ABitmap);
4714 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4721 {$IFDEF GLB_LAZARUS}
4722 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4723 function TglBitmap.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4725 rid: TRawImageDescription;
4726 FormatDesc: TFormatDescriptor;
4729 if not Assigned(aImage) or (Format = tfEmpty) then
4731 FormatDesc := TFormatDescriptor.Get(Format);
4732 if FormatDesc.IsCompressed then
4735 FillChar(rid{%H-}, SizeOf(rid), 0);
4737 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
4738 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
4739 tfLuminance4Alpha4, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16]) then
4740 rid.Format := ricfGray
4742 rid.Format := ricfRGBA;
4745 rid.Height := Height;
4746 rid.Depth := CountSetBits(FormatDesc.Range.r or FormatDesc.Range.g or FormatDesc.Range.b or FormatDesc.Range.a);
4747 rid.BitOrder := riboBitsInOrder;
4748 rid.ByteOrder := riboLSBFirst;
4749 rid.LineOrder := riloTopToBottom;
4750 rid.LineEnd := rileTight;
4751 rid.BitsPerPixel := Round(8 * FormatDesc.PixelSize);
4752 rid.RedPrec := CountSetBits(FormatDesc.Range.r);
4753 rid.GreenPrec := CountSetBits(FormatDesc.Range.g);
4754 rid.BluePrec := CountSetBits(FormatDesc.Range.b);
4755 rid.AlphaPrec := CountSetBits(FormatDesc.Range.a);
4756 rid.RedShift := FormatDesc.Shift.r;
4757 rid.GreenShift := FormatDesc.Shift.g;
4758 rid.BlueShift := FormatDesc.Shift.b;
4759 rid.AlphaShift := FormatDesc.Shift.a;
4761 rid.MaskBitsPerPixel := 0;
4762 rid.PaletteColorCount := 0;
4764 aImage.DataDescription := rid;
4767 Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension));
4772 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4773 function TglBitmap.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean;
4776 FormatDesc: TFormatDescriptor;
4781 if not Assigned(aImage) then
4783 for f := High(f) downto Low(f) do begin
4784 FormatDesc := TFormatDescriptor.Get(f);
4785 with aImage.DataDescription do
4786 if FormatDesc.MaskMatch(
4787 (QWord(1 shl RedPrec )-1) shl RedShift,
4788 (QWord(1 shl GreenPrec)-1) shl GreenShift,
4789 (QWord(1 shl BluePrec )-1) shl BlueShift,
4790 (QWord(1 shl AlphaPrec)-1) shl AlphaShift) then
4794 if (f = tfEmpty) then
4797 ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
4798 ImageData := GetMem(ImageSize);
4800 Move(aImage.PixelData^, ImageData^, (aImage.Width * aImage.Height * aImage.DataDescription.BitsPerPixel) shr 3);
4801 SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method
4803 if Assigned(ImageData) then
4811 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4812 function TglBitmap.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean;
4814 rid: TRawImageDescription;
4815 FormatDesc: TFormatDescriptor;
4816 Pixel: TglBitmapPixelData;
4822 if not Assigned(aImage) or (Format = tfEmpty) then
4824 FormatDesc := TFormatDescriptor.Get(Format);
4825 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
4828 FillChar(rid{%H-}, SizeOf(rid), 0);
4829 rid.Format := ricfGray;
4831 rid.Height := Height;
4832 rid.Depth := CountSetBits(FormatDesc.Range.a);
4833 rid.BitOrder := riboBitsInOrder;
4834 rid.ByteOrder := riboLSBFirst;
4835 rid.LineOrder := riloTopToBottom;
4836 rid.LineEnd := rileTight;
4837 rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8);
4838 rid.RedPrec := CountSetBits(FormatDesc.Range.a);
4843 rid.GreenShift := 0;
4845 rid.AlphaShift := 0;
4847 rid.MaskBitsPerPixel := 0;
4848 rid.PaletteColorCount := 0;
4850 aImage.DataDescription := rid;
4853 srcMD := FormatDesc.CreateMappingData;
4855 FormatDesc.PreparePixel(Pixel);
4857 dst := aImage.PixelData;
4858 for y := 0 to Height-1 do
4859 for x := 0 to Width-1 do begin
4860 FormatDesc.Unmap(src, Pixel, srcMD);
4861 case rid.BitsPerPixel of
4863 dst^ := Pixel.Data.a;
4867 PWord(dst)^ := Pixel.Data.a;
4871 PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0];
4872 PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1];
4873 PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2];
4877 PCardinal(dst)^ := Pixel.Data.a;
4881 raise EglBitmapUnsupportedFormat.Create(Format);
4885 FormatDesc.FreeMappingData(srcMD);
4890 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4891 function TglBitmap.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4895 tex := TglBitmap2D.Create;
4897 tex.AssignFromLazIntfImage(aImage);
4898 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4905 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4906 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar;
4907 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4909 rs: TResourceStream;
4911 PrepareResType(aResource, aResType);
4912 rs := TResourceStream.Create(aInstance, aResource, aResType);
4914 result := AddAlphaFromStream(rs, aFunc, aArgs);
4920 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4921 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
4922 const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4924 rs: TResourceStream;
4926 rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType);
4928 result := AddAlphaFromStream(rs, aFunc, aArgs);
4934 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4935 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4937 if TFormatDescriptor.Get(Format).IsCompressed then
4938 raise EglBitmapUnsupportedFormat.Create(Format);
4939 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
4942 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4943 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4947 FS := TFileStream.Create(FileName, fmOpenRead);
4949 result := AddAlphaFromStream(FS, aFunc, aArgs);
4955 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4956 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4960 tex := TglBitmap2D.Create(aStream);
4962 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4968 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4969 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4971 DestData, DestData2, SourceData: pByte;
4972 TempHeight, TempWidth: Integer;
4973 SourceFD, DestFD: TFormatDescriptor;
4974 SourceMD, DestMD, DestMD2: Pointer;
4976 FuncRec: TglBitmapFunctionRec;
4980 Assert(Assigned(Data));
4981 Assert(Assigned(aBitmap));
4982 Assert(Assigned(aBitmap.Data));
4984 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
4985 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
4987 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
4988 DestFD := TFormatDescriptor.Get(Format);
4990 if not Assigned(aFunc) then begin
4991 aFunc := glBitmapAlphaFunc;
4992 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
4994 FuncRec.Args := aArgs;
4997 TempHeight := aBitmap.FileHeight;
4998 TempWidth := aBitmap.FileWidth;
5000 FuncRec.Sender := Self;
5001 FuncRec.Size := Dimension;
5002 FuncRec.Position.Fields := FuncRec.Size.Fields;
5006 SourceData := aBitmap.Data;
5009 SourceFD.PreparePixel(FuncRec.Source);
5010 DestFD.PreparePixel (FuncRec.Dest);
5012 SourceMD := SourceFD.CreateMappingData;
5013 DestMD := DestFD.CreateMappingData;
5014 DestMD2 := DestFD.CreateMappingData;
5016 FuncRec.Position.Y := 0;
5017 while FuncRec.Position.Y < TempHeight do begin
5018 FuncRec.Position.X := 0;
5019 while FuncRec.Position.X < TempWidth do begin
5020 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5021 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5023 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5024 inc(FuncRec.Position.X);
5026 inc(FuncRec.Position.Y);
5029 SourceFD.FreeMappingData(SourceMD);
5030 DestFD.FreeMappingData(DestMD);
5031 DestFD.FreeMappingData(DestMD2);
5036 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5037 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5039 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5042 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5043 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5045 PixelData: TglBitmapPixelData;
5047 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5048 result := AddAlphaFromColorKeyFloat(
5049 aRed / PixelData.Range.r,
5050 aGreen / PixelData.Range.g,
5051 aBlue / PixelData.Range.b,
5052 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5055 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5056 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5058 values: array[0..2] of Single;
5061 PixelData: TglBitmapPixelData;
5063 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5064 with PixelData do begin
5066 values[1] := aGreen;
5069 for i := 0 to 2 do begin
5070 tmp := Trunc(Range.arr[i] * aDeviation);
5071 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5072 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5077 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5080 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5081 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5083 result := AddAlphaFromValueFloat(aAlpha / $FF);
5086 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5087 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5089 PixelData: TglBitmapPixelData;
5091 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5092 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5095 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5096 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5098 PixelData: TglBitmapPixelData;
5100 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5102 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5103 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5106 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5107 function TglBitmap.RemoveAlpha: Boolean;
5109 FormatDesc: TFormatDescriptor;
5112 FormatDesc := TFormatDescriptor.Get(Format);
5113 if Assigned(Data) then begin
5114 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5115 raise EglBitmapUnsupportedFormat.Create(Format);
5116 result := ConvertTo(FormatDesc.WithoutAlpha);
5120 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5121 function TglBitmap.Clone: TglBitmap;
5128 Temp := (ClassType.Create as TglBitmap);
5130 // copy texture data if assigned
5131 if Assigned(Data) then begin
5132 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5133 GetMem(TempPtr, Size);
5135 Move(Data^, TempPtr^, Size);
5136 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5138 if Assigned(TempPtr) then
5144 Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method
5149 Temp.fTarget := Target;
5150 Temp.fFormat := Format;
5151 Temp.fMipMap := MipMap;
5152 Temp.fAnisotropic := Anisotropic;
5153 Temp.fBorderColor := fBorderColor;
5154 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5155 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5156 Temp.fFilterMin := fFilterMin;
5157 Temp.fFilterMag := fFilterMag;
5158 Temp.fWrapS := fWrapS;
5159 Temp.fWrapT := fWrapT;
5160 Temp.fWrapR := fWrapR;
5161 Temp.fFilename := fFilename;
5162 Temp.fCustomName := fCustomName;
5163 Temp.fCustomNameW := fCustomNameW;
5164 Temp.fCustomData := fCustomData;
5173 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5174 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5176 SourceFD, DestFD: TFormatDescriptor;
5177 SourcePD, DestPD: TglBitmapPixelData;
5178 ShiftData: TShiftData;
5180 function CanCopyDirect: Boolean;
5183 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5184 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5185 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5186 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5189 function CanShift: Boolean;
5192 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5193 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5194 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5195 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5198 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5201 while (aSource > aDest) and (aSource > 0) do begin
5203 aSource := aSource shr 1;
5208 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5209 SourceFD := TFormatDescriptor.Get(Format);
5210 DestFD := TFormatDescriptor.Get(aFormat);
5212 SourceFD.PreparePixel(SourcePD);
5213 DestFD.PreparePixel (DestPD);
5215 if CanCopyDirect then
5216 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5217 else if CanShift then begin
5218 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5219 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5220 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5221 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5222 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5224 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5229 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5230 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5232 if aUseRGB or aUseAlpha then
5233 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5234 ((PtrInt(aUseAlpha) and 1) shl 1) or
5235 (PtrInt(aUseRGB) and 1) ));
5238 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5239 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5241 fBorderColor[0] := aRed;
5242 fBorderColor[1] := aGreen;
5243 fBorderColor[2] := aBlue;
5244 fBorderColor[3] := aAlpha;
5245 if (ID > 0) then begin
5247 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5251 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5252 procedure TglBitmap.FreeData;
5257 SetDataPointer(TempPtr, tfEmpty); //be careful, Data could be freed by this method
5260 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5261 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5262 const aAlpha: Byte);
5264 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5267 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5268 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5270 PixelData: TglBitmapPixelData;
5272 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5274 aRed / PixelData.Range.r,
5275 aGreen / PixelData.Range.g,
5276 aBlue / PixelData.Range.b,
5277 aAlpha / PixelData.Range.a);
5280 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5281 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5283 PixelData: TglBitmapPixelData;
5285 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5286 with PixelData do begin
5287 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5288 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5289 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5290 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5292 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5295 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5296 procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal);
5301 fFilterMin := GL_NEAREST;
5303 fFilterMin := GL_LINEAR;
5304 GL_NEAREST_MIPMAP_NEAREST:
5305 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5306 GL_LINEAR_MIPMAP_NEAREST:
5307 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5308 GL_NEAREST_MIPMAP_LINEAR:
5309 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5310 GL_LINEAR_MIPMAP_LINEAR:
5311 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5313 raise EglBitmapException.Create('SetFilter - Unknow MIN filter.');
5319 fFilterMag := GL_NEAREST;
5321 fFilterMag := GL_LINEAR;
5323 raise EglBitmapException.Create('SetFilter - Unknow MAG filter.');
5327 if (ID > 0) then begin
5329 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5331 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5333 GL_NEAREST, GL_LINEAR:
5334 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5335 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5336 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5337 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5338 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5341 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5345 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5346 procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; const R: Cardinal);
5348 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5352 aTarget := GL_CLAMP;
5355 aTarget := GL_REPEAT;
5357 GL_CLAMP_TO_EDGE: begin
5358 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5359 aTarget := GL_CLAMP_TO_EDGE
5361 aTarget := GL_CLAMP;
5364 GL_CLAMP_TO_BORDER: begin
5365 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5366 aTarget := GL_CLAMP_TO_BORDER
5368 aTarget := GL_CLAMP;
5371 GL_MIRRORED_REPEAT: begin
5372 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5373 aTarget := GL_MIRRORED_REPEAT
5375 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5378 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).');
5383 CheckAndSetWrap(S, fWrapS);
5384 CheckAndSetWrap(T, fWrapT);
5385 CheckAndSetWrap(R, fWrapR);
5387 if (ID > 0) then begin
5389 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5390 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5391 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5395 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5396 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5398 if aEnableTextureUnit then
5401 glBindTexture(Target, ID);
5404 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5405 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5407 if aDisableTextureUnit then
5409 glBindTexture(Target, 0);
5412 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5413 constructor TglBitmap.Create;
5415 if (ClassType = TglBitmap) then
5416 raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5417 {$IFDEF GLB_NATIVE_OGL}
5418 glbReadOpenGLExtensions;
5423 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5424 constructor TglBitmap.Create(const aFileName: String);
5427 LoadFromFile(FileName);
5430 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5431 constructor TglBitmap.Create(const aStream: TStream);
5434 LoadFromStream(aStream);
5437 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5438 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
5444 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5445 GetMem(Image, ImageSize);
5447 FillChar(Image^, ImageSize, #$FF);
5448 SetDataPointer(Image, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
5450 if Assigned(Image) then
5456 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5457 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
5458 const aFunc: TglBitmapFunction; const aArgs: Pointer);
5461 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5464 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5465 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5468 LoadFromResource(aInstance, aResource, aResType);
5471 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5472 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5475 LoadFromResourceID(aInstance, aResourceID, aResType);
5478 {$IFDEF GLB_SUPPORT_PNG_READ}
5479 {$IF DEFINED(GLB_SDL_IMAGE)}
5480 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5481 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5482 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5483 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5485 Surface: PSDL_Surface;
5489 RWops := glBitmapCreateRWops(aStream);
5491 if IMG_isPNG(RWops) > 0 then begin
5492 Surface := IMG_LoadPNG_RW(RWops);
5494 AssignFromSurface(Surface);
5497 SDL_FreeSurface(Surface);
5505 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5506 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5507 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5509 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5512 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5513 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5516 signature: array [0..7] of byte;
5518 png_info: png_infop;
5520 TempHeight, TempWidth: Integer;
5521 Format: TglBitmapFormat;
5524 png_rows: array of pByte;
5525 Row, LineSize: Integer;
5529 if not init_libPNG then
5530 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5534 StreamPos := aStream.Position;
5535 aStream.Read(signature{%H-}, 8);
5536 aStream.Position := StreamPos;
5538 if png_check_sig(@signature, 8) <> 0 then begin
5540 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5542 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5545 png_info := png_create_info_struct(png);
5546 if png_info = nil then begin
5547 png_destroy_read_struct(@png, nil, nil);
5548 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5551 // set read callback
5552 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5554 // read informations
5555 png_read_info(png, png_info);
5558 TempHeight := png_get_image_height(png, png_info);
5559 TempWidth := png_get_image_width(png, png_info);
5562 case png_get_color_type(png, png_info) of
5563 PNG_COLOR_TYPE_GRAY:
5564 Format := tfLuminance8;
5565 PNG_COLOR_TYPE_GRAY_ALPHA:
5566 Format := tfLuminance8Alpha8;
5569 PNG_COLOR_TYPE_RGB_ALPHA:
5572 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5575 // cut upper 8 bit from 16 bit formats
5576 if png_get_bit_depth(png, png_info) > 8 then
5577 png_set_strip_16(png);
5579 // expand bitdepth smaller than 8
5580 if png_get_bit_depth(png, png_info) < 8 then
5581 png_set_expand(png);
5583 // allocating mem for scanlines
5584 LineSize := png_get_rowbytes(png, png_info);
5585 GetMem(png_data, TempHeight * LineSize);
5587 SetLength(png_rows, TempHeight);
5588 for Row := Low(png_rows) to High(png_rows) do begin
5589 png_rows[Row] := png_data;
5590 Inc(png_rows[Row], Row * LineSize);
5593 // read complete image into scanlines
5594 png_read_image(png, @png_rows[0]);
5597 png_read_end(png, png_info);
5599 // destroy read struct
5600 png_destroy_read_struct(@png, @png_info, nil);
5602 SetLength(png_rows, 0);
5605 SetDataPointer(png_data, Format, TempWidth, TempHeight); //be careful, Data could be freed by this method
5609 if Assigned(png_data) then
5619 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5620 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5621 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5626 Row, Col, PixSize, LineSize: Integer;
5627 NewImage, pSource, pDest, pAlpha: pByte;
5628 PngFormat: TglBitmapFormat;
5629 FormatDesc: TFormatDescriptor;
5632 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
5637 StreamPos := aStream.Position;
5638 aStream.Read(Header[0], SizeOf(Header));
5639 aStream.Position := StreamPos;
5641 {Test if the header matches}
5642 if Header = PngHeader then begin
5643 Png := TPNGObject.Create;
5645 Png.LoadFromStream(aStream);
5647 case Png.Header.ColorType of
5649 PngFormat := tfLuminance8;
5650 COLOR_GRAYSCALEALPHA:
5651 PngFormat := tfLuminance8Alpha8;
5653 PngFormat := tfBGR8;
5655 PngFormat := tfBGRA8;
5657 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5660 FormatDesc := TFormatDescriptor.Get(PngFormat);
5661 PixSize := Round(FormatDesc.PixelSize);
5662 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
5664 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5668 case Png.Header.ColorType of
5669 COLOR_RGB, COLOR_GRAYSCALE:
5671 for Row := 0 to Png.Height -1 do begin
5672 Move (Png.Scanline[Row]^, pDest^, LineSize);
5673 Inc(pDest, LineSize);
5676 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5678 PixSize := PixSize -1;
5680 for Row := 0 to Png.Height -1 do begin
5681 pSource := Png.Scanline[Row];
5682 pAlpha := pByte(Png.AlphaScanline[Row]);
5684 for Col := 0 to Png.Width -1 do begin
5685 Move (pSource^, pDest^, PixSize);
5686 Inc(pSource, PixSize);
5687 Inc(pDest, PixSize);
5696 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5699 SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); //be careful, Data could be freed by this method
5703 if Assigned(NewImage) then
5715 {$IFDEF GLB_SUPPORT_PNG_WRITE}
5716 {$IFDEF GLB_LIB_PNG}
5717 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5718 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5720 TStream(png_get_io_ptr(png)).Write(buffer^, size);
5724 {$IF DEFINED(GLB_LIB_PNG)}
5725 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5726 procedure TglBitmap.SavePNG(const aStream: TStream);
5729 png_info: png_infop;
5730 png_rows: array of pByte;
5734 FormatDesc: TFormatDescriptor;
5736 if not (ftPNG in FormatGetSupportedFiles(Format)) then
5737 raise EglBitmapUnsupportedFormat.Create(Format);
5739 if not init_libPNG then
5740 raise Exception.Create('unable to initialize libPNG.');
5744 tfAlpha8, tfLuminance8:
5745 ColorType := PNG_COLOR_TYPE_GRAY;
5747 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
5749 ColorType := PNG_COLOR_TYPE_RGB;
5751 ColorType := PNG_COLOR_TYPE_RGBA;
5753 raise EglBitmapUnsupportedFormat.Create(Format);
5756 FormatDesc := TFormatDescriptor.Get(Format);
5757 LineSize := FormatDesc.GetSize(Width, 1);
5759 // creating array for scanline
5760 SetLength(png_rows, Height);
5762 for Row := 0 to Height - 1 do begin
5763 png_rows[Row] := Data;
5764 Inc(png_rows[Row], Row * LineSize)
5768 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5770 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
5773 png_info := png_create_info_struct(png);
5774 if png_info = nil then begin
5775 png_destroy_write_struct(@png, nil);
5776 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
5779 // set read callback
5780 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
5783 png_set_compression_level(png, 6);
5785 if Format in [tfBGR8, tfBGRA8] then
5788 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
5789 png_write_info(png, png_info);
5790 png_write_image(png, @png_rows[0]);
5791 png_write_end(png, png_info);
5792 png_destroy_write_struct(@png, @png_info);
5794 SetLength(png_rows, 0);
5801 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5802 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5803 procedure TglBitmap.SavePNG(const aStream: TStream);
5807 pSource, pDest: pByte;
5808 X, Y, PixSize: Integer;
5809 ColorType: Cardinal;
5815 if not (ftPNG in FormatGetSupportedFiles (Format)) then
5816 raise EglBitmapUnsupportedFormat.Create(Format);
5819 tfAlpha8, tfLuminance8: begin
5820 ColorType := COLOR_GRAYSCALE;
5824 tfLuminance8Alpha8: begin
5825 ColorType := COLOR_GRAYSCALEALPHA;
5829 tfBGR8, tfRGB8: begin
5830 ColorType := COLOR_RGB;
5834 tfBGRA8, tfRGBA8: begin
5835 ColorType := COLOR_RGBALPHA;
5840 raise EglBitmapUnsupportedFormat.Create(Format);
5843 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
5847 for Y := 0 to Height -1 do begin
5848 pDest := png.ScanLine[Y];
5849 for X := 0 to Width -1 do begin
5850 Move(pSource^, pDest^, PixSize);
5851 Inc(pDest, PixSize);
5852 Inc(pSource, PixSize);
5854 png.AlphaScanline[Y]^[X] := pSource^;
5859 // convert RGB line to BGR
5860 if Format in [tfRGB8, tfRGBA8] then begin
5861 pTemp := png.ScanLine[Y];
5862 for X := 0 to Width -1 do begin
5863 Temp := pByteArray(pTemp)^[0];
5864 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
5865 pByteArray(pTemp)^[2] := Temp;
5872 Png.CompressionLevel := 6;
5873 Png.SaveToStream(aStream);
5881 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5882 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5883 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5884 {$IFDEF GLB_LIB_JPEG}
5886 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
5887 glBitmap_libJPEG_source_mgr = record
5888 pub: jpeg_source_mgr;
5891 SrcBuffer: array [1..4096] of byte;
5894 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
5895 glBitmap_libJPEG_dest_mgr = record
5896 pub: jpeg_destination_mgr;
5898 DestStream: TStream;
5899 DestBuffer: array [1..4096] of byte;
5902 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
5908 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
5914 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
5919 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
5925 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
5931 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5932 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
5934 src: glBitmap_libJPEG_source_mgr_ptr;
5937 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5939 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
5940 if (bytes <= 0) then begin
5941 src^.SrcBuffer[1] := $FF;
5942 src^.SrcBuffer[2] := JPEG_EOI;
5946 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
5947 src^.pub.bytes_in_buffer := bytes;
5952 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5953 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
5955 src: glBitmap_libJPEG_source_mgr_ptr;
5957 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5959 if num_bytes > 0 then begin
5960 // wanted byte isn't in buffer so set stream position and read buffer
5961 if num_bytes > src^.pub.bytes_in_buffer then begin
5962 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
5963 src^.pub.fill_input_buffer(cinfo);
5965 // wanted byte is in buffer so only skip
5966 inc(src^.pub.next_input_byte, num_bytes);
5967 dec(src^.pub.bytes_in_buffer, num_bytes);
5972 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5973 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
5975 dest: glBitmap_libJPEG_dest_mgr_ptr;
5977 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5979 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
5980 // write complete buffer
5981 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
5984 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
5985 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
5991 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5992 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
5995 dest: glBitmap_libJPEG_dest_mgr_ptr;
5997 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5999 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6000 // check for endblock
6001 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6003 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6008 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6013 {$IFDEF GLB_SUPPORT_JPEG_READ}
6014 {$IF DEFINED(GLB_SDL_IMAGE)}
6015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6016 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6018 Surface: PSDL_Surface;
6023 RWops := glBitmapCreateRWops(aStream);
6025 if IMG_isJPG(RWops) > 0 then begin
6026 Surface := IMG_LoadJPG_RW(RWops);
6028 AssignFromSurface(Surface);
6031 SDL_FreeSurface(Surface);
6039 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6040 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6041 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6044 Temp: array[0..1]of Byte;
6046 jpeg: jpeg_decompress_struct;
6047 jpeg_err: jpeg_error_mgr;
6049 IntFormat: TglBitmapFormat;
6051 TempHeight, TempWidth: Integer;
6056 FormatDesc: TFormatDescriptor;
6060 if not init_libJPEG then
6061 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6064 // reading first two bytes to test file and set cursor back to begin
6065 StreamPos := aStream.Position;
6066 aStream.Read({%H-}Temp[0], 2);
6067 aStream.Position := StreamPos;
6069 // if Bitmap then read file.
6070 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6071 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6072 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6075 jpeg.err := jpeg_std_error(@jpeg_err);
6076 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6077 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6079 // decompression struct
6080 jpeg_create_decompress(@jpeg);
6082 // allocation space for streaming methods
6083 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6085 // seeting up custom functions
6086 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6087 pub.init_source := glBitmap_libJPEG_init_source;
6088 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6089 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6090 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6091 pub.term_source := glBitmap_libJPEG_term_source;
6093 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6094 pub.next_input_byte := nil; // until buffer loaded
6096 SrcStream := aStream;
6099 // set global decoding state
6100 jpeg.global_state := DSTATE_START;
6102 // read header of jpeg
6103 jpeg_read_header(@jpeg, false);
6105 // setting output parameter
6106 case jpeg.jpeg_color_space of
6109 jpeg.out_color_space := JCS_GRAYSCALE;
6110 IntFormat := tfLuminance8;
6113 jpeg.out_color_space := JCS_RGB;
6114 IntFormat := tfRGB8;
6118 jpeg_start_decompress(@jpeg);
6120 TempHeight := jpeg.output_height;
6121 TempWidth := jpeg.output_width;
6123 FormatDesc := TFormatDescriptor.Get(IntFormat);
6125 // creating new image
6126 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6130 for Row := 0 to TempHeight -1 do begin
6131 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6132 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6135 // finish decompression
6136 jpeg_finish_decompress(@jpeg);
6138 // destroy decompression
6139 jpeg_destroy_decompress(@jpeg);
6141 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
6145 if Assigned(pImage) then
6155 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6156 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6157 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6162 Temp: array[0..1]of Byte;
6166 // reading first two bytes to test file and set cursor back to begin
6167 StreamPos := aStream.Position;
6168 aStream.Read(Temp[0], 2);
6169 aStream.Position := StreamPos;
6171 // if Bitmap then read file.
6172 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6173 bmp := TBitmap.Create;
6175 jpg := TJPEGImage.Create;
6177 jpg.LoadFromStream(aStream);
6179 result := AssignFromBitmap(bmp);
6191 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6192 {$IF DEFINED(GLB_LIB_JPEG)}
6193 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6194 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6196 jpeg: jpeg_compress_struct;
6197 jpeg_err: jpeg_error_mgr;
6199 pTemp, pTemp2: pByte;
6201 procedure CopyRow(pDest, pSource: pByte);
6205 for X := 0 to Width - 1 do begin
6206 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6207 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6208 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6215 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6216 raise EglBitmapUnsupportedFormat.Create(Format);
6218 if not init_libJPEG then
6219 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6222 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6223 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6226 jpeg.err := jpeg_std_error(@jpeg_err);
6227 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6228 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6230 // compression struct
6231 jpeg_create_compress(@jpeg);
6233 // allocation space for streaming methods
6234 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6236 // seeting up custom functions
6237 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6238 pub.init_destination := glBitmap_libJPEG_init_destination;
6239 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6240 pub.term_destination := glBitmap_libJPEG_term_destination;
6242 pub.next_output_byte := @DestBuffer[1];
6243 pub.free_in_buffer := Length(DestBuffer);
6245 DestStream := aStream;
6248 // very important state
6249 jpeg.global_state := CSTATE_START;
6250 jpeg.image_width := Width;
6251 jpeg.image_height := Height;
6253 tfAlpha8, tfLuminance8: begin
6254 jpeg.input_components := 1;
6255 jpeg.in_color_space := JCS_GRAYSCALE;
6257 tfRGB8, tfBGR8: begin
6258 jpeg.input_components := 3;
6259 jpeg.in_color_space := JCS_RGB;
6263 jpeg_set_defaults(@jpeg);
6264 jpeg_set_quality(@jpeg, 95, true);
6265 jpeg_start_compress(@jpeg, true);
6268 if Format = tfBGR8 then
6269 GetMem(pTemp2, fRowSize)
6274 for Row := 0 to jpeg.image_height -1 do begin
6276 if Format = tfBGR8 then
6277 CopyRow(pTemp2, pTemp)
6282 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6283 inc(pTemp, fRowSize);
6287 if Format = tfBGR8 then
6290 jpeg_finish_compress(@jpeg);
6291 jpeg_destroy_compress(@jpeg);
6297 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6298 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6299 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6304 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6305 raise EglBitmapUnsupportedFormat.Create(Format);
6307 Bmp := TBitmap.Create;
6309 Jpg := TJPEGImage.Create;
6311 AssignToBitmap(Bmp);
6312 if (Format in [tfAlpha8, tfLuminance8]) then begin
6313 Jpg.Grayscale := true;
6314 Jpg.PixelFormat := jf8Bit;
6317 Jpg.SaveToStream(aStream);
6328 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6329 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6330 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6337 BMP_COMP_BITFIELDS = 3;
6340 TBMPHeader = packed record
6345 bfOffBits: Cardinal;
6348 TBMPInfo = packed record
6354 biCompression: Cardinal;
6355 biSizeImage: Cardinal;
6356 biXPelsPerMeter: Longint;
6357 biYPelsPerMeter: Longint;
6358 biClrUsed: Cardinal;
6359 biClrImportant: Cardinal;
6362 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6363 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6365 //////////////////////////////////////////////////////////////////////////////////////////////////
6366 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6369 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6370 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6373 case aInfo.biCompression of
6375 BMP_COMP_RLE8: begin
6376 raise EglBitmapException.Create('RLE compression is not supported');
6378 BMP_COMP_BITFIELDS: begin
6379 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6380 aStream.Read(aMask.r, SizeOf(aMask.r));
6381 aStream.Read(aMask.g, SizeOf(aMask.g));
6382 aStream.Read(aMask.b, SizeOf(aMask.b));
6383 aStream.Read(aMask.a, SizeOf(aMask.a));
6385 raise EglBitmapException.Create('Bitfields are only supported for 16bit and 32bit formats');
6389 //get suitable format
6390 case aInfo.biBitCount of
6391 8: result := tfLuminance8;
6392 16: result := tfBGR5;
6393 24: result := tfBGR8;
6394 32: result := tfBGRA8;
6398 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6401 ColorTable: TbmpColorTable;
6404 if (aInfo.biBitCount >= 16) then
6406 aFormat := tfLuminance8;
6407 c := aInfo.biClrUsed;
6409 c := 1 shl aInfo.biBitCount;
6410 SetLength(ColorTable, c);
6411 for i := 0 to c-1 do begin
6412 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6413 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6417 result := TbmpColorTableFormat.Create;
6418 result.PixelSize := aInfo.biBitCount / 8;
6419 result.ColorTable := ColorTable;
6420 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6423 //////////////////////////////////////////////////////////////////////////////////////////////////
6424 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6425 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6427 TmpFormat: TglBitmapFormat;
6428 FormatDesc: TFormatDescriptor;
6431 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6432 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6433 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6434 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6435 aFormat := FormatDesc.Format;
6440 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6441 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6442 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6443 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6445 result := TbmpBitfieldFormat.Create;
6446 result.PixelSize := aInfo.biBitCount / 8;
6447 result.RedMask := aMask.r;
6448 result.GreenMask := aMask.g;
6449 result.BlueMask := aMask.b;
6450 result.AlphaMask := aMask.a;
6457 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6458 PaddingBuff: Cardinal;
6459 LineBuf, ImageData, TmpData: PByte;
6460 SourceMD, DestMD: Pointer;
6461 BmpFormat: TglBitmapFormat;
6464 Mask: TglBitmapColorRec;
6469 SpecialFormat: TFormatDescriptor;
6470 FormatDesc: TFormatDescriptor;
6472 //////////////////////////////////////////////////////////////////////////////////////////////////
6473 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6476 Pixel: TglBitmapPixelData;
6478 aStream.Read(aLineBuf^, rbLineSize);
6479 SpecialFormat.PreparePixel(Pixel);
6480 for i := 0 to Info.biWidth-1 do begin
6481 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6482 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6483 FormatDesc.Map(Pixel, aData, DestMD);
6489 BmpFormat := tfEmpty;
6490 SpecialFormat := nil;
6496 StartPos := aStream.Position;
6497 aStream.Read(Header{%H-}, SizeOf(Header));
6499 if Header.bfType = BMP_MAGIC then begin
6501 BmpFormat := ReadInfo(Info, Mask);
6502 SpecialFormat := ReadColorTable(BmpFormat, Info);
6503 if not Assigned(SpecialFormat) then
6504 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6505 aStream.Position := StartPos + Header.bfOffBits;
6507 if (BmpFormat <> tfEmpty) then begin
6508 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6509 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6510 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6511 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6514 DestMD := FormatDesc.CreateMappingData;
6515 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6516 GetMem(ImageData, ImageSize);
6517 if Assigned(SpecialFormat) then begin
6518 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6519 SourceMD := SpecialFormat.CreateMappingData;
6524 FillChar(ImageData^, ImageSize, $FF);
6525 TmpData := ImageData;
6526 if (Info.biHeight > 0) then
6527 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6528 for i := 0 to Abs(Info.biHeight)-1 do begin
6529 if Assigned(SpecialFormat) then
6530 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6532 aStream.Read(TmpData^, wbLineSize); //else only read data
6533 if (Info.biHeight > 0) then
6534 dec(TmpData, wbLineSize)
6536 inc(TmpData, wbLineSize);
6537 aStream.Read(PaddingBuff{%H-}, Padding);
6539 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method
6542 if Assigned(LineBuf) then
6544 if Assigned(SourceMD) then
6545 SpecialFormat.FreeMappingData(SourceMD);
6546 FormatDesc.FreeMappingData(DestMD);
6549 if Assigned(ImageData) then
6554 raise EglBitmapException.Create('LoadBMP - No suitable format found');
6556 aStream.Position := StartPos;
6560 FreeAndNil(SpecialFormat);
6563 else aStream.Position := StartPos;
6566 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6567 procedure TglBitmap.SaveBMP(const aStream: TStream);
6571 Converter: TbmpColorTableFormat;
6572 FormatDesc: TFormatDescriptor;
6573 SourceFD, DestFD: Pointer;
6574 pData, srcData, dstData, ConvertBuffer: pByte;
6576 Pixel: TglBitmapPixelData;
6577 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6578 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6580 PaddingBuff: Cardinal;
6582 function GetLineWidth : Integer;
6584 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6588 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6589 raise EglBitmapUnsupportedFormat.Create(Format);
6592 FormatDesc := TFormatDescriptor.Get(Format);
6593 ImageSize := FormatDesc.GetSize(Dimension);
6595 FillChar(Header{%H-}, SizeOf(Header), 0);
6596 Header.bfType := BMP_MAGIC;
6597 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6598 Header.bfReserved1 := 0;
6599 Header.bfReserved2 := 0;
6600 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6602 FillChar(Info{%H-}, SizeOf(Info), 0);
6603 Info.biSize := SizeOf(Info);
6604 Info.biWidth := Width;
6605 Info.biHeight := Height;
6607 Info.biCompression := BMP_COMP_RGB;
6608 Info.biSizeImage := ImageSize;
6613 Info.biBitCount := 4;
6614 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6615 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6616 Converter := TbmpColorTableFormat.Create;
6617 Converter.PixelSize := 0.5;
6618 Converter.Format := Format;
6619 Converter.Range := glBitmapColorRec($F, $F, $F, $0);
6620 Converter.CreateColorTable;
6623 tfR3G3B2, tfLuminance8: begin
6624 Info.biBitCount := 8;
6625 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6626 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6627 Converter := TbmpColorTableFormat.Create;
6628 Converter.PixelSize := 1;
6629 Converter.Format := Format;
6630 if (Format = tfR3G3B2) then begin
6631 Converter.Range := glBitmapColorRec($7, $7, $3, $0);
6632 Converter.Shift := glBitmapShiftRec(0, 3, 6, 0);
6634 Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0);
6635 Converter.CreateColorTable;
6638 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6639 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6640 Info.biBitCount := 16;
6641 Info.biCompression := BMP_COMP_BITFIELDS;
6644 tfBGR8, tfRGB8: begin
6645 Info.biBitCount := 24;
6648 tfRGB10, tfRGB10A2, tfRGBA8,
6649 tfBGR10, tfBGR10A2, tfBGRA8: begin
6650 Info.biBitCount := 32;
6651 Info.biCompression := BMP_COMP_BITFIELDS;
6654 raise EglBitmapUnsupportedFormat.Create(Format);
6656 Info.biXPelsPerMeter := 2835;
6657 Info.biYPelsPerMeter := 2835;
6660 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6661 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
6662 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
6664 RedMask := FormatDesc.RedMask;
6665 GreenMask := FormatDesc.GreenMask;
6666 BlueMask := FormatDesc.BlueMask;
6667 AlphaMask := FormatDesc.AlphaMask;
6671 aStream.Write(Header, SizeOf(Header));
6672 aStream.Write(Info, SizeOf(Info));
6675 if Assigned(Converter) then
6676 aStream.Write(Converter.ColorTable[0].b,
6677 SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable));
6680 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6681 aStream.Write(RedMask, SizeOf(Cardinal));
6682 aStream.Write(GreenMask, SizeOf(Cardinal));
6683 aStream.Write(BlueMask, SizeOf(Cardinal));
6684 aStream.Write(AlphaMask, SizeOf(Cardinal));
6688 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
6689 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
6690 Padding := GetLineWidth - wbLineSize;
6694 inc(pData, (Height-1) * rbLineSize);
6696 // prepare row buffer. But only for RGB because RGBA supports color masks
6697 // so it's possible to change color within the image.
6698 if Assigned(Converter) then begin
6699 FormatDesc.PreparePixel(Pixel);
6700 GetMem(ConvertBuffer, wbLineSize);
6701 SourceFD := FormatDesc.CreateMappingData;
6702 DestFD := Converter.CreateMappingData;
6704 ConvertBuffer := nil;
6707 for LineIdx := 0 to Height - 1 do begin
6709 if Assigned(Converter) then begin
6711 dstData := ConvertBuffer;
6712 for PixelIdx := 0 to Info.biWidth-1 do begin
6713 FormatDesc.Unmap(srcData, Pixel, SourceFD);
6714 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
6715 Converter.Map(Pixel, dstData, DestFD);
6717 aStream.Write(ConvertBuffer^, wbLineSize);
6719 aStream.Write(pData^, rbLineSize);
6721 dec(pData, rbLineSize);
6722 if (Padding > 0) then
6723 aStream.Write(PaddingBuff, Padding);
6726 // destroy row buffer
6727 if Assigned(ConvertBuffer) then begin
6728 FormatDesc.FreeMappingData(SourceFD);
6729 Converter.FreeMappingData(DestFD);
6730 FreeMem(ConvertBuffer);
6734 if Assigned(Converter) then
6739 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6740 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6741 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6743 TTGAHeader = packed record
6747 //ColorMapSpec: Array[0..4] of Byte;
6748 ColorMapStart: Word;
6749 ColorMapLength: Word;
6750 ColorMapEntrySize: Byte;
6760 TGA_UNCOMPRESSED_RGB = 2;
6761 TGA_UNCOMPRESSED_GRAY = 3;
6762 TGA_COMPRESSED_RGB = 10;
6763 TGA_COMPRESSED_GRAY = 11;
6765 TGA_NONE_COLOR_TABLE = 0;
6767 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6768 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
6771 ImageData: System.PByte;
6772 StartPosition: Int64;
6773 PixelSize, LineSize: Integer;
6774 tgaFormat: TglBitmapFormat;
6775 FormatDesc: TFormatDescriptor;
6776 Counter: packed record
6778 low, high, dir: Integer;
6785 ////////////////////////////////////////////////////////////////////////////////////////
6786 procedure ReadUncompressed;
6789 buf, tmp1, tmp2: System.PByte;
6792 if (Counter.X.dir < 0) then
6793 GetMem(buf, LineSize);
6795 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
6797 inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart
6798 if (Counter.X.dir < 0) then begin //flip X
6799 aStream.Read(buf^, LineSize);
6801 inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line
6802 for i := 0 to Header.Width-1 do begin //for all pixels in line
6803 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
6808 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
6811 aStream.Read(tmp1^, LineSize);
6812 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
6815 if Assigned(buf) then
6820 ////////////////////////////////////////////////////////////////////////////////////////
6821 procedure ReadCompressed;
6823 /////////////////////////////////////////////////////////////////
6825 TmpData: System.PByte;
6826 LinePixelsRead: Integer;
6827 procedure CheckLine;
6829 if (LinePixelsRead >= Header.Width) then begin
6830 LinePixelsRead := 0;
6831 inc(Counter.Y.low, Counter.Y.dir); //next line index
6832 TmpData := ImageData;
6833 inc(TmpData, Counter.Y.low * LineSize); //set line
6834 if (Counter.X.dir < 0) then //if x flipped then
6835 inc(TmpData, LineSize - PixelSize); //set last pixel
6839 /////////////////////////////////////////////////////////////////
6842 CacheSize, CachePos: Integer;
6843 procedure CachedRead(out Buffer; Count: Integer);
6847 if (CachePos + Count > CacheSize) then begin
6848 //if buffer overflow save non read bytes
6850 if (CacheSize - CachePos > 0) then begin
6851 BytesRead := CacheSize - CachePos;
6852 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
6853 inc(CachePos, BytesRead);
6856 //load cache from file
6857 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
6858 aStream.Read(Cache^, CacheSize);
6861 //read rest of requested bytes
6862 if (Count - BytesRead > 0) then begin
6863 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
6864 inc(CachePos, Count - BytesRead);
6867 //if no buffer overflow just read the data
6868 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
6869 inc(CachePos, Count);
6873 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
6878 inc(aBuffer, Counter.X.dir);
6881 PWord(aBuffer)^ := PWord(aData)^;
6882 inc(aBuffer, 2 * Counter.X.dir);
6885 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
6886 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
6887 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
6888 inc(aBuffer, 3 * Counter.X.dir);
6891 PCardinal(aBuffer)^ := PCardinal(aData)^;
6892 inc(aBuffer, 4 * Counter.X.dir);
6898 TotalPixelsToRead, TotalPixelsRead: Integer;
6900 buf: array [0..3] of Byte; //1 pixel is max 32bit long
6901 PixelRepeat: Boolean;
6902 PixelsToRead, PixelCount: Integer;
6907 TotalPixelsToRead := Header.Width * Header.Height;
6908 TotalPixelsRead := 0;
6909 LinePixelsRead := 0;
6911 GetMem(Cache, CACHE_SIZE);
6913 TmpData := ImageData;
6914 inc(TmpData, Counter.Y.low * LineSize); //set line
6915 if (Counter.X.dir < 0) then //if x flipped then
6916 inc(TmpData, LineSize - PixelSize); //set last pixel
6920 CachedRead(Temp, 1);
6921 PixelRepeat := (Temp and $80) > 0;
6922 PixelsToRead := (Temp and $7F) + 1;
6923 inc(TotalPixelsRead, PixelsToRead);
6926 CachedRead(buf[0], PixelSize);
6927 while (PixelsToRead > 0) do begin
6929 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
6930 while (PixelCount > 0) do begin
6931 if not PixelRepeat then
6932 CachedRead(buf[0], PixelSize);
6933 PixelToBuffer(@buf[0], TmpData);
6934 inc(LinePixelsRead);
6939 until (TotalPixelsRead >= TotalPixelsToRead);
6945 function IsGrayFormat: Boolean;
6947 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
6953 // reading header to test file and set cursor back to begin
6954 StartPosition := aStream.Position;
6955 aStream.Read(Header{%H-}, SizeOf(Header));
6957 // no colormapped files
6958 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
6959 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
6962 if Header.ImageID <> 0 then // skip image ID
6963 aStream.Position := aStream.Position + Header.ImageID;
6965 tgaFormat := tfEmpty;
6967 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
6968 0: tgaFormat := tfLuminance8;
6969 8: tgaFormat := tfAlpha8;
6972 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
6973 0: tgaFormat := tfLuminance16;
6974 8: tgaFormat := tfLuminance8Alpha8;
6975 end else case (Header.ImageDesc and $F) of
6976 0: tgaFormat := tfBGR5;
6977 1: tgaFormat := tfBGR5A1;
6978 4: tgaFormat := tfBGRA4;
6981 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6982 0: tgaFormat := tfBGR8;
6985 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6986 2: tgaFormat := tfBGR10A2;
6987 8: tgaFormat := tfBGRA8;
6991 if (tgaFormat = tfEmpty) then
6992 raise EglBitmapException.Create('LoadTga - unsupported format');
6994 FormatDesc := TFormatDescriptor.Get(tgaFormat);
6995 PixelSize := FormatDesc.GetSize(1, 1);
6996 LineSize := FormatDesc.GetSize(Header.Width, 1);
6998 GetMem(ImageData, LineSize * Header.Height);
7001 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7002 Counter.X.low := Header.Height-1;;
7003 Counter.X.high := 0;
7004 Counter.X.dir := -1;
7007 Counter.X.high := Header.Height-1;
7012 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7014 Counter.Y.high := Header.Height-1;
7017 Counter.Y.low := Header.Height-1;;
7018 Counter.Y.high := 0;
7019 Counter.Y.dir := -1;
7023 case Header.ImageType of
7024 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7026 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7030 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method
7033 if Assigned(ImageData) then
7038 aStream.Position := StartPosition;
7041 else aStream.Position := StartPosition;
7044 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7045 procedure TglBitmap.SaveTGA(const aStream: TStream);
7048 LineSize, Size, x, y: Integer;
7049 Pixel: TglBitmapPixelData;
7050 LineBuf, SourceData, DestData: PByte;
7051 SourceMD, DestMD: Pointer;
7052 FormatDesc: TFormatDescriptor;
7053 Converter: TFormatDescriptor;
7055 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7056 raise EglBitmapUnsupportedFormat.Create(Format);
7059 FillChar(Header{%H-}, SizeOf(Header), 0);
7062 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7063 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7064 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7066 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7069 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7071 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7072 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7074 else if (Format in [tfBGR8, tfRGB8]) then
7082 Header.ImageDesc := 1 and $F;
7083 tfRGB10A2, tfBGR10A2:
7084 Header.ImageDesc := 2 and $F;
7086 Header.ImageDesc := 4 and $F;
7087 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7088 Header.ImageDesc := 8 and $F;
7091 Header.Width := Width;
7092 Header.Height := Height;
7093 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7094 aStream.Write(Header, SizeOf(Header));
7096 // convert RGB(A) to BGR(A)
7098 FormatDesc := TFormatDescriptor.Get(Format);
7099 Size := FormatDesc.GetSize(Dimension);
7100 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7101 if (FormatDesc.RGBInverted = tfEmpty) then
7102 raise EglBitmapException.Create('inverted RGB format is empty');
7103 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7104 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7105 (Converter.PixelSize <> FormatDesc.PixelSize) then
7106 raise EglBitmapException.Create('invalid inverted RGB format');
7109 if Assigned(Converter) then begin
7110 LineSize := FormatDesc.GetSize(Width, 1);
7111 GetMem(LineBuf, LineSize);
7112 SourceMD := FormatDesc.CreateMappingData;
7113 DestMD := Converter.CreateMappingData;
7116 for y := 0 to Height-1 do begin
7117 DestData := LineBuf;
7118 for x := 0 to Width-1 do begin
7119 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7120 Converter.Map(Pixel, DestData, DestMD);
7122 aStream.Write(LineBuf^, LineSize);
7126 FormatDesc.FreeMappingData(SourceMD);
7127 FormatDesc.FreeMappingData(DestMD);
7130 aStream.Write(Data^, Size);
7133 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7134 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7135 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7137 DDS_MAGIC: Cardinal = $20534444;
7139 // DDS_header.dwFlags
7140 DDSD_CAPS = $00000001;
7141 DDSD_HEIGHT = $00000002;
7142 DDSD_WIDTH = $00000004;
7143 DDSD_PIXELFORMAT = $00001000;
7145 // DDS_header.sPixelFormat.dwFlags
7146 DDPF_ALPHAPIXELS = $00000001;
7147 DDPF_ALPHA = $00000002;
7148 DDPF_FOURCC = $00000004;
7149 DDPF_RGB = $00000040;
7150 DDPF_LUMINANCE = $00020000;
7152 // DDS_header.sCaps.dwCaps1
7153 DDSCAPS_TEXTURE = $00001000;
7155 // DDS_header.sCaps.dwCaps2
7156 DDSCAPS2_CUBEMAP = $00000200;
7158 D3DFMT_DXT1 = $31545844;
7159 D3DFMT_DXT3 = $33545844;
7160 D3DFMT_DXT5 = $35545844;
7163 TDDSPixelFormat = packed record
7167 dwRGBBitCount: Cardinal;
7168 dwRBitMask: Cardinal;
7169 dwGBitMask: Cardinal;
7170 dwBBitMask: Cardinal;
7171 dwABitMask: Cardinal;
7174 TDDSCaps = packed record
7178 dwReserved: Cardinal;
7181 TDDSHeader = packed record
7186 dwPitchOrLinearSize: Cardinal;
7188 dwMipMapCount: Cardinal;
7189 dwReserved: array[0..10] of Cardinal;
7190 PixelFormat: TDDSPixelFormat;
7192 dwReserved2: Cardinal;
7195 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7196 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7199 Converter: TbmpBitfieldFormat;
7201 function GetDDSFormat: TglBitmapFormat;
7203 fd: TFormatDescriptor;
7205 Range: TglBitmapColorRec;
7209 with Header.PixelFormat do begin
7211 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7212 case Header.PixelFormat.dwFourCC of
7213 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7214 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7215 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7217 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7219 //find matching format
7220 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7221 fd := TFormatDescriptor.Get(result);
7222 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7223 (8 * fd.PixelSize = dwRGBBitCount) then
7227 //find format with same Range
7228 Range.r := dwRBitMask;
7229 Range.g := dwGBitMask;
7230 Range.b := dwBBitMask;
7231 Range.a := dwABitMask;
7232 for i := 0 to 3 do begin
7233 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7234 Range.arr[i] := Range.arr[i] shr 1;
7236 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7237 fd := TFormatDescriptor.Get(result);
7240 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7248 //no format with same range found -> use default
7249 if (result = tfEmpty) then begin
7250 if (dwABitMask > 0) then
7256 Converter := TbmpBitfieldFormat.Create;
7257 Converter.RedMask := dwRBitMask;
7258 Converter.GreenMask := dwGBitMask;
7259 Converter.BlueMask := dwBBitMask;
7260 Converter.AlphaMask := dwABitMask;
7261 Converter.PixelSize := dwRGBBitCount / 8;
7268 x, y, LineSize, RowSize, Magic: Cardinal;
7269 NewImage, TmpData, RowData, SrcData: System.PByte;
7270 SourceMD, DestMD: Pointer;
7271 Pixel: TglBitmapPixelData;
7272 ddsFormat: TglBitmapFormat;
7273 FormatDesc: TFormatDescriptor;
7278 StreamPos := aStream.Position;
7281 aStream.Read(Magic{%H-}, sizeof(Magic));
7282 if (Magic <> DDS_MAGIC) then begin
7283 aStream.Position := StreamPos;
7288 aStream.Read(Header{%H-}, sizeof(Header));
7289 if (Header.dwSize <> SizeOf(Header)) or
7290 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7291 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7293 aStream.Position := StreamPos;
7297 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7298 raise EglBitmapException.Create('LoadDDS - CubeMaps are not supported');
7300 ddsFormat := GetDDSFormat;
7302 if (ddsFormat = tfEmpty) then
7303 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7305 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7306 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7307 GetMem(NewImage, Header.dwHeight * LineSize);
7309 TmpData := NewImage;
7312 if Assigned(Converter) then begin
7313 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7314 GetMem(RowData, RowSize);
7315 SourceMD := Converter.CreateMappingData;
7316 DestMD := FormatDesc.CreateMappingData;
7318 for y := 0 to Header.dwHeight-1 do begin
7319 TmpData := NewImage;
7320 inc(TmpData, y * LineSize);
7322 aStream.Read(SrcData^, RowSize);
7323 for x := 0 to Header.dwWidth-1 do begin
7324 Converter.Unmap(SrcData, Pixel, SourceMD);
7325 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7326 FormatDesc.Map(Pixel, TmpData, DestMD);
7330 Converter.FreeMappingData(SourceMD);
7331 FormatDesc.FreeMappingData(DestMD);
7337 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7338 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7339 for Y := 0 to Header.dwHeight-1 do begin
7340 aStream.Read(TmpData^, RowSize);
7341 Inc(TmpData, LineSize);
7346 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7347 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7348 for Y := 0 to Header.dwHeight-1 do begin
7349 aStream.Read(TmpData^, RowSize);
7350 Inc(TmpData, LineSize);
7353 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7355 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method
7358 if Assigned(NewImage) then
7363 FreeAndNil(Converter);
7367 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7368 procedure TglBitmap.SaveDDS(const aStream: TStream);
7371 FormatDesc: TFormatDescriptor;
7373 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7374 raise EglBitmapUnsupportedFormat.Create(Format);
7376 FormatDesc := TFormatDescriptor.Get(Format);
7379 FillChar(Header{%H-}, SizeOf(Header), 0);
7380 Header.dwSize := SizeOf(Header);
7381 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7383 Header.dwWidth := Max(1, Width);
7384 Header.dwHeight := Max(1, Height);
7387 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7390 Header.PixelFormat.dwSize := sizeof(Header);
7391 if (FormatDesc.IsCompressed) then begin
7392 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7394 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7395 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7396 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7398 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7399 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7400 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7401 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7402 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7403 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7404 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7405 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7406 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7408 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7409 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7410 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7411 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7412 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7413 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7416 if (FormatDesc.HasAlpha) then
7417 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7419 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7420 aStream.Write(Header, SizeOf(Header));
7421 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7424 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7425 //TglBitmap1D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7426 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7427 procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7428 const aWidth: Integer; const aHeight: Integer);
7433 if (aHeight > 1) then begin
7434 Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1);
7435 GetMem(pTemp, Size);
7437 Move(aData^, pTemp^, Size);
7446 inherited SetDataPointer(pTemp, aFormat, aWidth);
7449 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7450 function TglBitmap1D.FlipHorz: Boolean;
7453 pTempDest, pDest, pSource: PByte;
7455 result := inherited FlipHorz;
7456 if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin
7458 GetMem(pDest, fRowSize);
7461 Inc(pTempDest, fRowSize);
7462 for Col := 0 to Width-1 do begin
7463 dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data
7464 Move(pSource^, pTempDest^, fPixelSize);
7465 Inc(pSource, fPixelSize);
7467 SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method
7470 if Assigned(pDest) then
7477 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7478 procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean);
7480 FormatDesc: TFormatDescriptor;
7483 FormatDesc := TFormatDescriptor.Get(Format);
7484 if FormatDesc.IsCompressed then
7485 glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
7486 else if aBuildWithGlu then
7487 gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7489 glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7492 if (FreeDataAfterGenTexture) then
7496 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7497 procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean);
7499 BuildWithGlu, TexRec: Boolean;
7502 if Assigned(Data) then begin
7503 // Check Texture Size
7504 if (aTestTextureSize) then begin
7505 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7507 if (Width > TexSize) then
7508 raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7510 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7511 (Target = GL_TEXTURE_RECTANGLE_ARB);
7512 if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7513 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7517 SetupParameters(BuildWithGlu);
7518 UploadData(BuildWithGlu);
7519 glAreTexturesResident(1, @fID, @fIsResident);
7523 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7524 procedure TglBitmap1D.AfterConstruction;
7527 Target := GL_TEXTURE_1D;
7530 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7531 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7532 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7533 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7535 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7536 result := fLines[aIndex]
7541 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7542 procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat;
7543 const aWidth: Integer; const aHeight: Integer);
7545 Idx, LineWidth: Integer;
7547 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7549 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7551 if Assigned(Data) then begin
7552 SetLength(fLines, GetHeight);
7553 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7555 for Idx := 0 to GetHeight-1 do begin
7556 fLines[Idx] := Data;
7557 Inc(fLines[Idx], Idx * LineWidth);
7560 else SetLength(fLines, 0);
7562 SetLength(fLines, 0);
7566 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7567 procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean);
7569 FormatDesc: TFormatDescriptor;
7571 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7573 FormatDesc := TFormatDescriptor.Get(Format);
7574 if FormatDesc.IsCompressed then begin
7575 glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7576 end else if aBuildWithGlu then begin
7577 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7578 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7580 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7581 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7585 if (FreeDataAfterGenTexture) then
7589 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7590 procedure TglBitmap2D.AfterConstruction;
7593 Target := GL_TEXTURE_2D;
7596 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7597 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7600 Size, w, h: Integer;
7601 FormatDesc: TFormatDescriptor;
7603 FormatDesc := TFormatDescriptor.Get(Format);
7604 if FormatDesc.IsCompressed then
7605 raise EglBitmapUnsupportedFormat.Create(Format);
7607 w := aRight - aLeft;
7608 h := aBottom - aTop;
7609 Size := FormatDesc.GetSize(w, h);
7612 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7613 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7614 SetDataPointer(Temp, Format, w, h); //be careful, Data could be freed by this method
7617 if Assigned(Temp) then
7623 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7624 procedure TglBitmap2D.GetDataFromTexture;
7627 TempWidth, TempHeight: Integer;
7628 TempIntFormat: Cardinal;
7629 IntFormat, f: TglBitmapFormat;
7630 FormatDesc: TFormatDescriptor;
7635 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7636 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7637 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7639 IntFormat := tfEmpty;
7640 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
7641 FormatDesc := TFormatDescriptor.Get(f);
7642 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
7643 IntFormat := FormatDesc.Format;
7648 // Getting data from OpenGL
7649 FormatDesc := TFormatDescriptor.Get(IntFormat);
7650 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
7652 if FormatDesc.IsCompressed then
7653 glGetCompressedTexImage(Target, 0, Temp)
7655 glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
7656 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
7658 if Assigned(Temp) then
7664 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7665 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
7667 BuildWithGlu, PotTex, TexRec: Boolean;
7670 if Assigned(Data) then begin
7671 // Check Texture Size
7672 if (aTestTextureSize) then begin
7673 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7675 if ((Height > TexSize) or (Width > TexSize)) then
7676 raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7678 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
7679 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
7680 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7681 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7685 SetupParameters(BuildWithGlu);
7686 UploadData(Target, BuildWithGlu);
7687 glAreTexturesResident(1, @fID, @fIsResident);
7691 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7692 function TglBitmap2D.FlipHorz: Boolean;
7695 TempDestData, DestData, SourceData: PByte;
7698 result := inherited FlipHorz;
7699 if Assigned(Data) then begin
7701 ImgSize := Height * fRowSize;
7702 GetMem(DestData, ImgSize);
7704 TempDestData := DestData;
7705 Dec(TempDestData, fRowSize + fPixelSize);
7706 for Row := 0 to Height -1 do begin
7707 Inc(TempDestData, fRowSize * 2);
7708 for Col := 0 to Width -1 do begin
7709 Move(SourceData^, TempDestData^, fPixelSize);
7710 Inc(SourceData, fPixelSize);
7711 Dec(TempDestData, fPixelSize);
7714 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
7717 if Assigned(DestData) then
7724 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7725 function TglBitmap2D.FlipVert: Boolean;
7728 TempDestData, DestData, SourceData: PByte;
7730 result := inherited FlipVert;
7731 if Assigned(Data) then begin
7733 GetMem(DestData, Height * fRowSize);
7735 TempDestData := DestData;
7736 Inc(TempDestData, Width * (Height -1) * fPixelSize);
7737 for Row := 0 to Height -1 do begin
7738 Move(SourceData^, TempDestData^, fRowSize);
7739 Dec(TempDestData, fRowSize);
7740 Inc(SourceData, fRowSize);
7742 SetDataPointer(DestData, Format); //be careful, Data could be freed by this method
7745 if Assigned(DestData) then
7752 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7753 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7754 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7756 TMatrixItem = record
7761 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
7762 TglBitmapToNormalMapRec = Record
7764 Heights: array of Single;
7765 MatrixU : array of TMatrixItem;
7766 MatrixV : array of TMatrixItem;
7770 ONE_OVER_255 = 1 / 255;
7772 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7773 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
7777 with FuncRec do begin
7779 Source.Data.r * LUMINANCE_WEIGHT_R +
7780 Source.Data.g * LUMINANCE_WEIGHT_G +
7781 Source.Data.b * LUMINANCE_WEIGHT_B;
7782 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
7786 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7787 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
7790 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
7793 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7794 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
7796 TVec = Array[0..2] of Single;
7803 function GetHeight(X, Y: Integer): Single;
7805 with FuncRec do begin
7806 X := Max(0, Min(Size.X -1, X));
7807 Y := Max(0, Min(Size.Y -1, Y));
7808 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
7813 with FuncRec do begin
7814 with PglBitmapToNormalMapRec(Args)^ do begin
7816 for Idx := Low(MatrixU) to High(MatrixU) do
7817 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
7820 for Idx := Low(MatrixU) to High(MatrixU) do
7821 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
7823 Vec[0] := -du * Scale;
7824 Vec[1] := -dv * Scale;
7829 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
7830 if Len <> 0 then begin
7831 Vec[0] := Vec[0] * Len;
7832 Vec[1] := Vec[1] * Len;
7833 Vec[2] := Vec[2] * Len;
7837 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
7838 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
7839 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
7843 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7844 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
7846 Rec: TglBitmapToNormalMapRec;
7848 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
7850 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
7851 Matrix[Index].X := X;
7852 Matrix[Index].Y := Y;
7853 Matrix[Index].W := W;
7858 if TFormatDescriptor.Get(Format).IsCompressed then
7859 raise EglBitmapUnsupportedFormat.Create(Format);
7861 if aScale > 100 then
7863 else if aScale < -100 then
7866 Rec.Scale := aScale;
7868 SetLength(Rec.Heights, Width * Height);
7872 SetLength(Rec.MatrixU, 2);
7873 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
7874 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
7876 SetLength(Rec.MatrixV, 2);
7877 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
7878 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
7882 SetLength(Rec.MatrixU, 6);
7883 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
7884 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
7885 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
7886 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
7887 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
7888 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
7890 SetLength(Rec.MatrixV, 6);
7891 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
7892 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
7893 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
7894 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
7895 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
7896 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
7900 SetLength(Rec.MatrixU, 6);
7901 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
7902 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
7903 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
7904 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
7905 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
7906 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
7908 SetLength(Rec.MatrixV, 6);
7909 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
7910 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
7911 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
7912 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
7913 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
7914 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
7918 SetLength(Rec.MatrixU, 20);
7919 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
7920 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
7921 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
7922 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
7923 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
7924 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
7925 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
7926 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
7927 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
7928 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
7929 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
7930 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
7931 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
7932 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
7933 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
7934 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
7935 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
7936 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
7937 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
7938 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
7940 SetLength(Rec.MatrixV, 20);
7941 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
7942 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
7943 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
7944 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
7945 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
7946 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
7947 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
7948 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
7949 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
7950 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
7951 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
7952 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
7953 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
7954 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
7955 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
7956 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
7957 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
7958 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
7959 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
7960 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
7965 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
7966 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
7968 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
7969 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
7971 SetLength(Rec.Heights, 0);
7975 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7976 //TglBitmapCubeMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7977 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7978 procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean);
7980 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
7983 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7984 procedure TglBitmapCubeMap.AfterConstruction;
7988 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
7989 raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
7992 Target := GL_TEXTURE_CUBE_MAP;
7993 fGenMode := GL_REFLECTION_MAP;
7996 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7997 procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean);
7999 BuildWithGlu: Boolean;
8002 if (aTestTextureSize) then begin
8003 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8005 if (Height > TexSize) or (Width > TexSize) then
8006 raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8008 if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8009 raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8014 SetupParameters(BuildWithGlu);
8015 UploadData(aCubeTarget, BuildWithGlu);
8018 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8019 procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean);
8021 inherited Bind (aEnableTextureUnit);
8022 if aEnableTexCoordsGen then begin
8023 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8024 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8025 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8026 glEnable(GL_TEXTURE_GEN_S);
8027 glEnable(GL_TEXTURE_GEN_T);
8028 glEnable(GL_TEXTURE_GEN_R);
8032 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8033 procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean);
8035 inherited Unbind(aDisableTextureUnit);
8036 if aDisableTexCoordsGen then begin
8037 glDisable(GL_TEXTURE_GEN_S);
8038 glDisable(GL_TEXTURE_GEN_T);
8039 glDisable(GL_TEXTURE_GEN_R);
8043 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8044 //TglBitmapNormalMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8045 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8047 TVec = Array[0..2] of Single;
8048 TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8050 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8051 TglBitmapNormalMapRec = record
8053 Func: TglBitmapNormalMapGetVectorFunc;
8056 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8057 procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8059 aVec[0] := aHalfSize;
8060 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8061 aVec[2] := - (aPosition.X + 0.5 - aHalfSize);
8064 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8065 procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8067 aVec[0] := - aHalfSize;
8068 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8069 aVec[2] := aPosition.X + 0.5 - aHalfSize;
8072 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8073 procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8075 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8076 aVec[1] := aHalfSize;
8077 aVec[2] := aPosition.Y + 0.5 - aHalfSize;
8080 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8081 procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8083 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8084 aVec[1] := - aHalfSize;
8085 aVec[2] := - (aPosition.Y + 0.5 - aHalfSize);
8088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8089 procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8091 aVec[0] := aPosition.X + 0.5 - aHalfSize;
8092 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8093 aVec[2] := aHalfSize;
8096 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8097 procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer);
8099 aVec[0] := - (aPosition.X + 0.5 - aHalfSize);
8100 aVec[1] := - (aPosition.Y + 0.5 - aHalfSize);
8101 aVec[2] := - aHalfSize;
8104 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8105 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8111 with FuncRec do begin
8112 with PglBitmapNormalMapRec(Args)^ do begin
8113 Func(Vec, Position, HalfSize);
8116 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8117 if Len <> 0 then begin
8118 Vec[0] := Vec[0] * Len;
8119 Vec[1] := Vec[1] * Len;
8120 Vec[2] := Vec[2] * Len;
8123 // Scale Vector and AddVectro
8124 Vec[0] := Vec[0] * 0.5 + 0.5;
8125 Vec[1] := Vec[1] * 0.5 + 0.5;
8126 Vec[2] := Vec[2] * 0.5 + 0.5;
8131 Dest.Data.arr[i] := Round(Vec[i] * 255);
8135 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8136 procedure TglBitmapNormalMap.AfterConstruction;
8139 fGenMode := GL_NORMAL_MAP;
8142 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8143 procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean);
8145 Rec: TglBitmapNormalMapRec;
8146 SizeRec: TglBitmapPixelPosition;
8148 Rec.HalfSize := aSize div 2;
8149 FreeDataAfterGenTexture := false;
8151 SizeRec.Fields := [ffX, ffY];
8156 Rec.Func := glBitmapNormalMapPosX;
8157 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8158 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize);
8161 Rec.Func := glBitmapNormalMapNegX;
8162 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8163 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize);
8166 Rec.Func := glBitmapNormalMapPosY;
8167 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8168 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize);
8171 Rec.Func := glBitmapNormalMapNegY;
8172 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8173 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize);
8176 Rec.Func := glBitmapNormalMapPosZ;
8177 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8178 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize);
8181 Rec.Func := glBitmapNormalMapNegZ;
8182 LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec);
8183 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize);
8188 glBitmapSetDefaultFormat(tfEmpty);
8189 glBitmapSetDefaultMipmap(mmMipmap);
8190 glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8191 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8193 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8194 glBitmapSetDefaultDeleteTextureOnFree (true);
8196 TFormatDescriptor.Init;
8198 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8199 OpenGLInitialized := false;
8200 InitOpenGLCS := TCriticalSection.Create;
8204 TFormatDescriptor.Finalize;
8206 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8207 FreeAndNil(InitOpenGLCS);