1 {***********************************************************
2 glBitmap by Steffen Xonna aka Lossy eX (2003-2008)
3 http://www.opengl24.de/index.php?cat=header&file=glbitmap
4 ------------------------------------------------------------
5 The contents of this file are used with permission, subject to
6 the Mozilla Public License Version 1.1 (the "License"); you may
7 not use this file except in compliance with the License. You may
8 obtain a copy of the License at
9 http://www.mozilla.org/MPL/MPL-1.1.html
10 ------------------------------------------------------------
12 ------------------------------------------------------------
15 - The define GLB_DELPHI dosn't check versions anymore. If you say you are using delphi
16 then it's your problem if that isn't true. This prevents the unit for incompatibility
17 with newer versions of Delphi.
18 - Problems with D2009+ resolved (Thanks noeska and all i forgot)
19 - GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson)
21 - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson)
22 - Additional Datapointer for functioninterface now has the name CustomData
24 - AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson)
25 - If you load an texture from an file the property Filename will be set to the name of the file
26 - Three new properties to attach custom data to the Texture objects
27 - CustomName (free for use string)
28 - CustomNameW (free for use widestring)
29 - CustomDataPointer (free for use pointer to attach other objects or complex structures)
31 - RLE TGAs loaded much faster
33 - fixed some problem with reading RLE TGAs.
35 - function clone now only copys data if it's assigned and now it also copies the ID
36 - it seems that lazarus dont like comments in comments.
38 - It's possible to set the id of the texture
39 - define GLB_NO_NATIVE_GL deactivated by default
41 - Now supports the following libraries
45 - Linux compatibillity via free pascal compatibility (delphi sources optional)
46 - BMPs now loaded manuel
48 - Property DataPtr now has the name Data
49 - Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR
50 - Unused Depth removed
51 - Function FreeData to freeing image data added
53 - ImageID flag of TGAs was ignored. (Thanks Zwoetzen)
55 - Function SetBorderColor implemented (only used by opengl if wrap is set to GL_CLAMP_TO_BORDER)
56 - Function AddAlphaFromValue implemented to use an fixed Value as Alphachannel
57 - Function ReadOpenGLExtension is now only intern
59 - pngimage now disabled by default like all other versions.
61 - Setting up an anisotropic filter of 0 isnt allowed by nvidia (Thanks Ogridi)
63 - Fixed some Problem with Delphi 5
64 - Now uses the newest version of pngimage. Makes saving pngs much easier.
66 - Property IsCompressed and Size removed. Not really supported by Spec (Thanks Ogridi)
68 - Internal Format ifDepth8 added
69 - function GrabScreen now supports all uncompressed formats
71 - AddAlphaFromglBitmap implemented
73 - LoadFromResource and LoadFromResourceId now needs an Instance and an ResourceType (for ID)
75 - Width, Height and Depth internal changed to TglBitmapPixelPosition.
76 property Width, Height, Depth are still existing and new property Dimension are avail
78 - Added native OpenGL Support. Breaking the dglOpenGL "barrier".
80 - Added function GrabScreen to class TglBitmap2D
82 - Added support to Save images
83 - Added function Clone to Clone Instance
85 - Functions now works with Cardinals for each channel. Up to 32 Bits per channel.
87 - Several speed optimizations
89 - Internal structure change. Loading of TGA, PNG and DDS improved.
90 Data, format and size will now set directly with SetDataPtr.
91 - AddFunc now works with all Types of Images and Formats
92 - Some Funtions moved to Baseclass TglBitmap
94 - Added Support to decompress DXT3 and DXT5 compressed Images.
95 - Added Mapping to convert data from one format into an other.
97 - Added method ConvertTo in Class TglBitmap2D. Method allows to convert every
98 supported Input format (supported by GetPixel) into any uncompresed Format
99 - Added Support to decompress DXT1 compressed Images.
100 - SwapColors replaced by ConvertTo
102 - Added Support for compressed DDSs
103 - Added new internal formats (DXT1, DXT3, DXT5)
105 - Parameter Components renamed to InternalFormat
107 - Some AllocMem replaced with GetMem (little speed change)
108 - better exception handling. Better protection from memory leaks.
110 - Added support for Direct Draw Surfaces (.DDS) (uncompressed images only)
111 - Added new internal formats (RGB8, RGBA8, RGBA4, RGB5A1, RGB10A2, R5G6B5)
113 - Added support for Grayscale textures
114 - Added internal formats (Alpha, Luminance, LuminanceAlpha, BGR8, BGRA8)
116 - Added support for GL_VERSION_2_0
117 - Added support for GL_EXT_texture_filter_anisotropic
119 - Function FillWithColor fills the Image with one Color
120 - Function LoadNormalMap added
122 - ToNormalMap allows to Create an NormalMap from the Alphachannel
123 - ToNormalMap now supports Sobel (nmSobel) function.
125 - support for RLE Compressed RGB TGAs added
127 - Class TglBitmapNormalMap added to support Normalmap generation
128 - Added function ToNormalMap in class TglBitmap2D to genereate normal maps from textures.
129 3 Filters are supported. (4 Samples, 3x3 and 5x5)
131 - Method LoadCubeMapClass removed
132 - LoadCubeMap returnvalue is now the Texture paramter. Such as LoadTextures
133 - virtual abstract method GenTexture in class TglBitmap now is protected
135 - now support DescriptionFlag in LoadTga. Allows vertical flipped images to be loaded as normal
137 - little enhancement for IsPowerOfTwo
138 - TglBitmap1D.GenTexture now tests NPOT Textures
140 - some little name changes. All properties or function with Texture in name are
141 now without texture in name. We have allways texture so we dosn't name it.
143 - GenTexture now tests if texture is NPOT and NPOT-Texture are supported or
144 TextureTarget is GL_TEXTURE_RECTANGLE. Else it raised an exception.
146 - added support for GL_ARB_texture_rectangle, GL_EXT_texture_rectangle and GL_NV_texture_rectangle
148 - Function Unbind added
149 - call of SetFilter or SetTextureWrap if TextureID exists results in setting properties to opengl texture.
151 - class TglBitmapCubeMap added (allows to Create Cubemaps)
153 - Added Support for PNG Images. (http://pngdelphi.sourceforge.net/)
154 To Enable png's use the define pngimage
156 - New Functioninterface added
157 - Function GetPixel added
159 - Property BuildMipMaps renamed to MipMap
161 - property Name removed.
162 - BuildMipMaps is now a set of 3 values. None, GluBuildMipmaps and SGIS_generate_mipmap
164 - property name added. Only used in glForms!
166 - property FreeDataAfterGenTexture is now available as default (default = true)
167 - BuildMipmaps now implemented in TglBitmap1D (i've forgotten it)
168 - function MoveMemory replaced with function Move (little speed change)
169 - several calculations stored in variables (little speed change)
171 - property BuildMipsMaps added (default = true)
172 if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps
173 - property FreeDataAfterGenTexture added (default = true)
174 if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated.
175 - parameter DisableOtherTextureUnits of Bind removed
176 - parameter FreeDataAfterGeneration of GenTextures removed
178 - TglBitmap dosn't delete data if class was destroyed (fixed)
180 - Bind now enables TextureUnits (by params)
181 - GenTextures can leave data (by param)
182 - LoadTextures now optimal
184 - Performance optimization in AddFunc
185 - procedure Bind moved to subclasses
186 - Added new Class TglBitmap1D to support real OpenGL 1D Textures
188 - Texturefilter and texturewrap now also as defaults
189 Minfilter = GL_LINEAR_MIPMAP_LINEAR
190 Magfilter = GL_LINEAR
191 Wrap(str) = GL_CLAMP_TO_EDGE
192 - Added new format tfCompressed to create a compressed texture.
193 - propertys IsCompressed, TextureSize and IsResident added
194 IsCompressed and TextureSize only contains data from level 0
196 - Added function AddFunc to add PerPixelEffects to Image
197 - LoadFromFunc now based on AddFunc
198 - Invert now based on AddFunc
199 - SwapColors now based on AddFunc
201 - Added function FlipHorz
203 - Added function LaodFromFunc to create images with function
204 - Added function FlipVert
205 - Added internal format RGB(A) if GL_EXT_bgra or OpenGL 1.2 isn't supported
207 - Added Alphafunctions to calculate alpha per function
208 - Added Alpha from ColorKey using alphafunctions
210 - First full functionally Version of glBitmap
211 - Support for 24Bit and 32Bit TGA Pictures added
213 - begin of programming
214 ***********************************************************}
217 {.$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
218 // Please uncomment the defines below to configure the glBitmap to your preferences.
219 // If you have configured the unit you can uncomment the warning above.
221 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
222 // Preferences ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
223 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
224 // activate to enable build-in OpenGL support with statically linked methods
225 // use dglOpenGL.pas if not enabled
226 {.$DEFINE GLB_NATIVE_OGL_STATIC}
228 // activate to enable build-in OpenGL support with dynamically linked methods
229 // use dglOpenGL.pas if not enabled
230 {$DEFINE GLB_NATIVE_OGL_DYNAMIC}
232 // activate to enable the support for SDL_surfaces
235 // activate to enable the support for TBitmap from Delphi (not lazarus)
236 {.$DEFINE GLB_DELPHI}
239 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
240 // activate to enable the support of SDL_image to load files. (READ ONLY)
241 // If you enable SDL_image all other libraries will be ignored!
242 {.$DEFINE GLB_SDL_IMAGE}
244 // activate to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/
245 // if you enable pngimage the libPNG will be ignored
246 {.$DEFINE GLB_PNGIMAGE}
248 // activate to use the libPNG http://www.libpng.org/
249 // You will need an aditional header.
250 // http://www.opengl24.de/index.php?cat=header&file=libpng
251 {.$DEFINE GLB_LIB_PNG}
253 // if you enable delphi jpegs the libJPEG will be ignored
254 {.$DEFINE GLB_DELPHI_JPEG}
256 // activateto use the libJPEG http://www.ijg.org/
257 // You will need an aditional header.
258 // http://www.opengl24.de/index.php?cat=header&file=libjpeg
259 {.$DEFINE GLB_LIB_JPEG}
262 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
263 // PRIVATE: DO not change anything! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
264 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
280 {$IF DEFINED(WIN32) or DEFINED(WIN64)}
282 {$ELSEIF DEFINED(LINUX)}
286 // native OpenGL Support
287 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) OR DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
288 {$DEFINE GLB_NATIVE_OGL}
291 // checking define combinations
293 {$IFDEF GLB_SDL_IMAGE}
295 {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
298 {$IFDEF GLB_PNGIMAGE}
299 {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
300 {$undef GLB_PNGIMAGE}
302 {$IFDEF GLB_DELPHI_JPEG}
303 {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
304 {$undef GLB_DELPHI_JPEG}
307 {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
310 {$IFDEF GLB_LIB_JPEG}
311 {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
312 {$undef GLB_LIB_JPEG}
315 {$DEFINE GLB_SUPPORT_PNG_READ}
316 {$DEFINE GLB_SUPPORT_JPEG_READ}
320 {$IFDEF GLB_PNGIMAGE}
322 {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'}
326 {$DEFINE GLB_SUPPORT_PNG_READ}
327 {$DEFINE GLB_SUPPORT_PNG_WRITE}
332 {$DEFINE GLB_SUPPORT_PNG_READ}
333 {$DEFINE GLB_SUPPORT_PNG_WRITE}
337 {$IFDEF GLB_DELPHI_JPEG}
338 {$IFDEF GLB_LIB_JPEG}
339 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
340 {$undef GLB_LIB_JPEG}
343 {$DEFINE GLB_SUPPORT_JPEG_READ}
344 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
348 {$IFDEF GLB_LIB_JPEG}
349 {$DEFINE GLB_SUPPORT_JPEG_READ}
350 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
354 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) AND DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
355 {$MESSAGE warn 'GLB_NATIVE_OGL_STATIC will be ignored because you enabled GLB_NATIVE_OGL_DYNAMIC'}
369 {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF}
370 {$IF DEFINED(GLB_WIN) AND
371 DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND}
373 {$IFDEF GLB_SDL} SDL, {$ENDIF}
374 {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF}
376 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
378 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
379 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
381 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
382 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
392 TRGBQuad = packed record
400 {$IFDEF GLB_NATIVE_OGL}
406 GL_EXTENSIONS = $1F03;
408 GL_TEXTURE_1D = $0DE0;
409 GL_TEXTURE_2D = $0DE1;
410 GL_TEXTURE_RECTANGLE = $84F5;
412 GL_TEXTURE_WIDTH = $1000;
413 GL_TEXTURE_HEIGHT = $1001;
414 GL_TEXTURE_INTERNAL_FORMAT = $1003;
422 GL_LUMINANCE = $1909;
423 GL_LUMINANCE4 = $803F;
424 GL_LUMINANCE8 = $8040;
425 GL_LUMINANCE12 = $8041;
426 GL_LUMINANCE16 = $8042;
428 GL_LUMINANCE_ALPHA = $190A;
429 GL_LUMINANCE4_ALPHA4 = $8043;
430 GL_LUMINANCE6_ALPHA2 = $8044;
431 GL_LUMINANCE8_ALPHA8 = $8045;
432 GL_LUMINANCE12_ALPHA4 = $8046;
433 GL_LUMINANCE12_ALPHA12 = $8047;
434 GL_LUMINANCE16_ALPHA16 = $8048;
457 GL_DEPTH_COMPONENT = $1902;
458 GL_DEPTH_COMPONENT16 = $81A5;
459 GL_DEPTH_COMPONENT24 = $81A6;
460 GL_DEPTH_COMPONENT32 = $81A7;
462 GL_COMPRESSED_RGB = $84ED;
463 GL_COMPRESSED_RGBA = $84EE;
464 GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
465 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
466 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
467 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
469 GL_UNSIGNED_BYTE = $1401;
470 GL_UNSIGNED_BYTE_3_3_2 = $8032;
471 GL_UNSIGNED_BYTE_2_3_3_REV = $8362;
473 GL_UNSIGNED_SHORT = $1403;
474 GL_UNSIGNED_SHORT_5_6_5 = $8363;
475 GL_UNSIGNED_SHORT_4_4_4_4 = $8033;
476 GL_UNSIGNED_SHORT_5_5_5_1 = $8034;
477 GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
478 GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
479 GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
481 GL_UNSIGNED_INT = $1405;
482 GL_UNSIGNED_INT_8_8_8_8 = $8035;
483 GL_UNSIGNED_INT_10_10_10_2 = $8036;
484 GL_UNSIGNED_INT_8_8_8_8_REV = $8367;
485 GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
488 GL_TEXTURE_MAG_FILTER = $2800;
489 GL_TEXTURE_MIN_FILTER = $2801;
491 GL_NEAREST_MIPMAP_NEAREST = $2700;
492 GL_NEAREST_MIPMAP_LINEAR = $2702;
494 GL_LINEAR_MIPMAP_NEAREST = $2701;
495 GL_LINEAR_MIPMAP_LINEAR = $2703;
498 GL_TEXTURE_WRAP_S = $2802;
499 GL_TEXTURE_WRAP_T = $2803;
500 GL_TEXTURE_WRAP_R = $8072;
503 GL_CLAMP_TO_EDGE = $812F;
504 GL_CLAMP_TO_BORDER = $812D;
505 GL_MIRRORED_REPEAT = $8370;
508 GL_GENERATE_MIPMAP = $8191;
509 GL_TEXTURE_BORDER_COLOR = $1004;
510 GL_MAX_TEXTURE_SIZE = $0D33;
511 GL_PACK_ALIGNMENT = $0D05;
512 GL_UNPACK_ALIGNMENT = $0CF5;
514 GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
515 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
518 libglu = 'libGLU.so.1';
519 libopengl = 'libGL.so.1';
521 libglu = 'glu32.dll';
522 libopengl = 'opengl32.dll';
526 GLboolean = BYTEBOOL;
534 PGLboolean = ^GLboolean;
539 TglCompressedTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
540 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}
541 TglGetCompressedTexImage = procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
543 {$IF DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
544 TglEnable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
545 TglDisable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
547 TglGetString = function(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
548 TglGetIntegerv = procedure(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
550 TglTexParameteri = procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
551 TglTexParameterfv = procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
552 TglGetTexParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
553 TglGetTexParameterfv = procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
554 TglGetTexLevelParameteriv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
555 TglGetTexLevelParameterfv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
557 TglGenTextures = procedure(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
558 TglBindTexture = procedure(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
559 TglDeleteTextures = procedure(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
561 TglAreTexturesResident = function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
562 TglReadPixels = procedure(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
563 TglPixelStorei = procedure(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
565 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}
566 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}
567 TglGetTexImage = procedure(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
569 TgluBuild1DMipmaps = function(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
570 TgluBuild2DMipmaps = function(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
573 TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl;
575 TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall;
578 {$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)}
579 procedure glEnable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
580 procedure glDisable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
582 function glGetString(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
583 procedure glGetIntegerv(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
585 procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
586 procedure glTexParameterfv(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
587 procedure glGetTexParameteriv(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
588 procedure glGetTexParameterfv(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
589 procedure glGetTexLevelParameteriv(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
590 procedure glGetTexLevelParameterfv(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
592 procedure glGenTextures(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
593 procedure glBindTexture(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
594 procedure glDeleteTextures(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
596 function glAreTexturesResident(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
597 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;
598 procedure glPixelStorei(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
600 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;
601 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;
602 procedure glGetTexImage(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
604 function gluBuild1DMipmaps(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
605 function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
614 GL_SGIS_generate_mipmap,
616 GL_ARB_texture_border_clamp,
617 GL_ARB_texture_mirrored_repeat,
618 GL_ARB_texture_rectangle,
619 GL_ARB_texture_non_power_of_two,
621 GL_IBM_texture_mirrored_repeat,
623 GL_NV_texture_rectangle,
625 GL_EXT_texture_edge_clamp,
626 GL_EXT_texture_rectangle,
627 GL_EXT_texture_filter_anisotropic: Boolean;
629 glCompressedTexImage1D: TglCompressedTexImage1D;
630 glCompressedTexImage2D: TglCompressedTexImage2D;
631 glGetCompressedTexImage: TglGetCompressedTexImage;
633 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
635 glDisable: TglDisable;
637 glGetString: TglGetString;
638 glGetIntegerv: TglGetIntegerv;
640 glTexParameteri: TglTexParameteri;
641 glTexParameterfv: TglTexParameterfv;
642 glGetTexParameteriv: TglGetTexParameteriv;
643 glGetTexParameterfv: TglGetTexParameterfv;
644 glGetTexLevelParameteriv: TglGetTexLevelParameteriv;
645 glGetTexLevelParameterfv: TglGetTexLevelParameterfv;
647 glGenTextures: TglGenTextures;
648 glBindTexture: TglBindTexture;
649 glDeleteTextures: TglDeleteTextures;
651 glAreTexturesResident: TglAreTexturesResident;
652 glReadPixels: TglReadPixels;
653 glPixelStorei: TglPixelStorei;
655 glTexImage1D: TglTexImage1D;
656 glTexImage2D: TglTexImage2D;
657 glGetTexImage: TglGetTexImage;
659 gluBuild1DMipmaps: TgluBuild1DMipmaps;
660 gluBuild2DMipmaps: TgluBuild2DMipmaps;
662 {$IF DEFINED(GLB_WIN)}
663 wglGetProcAddress: TwglGetProcAddress;
664 {$ELSEIF DEFINED(GLB_LINUX)}
665 glXGetProcAddress: TglXGetProcAddress;
666 glXGetProcAddressARB: TglXGetProcAddressARB;
680 ////////////////////////////////////////////////////////////////////////////////////////////////////
681 EglBitmapException = class(Exception);
682 EglBitmapSizeToLargeException = class(EglBitmapException);
683 EglBitmapNonPowerOfTwoException = class(EglBitmapException);
684 EglBitmapUnsupportedFormatFormat = class(EglBitmapException);
686 ////////////////////////////////////////////////////////////////////////////////////////////////////
688 tfEmpty = 0, //must be smallest value!
704 tfLuminance12Alpha12,
705 tfLuminance16Alpha16,
749 TglBitmapFileType = (
750 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
751 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
755 TglBitmapFileTypes = set of TglBitmapFileType;
762 TglBitmapNormalMapFunc = (
768 ////////////////////////////////////////////////////////////////////////////////////////////////////
769 TglBitmapColorRec = packed record
771 0: (r, g, b, a: Cardinal);
772 1: (arr: array[0..3] of Cardinal);
775 TglBitmapPixelData = packed record
776 Data, Range: TglBitmapColorRec;
777 Format: TglBitmapFormat;
779 PglBitmapPixelData = ^TglBitmapPixelData;
781 ////////////////////////////////////////////////////////////////////////////////////////////////////
782 TglBitmapPixelPositionFields = set of (ffX, ffY);
783 TglBitmapPixelPosition = record
784 Fields : TglBitmapPixelPositionFields;
789 ////////////////////////////////////////////////////////////////////////////////////////////////////
791 TglBitmapFunctionRec = record
793 Size: TglBitmapPixelPosition;
794 Position: TglBitmapPixelPosition;
795 Source: TglBitmapPixelData;
796 Dest: TglBitmapPixelData;
799 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
801 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
806 fAnisotropic: Integer;
807 fDeleteTextureOnFree: Boolean;
808 fFreeDataAfterGenTexture: Boolean;
810 fIsResident: Boolean;
811 fBorderColor: array[0..3] of Single;
813 fDimension: TglBitmapPixelPosition;
814 fMipMap: TglBitmapMipMap;
815 fFormat: TglBitmapFormat;
822 fFilterMin: Cardinal;
823 fFilterMag: Cardinal;
833 fCustomNameW: WideString;
834 fCustomData: Pointer;
837 function GetWidth: Integer; virtual;
838 function GetHeight: Integer; virtual;
840 function GetFileWidth: Integer; virtual;
841 function GetFileHeight: Integer; virtual;
844 procedure SetCustomData(const aValue: Pointer);
845 procedure SetCustomName(const aValue: String);
846 procedure SetCustomNameW(const aValue: WideString);
847 procedure SetDeleteTextureOnFree(const aValue: Boolean);
848 procedure SetFormat(const aValue: TglBitmapFormat);
849 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
850 procedure SetID(const aValue: Cardinal);
851 procedure SetMipMap(const aValue: TglBitmapMipMap);
852 procedure SetTarget(const aValue: Cardinal);
853 procedure SetAnisotropic(const aValue: Integer);
856 procedure SetupParameters(out aBuildWithGlu: Boolean);
857 procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
858 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual;
859 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
861 function FlipHorz: Boolean; virtual;
862 function FlipVert: Boolean; virtual;
864 property Width: Integer read GetWidth;
865 property Height: Integer read GetHeight;
867 property FileWidth: Integer read GetFileWidth;
868 property FileHeight: Integer read GetFileHeight;
871 property ID: Cardinal read fID write SetID;
872 property Target: Cardinal read fTarget write SetTarget;
873 property Format: TglBitmapFormat read fFormat write SetFormat;
874 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
875 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
877 property Filename: String read fFilename;
878 property CustomName: String read fCustomName write SetCustomName;
879 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
880 property CustomData: Pointer read fCustomData write SetCustomData;
882 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
883 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
885 property Dimension: TglBitmapPixelPosition read fDimension;
886 property Data: PByte read fData;
887 property IsResident: Boolean read fIsResident;
889 procedure AfterConstruction; override;
890 procedure BeforeDestruction; override;
893 procedure LoadFromFile(const aFilename: String);
894 procedure LoadFromStream(const aStream: TStream); virtual;
895 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
896 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil);
898 procedure LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
899 procedure LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
903 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
904 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
907 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
908 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
909 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
913 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
914 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
915 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
916 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
917 const aArgs: Pointer = nil): Boolean;
921 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
922 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
923 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
924 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
925 const aArgs: Pointer = nil): Boolean;
926 function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil;
927 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
928 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
929 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
932 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
933 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
934 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
935 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
937 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
938 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
939 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
941 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
942 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
943 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
945 function RemoveAlpha: Boolean; virtual;
948 function Clone: TglBitmap;
949 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
950 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
951 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
955 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
956 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
957 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
960 procedure SetFilter(const aMin, aMag: Cardinal);
962 const S: Cardinal = GL_CLAMP_TO_EDGE;
963 const T: Cardinal = GL_CLAMP_TO_EDGE;
964 const R: Cardinal = GL_CLAMP_TO_EDGE);
966 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
967 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
970 constructor Create; overload;
971 constructor Create(const aFileName: String); overload;
972 constructor Create(const aStream: TStream); overload;
973 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload;
974 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;
980 {$IFDEF GLB_SUPPORT_PNG_READ}
981 function LoadPNG(const aStream: TStream): Boolean; virtual;
982 procedure SavePNG(const aStream: TStream); virtual;
984 {$IFDEF GLB_SUPPORT_JPEG_READ}
985 function LoadJPEG(const aStream: TStream): Boolean; virtual;
986 procedure SaveJPEG(const aStream: TStream); virtual;
988 function LoadBMP(const aStream: TStream): Boolean; virtual;
989 procedure SaveBMP(const aStream: TStream); virtual;
991 function LoadTGA(const aStream: TStream): Boolean; virtual;
992 procedure SaveTGA(const aStream: TStream); virtual;
994 function LoadDDS(const aStream: TStream): Boolean; virtual;
995 procedure SaveDDS(const aStream: TStream); virtual;
998 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
999 TglBitmap2D = class(TglBitmap)
1001 // Bildeinstellungen
1002 fLines: array of PByte;
1005 procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
1006 procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1007 procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1008 procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1009 procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1010 procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
1013 function GetScanline(const aIndex: Integer): Pointer;
1014 procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
1015 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1016 procedure UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
1020 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
1022 procedure AfterConstruction; override;
1024 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
1025 procedure GetDataFromTexture;
1026 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1028 function FlipHorz: Boolean; override;
1029 function FlipVert: Boolean; override;
1031 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
1032 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1036 TglBitmapCubeMap = class(TglBitmap2D)
1041 procedure GenTexture(TestTextureSize: Boolean = true); reintroduce;
1043 procedure AfterConstruction; override;
1045 procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true);
1047 procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = true); reintroduce; virtual;
1048 procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = true); reintroduce; virtual;
1052 TglBitmapNormalMap = class(TglBitmapCubeMap)
1054 procedure AfterConstruction; override;
1056 procedure GenerateNormalMap(Size: Integer = 32; TestTextureSize: Boolean = true);
1060 TglBitmap1D = class(TglBitmap)
1062 procedure GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1064 procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override;
1065 procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
1070 procedure AfterConstruction; override;
1073 function FlipHorz: Boolean; override;
1076 procedure GenTexture(TestTextureSize: Boolean = true); override;
1081 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1083 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1084 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1085 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1086 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1087 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1088 procedure glBitmapSetDefaultWrap(
1089 const S: Cardinal = GL_CLAMP_TO_EDGE;
1090 const T: Cardinal = GL_CLAMP_TO_EDGE;
1091 const R: Cardinal = GL_CLAMP_TO_EDGE);
1093 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1094 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1095 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1096 function glBitmapGetDefaultFormat: TglBitmapFormat;
1097 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1098 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1100 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1101 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1102 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1105 glBitmapDefaultDeleteTextureOnFree: Boolean;
1106 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1107 glBitmapDefaultFormat: TglBitmapFormat;
1108 glBitmapDefaultMipmap: TglBitmapMipMap;
1109 glBitmapDefaultFilterMin: Cardinal;
1110 glBitmapDefaultFilterMag: Cardinal;
1111 glBitmapDefaultWrapS: Cardinal;
1112 glBitmapDefaultWrapT: Cardinal;
1113 glBitmapDefaultWrapR: Cardinal;
1116 function CreateGrayPalette: HPALETTE;
1123 function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
1124 function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
1125 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
1126 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
1127 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
1134 ////////////////////////////////////////////////////////////////////////////////////////////////////
1135 TShiftRec = packed record
1137 0: (r, g, b, a: Byte);
1138 1: (arr: array[0..3] of Byte);
1141 TFormatDescriptor = class(TObject)
1143 function GetRedMask: UInt64;
1144 function GetGreenMask: UInt64;
1145 function GetBlueMask: UInt64;
1146 function GetAlphaMask: UInt64;
1148 fFormat: TglBitmapFormat;
1149 fWithAlpha: TglBitmapFormat;
1150 fWithoutAlpha: TglBitmapFormat;
1151 fRGBInverted: TglBitmapFormat;
1152 fUncompressed: TglBitmapFormat;
1154 fIsCompressed: Boolean;
1156 fRange: TglBitmapColorRec;
1159 fglFormat: Cardinal;
1160 fglInternalFormat: Cardinal;
1161 fglDataFormat: Cardinal;
1163 function GetComponents: Integer; virtual;
1165 property Format: TglBitmapFormat read fFormat;
1166 property WithAlpha: TglBitmapFormat read fWithAlpha;
1167 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1168 property RGBInverted: TglBitmapFormat read fRGBInverted;
1169 property Components: Integer read GetComponents;
1170 property PixelSize: Single read fPixelSize;
1171 property IsCompressed: Boolean read fIsCompressed;
1173 property glFormat: Cardinal read fglFormat;
1174 property glInternalFormat: Cardinal read fglInternalFormat;
1175 property glDataFormat: Cardinal read fglDataFormat;
1177 property Range: TglBitmapColorRec read fRange;
1178 property Shift: TShiftRec read fShift;
1180 property RedMask: UInt64 read GetRedMask;
1181 property GreenMask: UInt64 read GetGreenMask;
1182 property BlueMask: UInt64 read GetBlueMask;
1183 property AlphaMask: UInt64 read GetAlphaMask;
1185 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1186 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1188 function GetSize(const aSize: TglBitmapPixelPosition): Integer; virtual; overload;
1189 function GetSize(const aWidth, aHeight: Integer): Integer; virtual; overload;
1191 function CreateMappingData: Pointer; virtual;
1192 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1194 function IsEmpty: Boolean; virtual;
1195 function HasAlpha: Boolean; virtual;
1196 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual;
1198 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1200 constructor Create; virtual;
1202 class procedure Init;
1203 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1204 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1205 class procedure Clear;
1206 class procedure Finalize;
1208 TFormatDescriptorClass = class of TFormatDescriptor;
1210 TfdEmpty = class(TFormatDescriptor);
1212 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1213 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1214 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1215 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1216 constructor Create; override;
1219 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1220 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1221 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1222 constructor Create; override;
1225 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1226 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1227 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1228 constructor Create; override;
1231 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1232 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1233 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1234 constructor Create; override;
1237 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1238 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1239 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1240 constructor Create; override;
1243 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1244 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1245 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1246 constructor Create; override;
1249 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1250 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1251 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1252 constructor Create; override;
1255 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1256 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1257 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1258 constructor Create; override;
1261 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1262 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1263 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1264 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1265 constructor Create; override;
1268 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1269 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1270 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1271 constructor Create; override;
1274 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1275 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1276 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1277 constructor Create; override;
1280 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1281 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1282 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1283 constructor Create; override;
1286 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1287 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1288 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1289 constructor Create; override;
1292 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1293 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1294 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1295 constructor Create; override;
1298 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1299 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1300 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1301 constructor Create; override;
1304 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1305 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1306 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1307 constructor Create; override;
1310 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1311 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1312 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1313 constructor Create; override;
1316 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1317 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1318 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1319 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1320 constructor Create; override;
1323 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1324 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1325 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1326 constructor Create; override;
1329 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1330 TfdAlpha4 = class(TfdAlpha_UB1)
1331 constructor Create; override;
1334 TfdAlpha8 = class(TfdAlpha_UB1)
1335 constructor Create; override;
1338 TfdAlpha12 = class(TfdAlpha_US1)
1339 constructor Create; override;
1342 TfdAlpha16 = class(TfdAlpha_US1)
1343 constructor Create; override;
1346 TfdLuminance4 = class(TfdLuminance_UB1)
1347 constructor Create; override;
1350 TfdLuminance8 = class(TfdLuminance_UB1)
1351 constructor Create; override;
1354 TfdLuminance12 = class(TfdLuminance_US1)
1355 constructor Create; override;
1358 TfdLuminance16 = class(TfdLuminance_US1)
1359 constructor Create; override;
1362 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1363 constructor Create; override;
1366 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1367 constructor Create; override;
1370 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1371 constructor Create; override;
1374 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1375 constructor Create; override;
1378 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1379 constructor Create; override;
1382 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1383 constructor Create; override;
1386 TfdR3G3B2 = class(TfdUniversal_UB1)
1387 constructor Create; override;
1390 TfdRGB4 = class(TfdUniversal_US1)
1391 constructor Create; override;
1394 TfdR5G6B5 = class(TfdUniversal_US1)
1395 constructor Create; override;
1398 TfdRGB5 = class(TfdUniversal_US1)
1399 constructor Create; override;
1402 TfdRGB8 = class(TfdRGB_UB3)
1403 constructor Create; override;
1406 TfdRGB10 = class(TfdUniversal_UI1)
1407 constructor Create; override;
1410 TfdRGB12 = class(TfdRGB_US3)
1411 constructor Create; override;
1414 TfdRGB16 = class(TfdRGB_US3)
1415 constructor Create; override;
1418 TfdRGBA2 = class(TfdRGBA_UB4)
1419 constructor Create; override;
1422 TfdRGBA4 = class(TfdUniversal_US1)
1423 constructor Create; override;
1426 TfdRGB5A1 = class(TfdUniversal_US1)
1427 constructor Create; override;
1430 TfdRGBA8 = class(TfdRGBA_UB4)
1431 constructor Create; override;
1434 TfdRGB10A2 = class(TfdUniversal_UI1)
1435 constructor Create; override;
1438 TfdRGBA12 = class(TfdRGBA_US4)
1439 constructor Create; override;
1442 TfdRGBA16 = class(TfdRGBA_US4)
1443 constructor Create; override;
1446 TfdBGR4 = class(TfdUniversal_US1)
1447 constructor Create; override;
1450 TfdB5G6R5 = class(TfdUniversal_US1)
1451 constructor Create; override;
1454 TfdBGR5 = class(TfdUniversal_US1)
1455 constructor Create; override;
1458 TfdBGR8 = class(TfdBGR_UB3)
1459 constructor Create; override;
1462 TfdBGR10 = class(TfdUniversal_UI1)
1463 constructor Create; override;
1466 TfdBGR12 = class(TfdBGR_US3)
1467 constructor Create; override;
1470 TfdBGR16 = class(TfdBGR_US3)
1471 constructor Create; override;
1474 TfdBGRA2 = class(TfdBGRA_UB4)
1475 constructor Create; override;
1478 TfdBGRA4 = class(TfdUniversal_US1)
1479 constructor Create; override;
1482 TfdBGR5A1 = class(TfdUniversal_US1)
1483 constructor Create; override;
1486 TfdBGRA8 = class(TfdBGRA_UB4)
1487 constructor Create; override;
1490 TfdBGR10A2 = class(TfdUniversal_UI1)
1491 constructor Create; override;
1494 TfdBGRA12 = class(TfdBGRA_US4)
1495 constructor Create; override;
1498 TfdBGRA16 = class(TfdBGRA_US4)
1499 constructor Create; override;
1502 TfdDepth16 = class(TfdDepth_US1)
1503 constructor Create; override;
1506 TfdDepth24 = class(TfdDepth_UI1)
1507 constructor Create; override;
1510 TfdDepth32 = class(TfdDepth_UI1)
1511 constructor Create; override;
1514 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1515 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1516 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1517 constructor Create; override;
1520 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
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;
1523 constructor Create; override;
1526 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1527 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1528 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1529 constructor Create; override;
1532 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1533 TbmpBitfieldFormat = class(TFormatDescriptor)
1535 procedure SetRedMask (const aValue: UInt64);
1536 procedure SetGreenMask(const aValue: UInt64);
1537 procedure SetBlueMask (const aValue: UInt64);
1538 procedure SetAlphaMask(const aValue: UInt64);
1540 procedure Update(aMask: UInt64; out aRange: Cardinal; out aShift: Byte);
1542 property RedMask: UInt64 read GetRedMask write SetRedMask;
1543 property GreenMask: UInt64 read GetGreenMask write SetGreenMask;
1544 property BlueMask: UInt64 read GetBlueMask write SetBlueMask;
1545 property AlphaMask: UInt64 read GetAlphaMask write SetAlphaMask;
1547 property PixelSize: Single read fPixelSize write fPixelSize;
1549 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1550 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1553 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1554 TbmpColorTableEnty = packed record
1557 TbmpColorTable = array of TbmpColorTableEnty;
1558 TbmpColorTableFormat = class(TFormatDescriptor)
1560 fColorTable: TbmpColorTable;
1562 property PixelSize: Single read fPixelSize write fPixelSize;
1563 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1564 property Range: TglBitmapColorRec read fRange write fRange;
1565 property Shift: TShiftRec read fShift write fShift;
1566 property Format: TglBitmapFormat read fFormat write fFormat;
1568 procedure CreateColorTable;
1570 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1571 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1572 destructor Destroy; override;
1576 LUMINANCE_WEIGHT_R = 0.30;
1577 LUMINANCE_WEIGHT_G = 0.59;
1578 LUMINANCE_WEIGHT_B = 0.11;
1580 ALPHA_WEIGHT_R = 0.30;
1581 ALPHA_WEIGHT_G = 0.59;
1582 ALPHA_WEIGHT_B = 0.11;
1584 DEPTH_WEIGHT_R = 0.333333333;
1585 DEPTH_WEIGHT_G = 0.333333333;
1586 DEPTH_WEIGHT_B = 0.333333333;
1588 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1590 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1603 TfdLuminance4Alpha4,
1604 TfdLuminance6Alpha2,
1605 TfdLuminance8Alpha8,
1606 TfdLuminance12Alpha4,
1607 TfdLuminance12Alpha12,
1608 TfdLuminance16Alpha16,
1653 FormatDescriptorCS: TCriticalSection;
1654 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1656 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1657 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1659 result.Fields := [];
1662 result.Fields := result.Fields + [ffX];
1664 result.Fields := result.Fields + [ffY];
1666 result.X := Max(0, X);
1667 result.Y := Max(0, Y);
1670 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1671 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1679 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1680 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1685 for i := 0 to high(r1.arr) do
1686 if (r1.arr[i] <> r2.arr[i]) then
1691 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1692 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1700 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1701 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1710 tfR3G3B2, tfLuminance8,
1713 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1714 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1720 tfRGB10, tfRGB10A2, tfRGBA8,
1721 tfBGR10, tfBGR10A2, tfBGRA8]) then
1722 result := result + [ftBMP];
1726 tfLuminance8, tfAlpha8,
1729 tfLuminance16, tfLuminance8Alpha8,
1730 tfRGB5, tfRGB5A1, tfRGBA4,
1731 tfBGR5, tfBGR5A1, tfBGRA4,
1737 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1738 result := result + [ftTGA];
1742 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1743 tfR3G3B2, tfRGBA2, tfBGRA2,
1746 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1747 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1748 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1754 tfLuminance16Alpha16,
1759 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1760 result := result + [ftDDS];
1763 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1765 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1766 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1767 tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
1768 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1769 tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
1770 tfDepth16, tfDepth24, tfDepth32]
1772 result := result + [ftPNG];
1775 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1777 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1778 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1779 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1780 tfDepth16, tfDepth24, tfDepth32]
1782 result := result + [ftJPEG];
1786 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1787 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1788 tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
1789 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1790 tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
1791 tfDepth16, tfDepth24, tfDepth32]
1793 result := result + [ftDDS, ftTGA, ftBMP];
1797 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1798 function IsPowerOfTwo(aNumber: Integer): Boolean;
1800 while (aNumber and 1) = 0 do
1801 aNumber := aNumber shr 1;
1802 result := aNumber = 1;
1805 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1806 function GetTopMostBit(aBitSet: UInt64): Integer;
1809 while aBitSet > 0 do begin
1811 aBitSet := aBitSet shr 1;
1815 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1816 function CountSetBits(aBitSet: UInt64): Integer;
1819 while aBitSet > 0 do begin
1820 if (aBitSet and 1) = 1 then
1822 aBitSet := aBitSet shr 1;
1826 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1827 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1830 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1831 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1832 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1835 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1836 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1839 DEPTH_WEIGHT_R * aPixel.Data.r +
1840 DEPTH_WEIGHT_G * aPixel.Data.g +
1841 DEPTH_WEIGHT_B * aPixel.Data.b);
1844 {$IFDEF GLB_NATIVE_OGL}
1845 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1846 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1847 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1849 GL_LibHandle: Pointer = nil;
1851 function glbGetProcAddress(aProcName: PChar; aLibHandle: Pointer = nil): Pointer;
1855 if not Assigned(aLibHandle) then
1856 aLibHandle := GL_LibHandle;
1858 {$IF DEFINED(GLB_WIN)}
1859 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1860 if Assigned(result) then
1863 if Assigned(wglGetProcAddress) then
1864 result := wglGetProcAddress(aProcName);
1865 {$ELSEIF DEFINED(GLB_LINUX)}
1866 if Assigned(glXGetProcAddress) then begin
1867 result := glXGetProcAddress(aProcName);
1868 if Assigned(result) then
1872 if Assigned(glXGetProcAddressARB) then begin
1873 result := glXGetProcAddressARB(aProcName);
1874 if Assigned(result) then
1878 result := dlsym(aLibHandle, aProcName);
1880 if not Assigned(result) then
1881 raise EglBitmapException.Create('unable to load procedure form library: ' + aProcName);
1884 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1886 GLU_LibHandle: Pointer = nil;
1887 OpenGLInitialized: Boolean;
1888 InitOpenGLCS: TCriticalSection;
1890 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1891 procedure glbInitOpenGL;
1893 ////////////////////////////////////////////////////////////////////////////////
1894 function glbLoadLibrary(const aName: PChar): Pointer;
1896 {$IF DEFINED(GLB_WIN)}
1897 result := {%H-}Pointer(LoadLibrary(aName));
1898 {$ELSEIF DEFINED(GLB_LINUX)}
1899 result := dlopen(Name, RTLD_LAZY);
1905 ////////////////////////////////////////////////////////////////////////////////
1906 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
1909 if not Assigned(aLibHandle) then
1912 {$IF DEFINED(GLB_WIN)}
1913 Result := FreeLibrary({%H-}HINST(aLibHandle));
1914 {$ELSEIF DEFINED(GLB_LINUX)}
1915 Result := dlclose(aLibHandle) = 0;
1920 if Assigned(GL_LibHandle) then
1921 glbFreeLibrary(GL_LibHandle);
1923 if Assigned(GLU_LibHandle) then
1924 glbFreeLibrary(GLU_LibHandle);
1926 GL_LibHandle := glbLoadLibrary(libopengl);
1927 if not Assigned(GL_LibHandle) then
1928 raise EglBitmapException.Create('unable to load library: ' + libopengl);
1930 GLU_LibHandle := glbLoadLibrary(libglu);
1931 if not Assigned(GLU_LibHandle) then
1932 raise EglBitmapException.Create('unable to load library: ' + libglu);
1935 {$IF DEFINED(GLB_WIN)}
1936 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
1937 {$ELSEIF DEFINED(GLB_LINUX)}
1938 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
1939 glXGetProcAddressARB := dglGetProcAddress('glXGetProcAddressARB');
1942 glEnable := glbGetProcAddress('glEnable');
1943 glDisable := glbGetProcAddress('glDisable');
1944 glGetString := glbGetProcAddress('glGetString');
1945 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
1946 glTexParameteri := glbGetProcAddress('glTexParameteri');
1947 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
1948 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
1949 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
1950 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
1951 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
1952 glGenTextures := glbGetProcAddress('glGenTextures');
1953 glBindTexture := glbGetProcAddress('glBindTexture');
1954 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
1955 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
1956 glReadPixels := glbGetProcAddress('glReadPixels');
1957 glPixelStorei := glbGetProcAddress('glPixelStorei');
1958 glTexImage1D := glbGetProcAddress('glTexImage1D');
1959 glTexImage2D := glbGetProcAddress('glTexImage2D');
1960 glGetTexImage := glbGetProcAddress('glGetTexImage');
1962 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
1963 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
1965 glbFreeLibrary(GL_LibHandle);
1966 glbFreeLibrary(GLU_LibHandle);
1971 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1972 procedure glbReadOpenGLExtensions;
1978 MajorVersion, MinorVersion: Integer;
1980 ///////////////////////////////////////////////////////////////////////////////////////////
1981 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
1988 Separator := Pos(AnsiString('.'), aBuffer);
1989 if (Separator > 1) and (Separator < Length(aBuffer)) and
1990 (aBuffer[Separator - 1] in ['0'..'9']) and
1991 (aBuffer[Separator + 1] in ['0'..'9']) then begin
1994 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
1997 Delete(aBuffer, 1, Separator);
1998 Separator := Pos(AnsiString('.'), aBuffer) + 1;
2000 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
2003 Delete(aBuffer, Separator, 255);
2004 Separator := Pos(AnsiString('.'), aBuffer);
2006 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
2007 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2011 ///////////////////////////////////////////////////////////////////////////////////////////
2012 function CheckExtension(const Extension: AnsiString): Boolean;
2016 ExtPos := Pos(Extension, Buffer);
2017 result := ExtPos > 0;
2019 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2023 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2026 if not OpenGLInitialized then begin
2028 OpenGLInitialized := true;
2036 Context := wglGetCurrentContext;
2037 if (Context <> gLastContext) then begin
2038 gLastContext := Context;
2042 Buffer := glGetString(GL_VERSION);
2043 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2045 GL_VERSION_1_2 := false;
2046 GL_VERSION_1_3 := false;
2047 GL_VERSION_1_4 := false;
2048 GL_VERSION_2_0 := false;
2049 if MajorVersion = 1 then begin
2050 if MinorVersion >= 2 then
2051 GL_VERSION_1_2 := true;
2053 if MinorVersion >= 3 then
2054 GL_VERSION_1_3 := true;
2056 if MinorVersion >= 4 then
2057 GL_VERSION_1_4 := true;
2058 end else if MajorVersion >= 2 then begin
2059 GL_VERSION_1_2 := true;
2060 GL_VERSION_1_3 := true;
2061 GL_VERSION_1_4 := true;
2062 GL_VERSION_2_0 := true;
2066 Buffer := glGetString(GL_EXTENSIONS);
2067 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2068 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2069 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2070 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2071 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2072 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2073 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2074 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2075 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2076 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2078 if GL_VERSION_1_3 then begin
2079 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2080 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2081 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2083 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB');
2084 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB');
2085 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB');
2095 function CreateGrayPalette: HPALETTE;
2100 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
2102 Pal.palVersion := $300;
2103 Pal.palNumEntries := 256;
2106 {$DEFINE GLB_TEMPRANGECHECK}
2110 for Idx := 0 to 256 - 1 do begin
2111 Pal.palPalEntry[Idx].peRed := Idx;
2112 Pal.palPalEntry[Idx].peGreen := Idx;
2113 Pal.palPalEntry[Idx].peBlue := Idx;
2114 Pal.palPalEntry[Idx].peFlags := 0;
2117 {$IFDEF GLB_TEMPRANGECHECK}
2118 {$UNDEF GLB_TEMPRANGECHECK}
2122 result := CreatePalette(Pal^);
2129 (* TODO GLB_SDL_IMAGE
2130 {$IFDEF GLB_SDL_IMAGE}
2131 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2133 result := TStream(context^.unknown.data1).Seek(offset, whence);
2136 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2138 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2141 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2143 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2146 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2151 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2153 result := SDL_AllocRW;
2155 if result = nil then
2156 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2158 result^.seek := glBitmapRWseek;
2159 result^.read := glBitmapRWread;
2160 result^.write := glBitmapRWwrite;
2161 result^.close := glBitmapRWclose;
2162 result^.unknown.data1 := Stream;
2168 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
2170 glBitmap: TglBitmap2D;
2176 if Instance = 0 then
2177 Instance := HInstance;
2179 if (LoadFromRes) then
2180 glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName)
2183 glBitmap := TglBitmap2D.Create(FileName);
2186 glBitmap.DeleteTextureOnFree := false;
2187 glBitmap.FreeDataAfterGenTexture := false;
2188 glBitmap.GenTexture(true);
2189 if (glBitmap.ID > 0) then begin
2190 Texture := glBitmap.ID;
2198 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
2200 CM: TglBitmapCubeMap;
2205 if Instance = 0 then
2206 Instance := HInstance;
2209 CM := TglBitmapCubeMap.Create;
2211 CM.DeleteTextureOnFree := false;
2215 if (LoadFromRes) then
2216 CM.LoadFromResource(Instance, PositiveX)
2219 CM.LoadFromFile(PositiveX);
2220 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
2223 if (LoadFromRes) then
2224 CM.LoadFromResource(Instance, NegativeX)
2227 CM.LoadFromFile(NegativeX);
2228 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
2231 if (LoadFromRes) then
2232 CM.LoadFromResource(Instance, PositiveY)
2235 CM.LoadFromFile(PositiveY);
2236 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
2239 if (LoadFromRes) then
2240 CM.LoadFromResource(Instance, NegativeY)
2243 CM.LoadFromFile(NegativeY);
2244 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
2247 if (LoadFromRes) then
2248 CM.LoadFromResource(Instance, PositiveZ)
2251 CM.LoadFromFile(PositiveZ);
2252 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
2255 if (LoadFromRes) then
2256 CM.LoadFromResource(Instance, NegativeZ)
2259 CM.LoadFromFile(NegativeZ);
2260 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
2269 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
2271 NM: TglBitmapNormalMap;
2275 NM := TglBitmapNormalMap.Create;
2277 NM.DeleteTextureOnFree := false;
2278 NM.GenerateNormalMap(Size);
2288 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2289 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2291 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2294 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2295 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2297 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2300 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2301 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2303 glBitmapDefaultMipmap := aValue;
2306 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2307 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2309 glBitmapDefaultFormat := aFormat;
2312 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2313 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2315 glBitmapDefaultFilterMin := aMin;
2316 glBitmapDefaultFilterMag := aMag;
2319 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2320 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2322 glBitmapDefaultWrapS := S;
2323 glBitmapDefaultWrapT := T;
2324 glBitmapDefaultWrapR := R;
2327 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2328 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2330 result := glBitmapDefaultDeleteTextureOnFree;
2333 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2334 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2336 result := glBitmapDefaultFreeDataAfterGenTextures;
2339 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2340 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2342 result := glBitmapDefaultMipmap;
2345 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2346 function glBitmapGetDefaultFormat: TglBitmapFormat;
2348 result := glBitmapDefaultFormat;
2351 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2352 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
2354 aMin := glBitmapDefaultFilterMin;
2355 aMag := glBitmapDefaultFilterMag;
2358 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2359 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
2361 S := glBitmapDefaultWrapS;
2362 T := glBitmapDefaultWrapT;
2363 R := glBitmapDefaultWrapR;
2366 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2367 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2368 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2369 function TFormatDescriptor.GetRedMask: UInt64;
2371 result := fRange.r shl fShift.r;
2374 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2375 function TFormatDescriptor.GetGreenMask: UInt64;
2377 result := fRange.g shl fShift.g;
2380 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2381 function TFormatDescriptor.GetBlueMask: UInt64;
2383 result := fRange.b shl fShift.b;
2386 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2387 function TFormatDescriptor.GetAlphaMask: UInt64;
2389 result := fRange.a shl fShift.a;
2392 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2393 function TFormatDescriptor.GetComponents: Integer;
2399 if (fRange.arr[i] > 0) then
2403 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2404 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2408 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2409 w := Max(1, aSize.X);
2410 h := Max(1, aSize.Y);
2411 result := GetSize(w, h);
2416 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2417 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2420 if (aWidth <= 0) or (aHeight <= 0) then
2422 result := Ceil(aWidth * aHeight * fPixelSize);
2425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2426 function TFormatDescriptor.CreateMappingData: Pointer;
2431 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2432 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2437 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2438 function TFormatDescriptor.IsEmpty: Boolean;
2440 result := (fFormat = tfEmpty);
2443 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2444 function TFormatDescriptor.HasAlpha: Boolean;
2446 result := (fRange.a > 0);
2449 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2450 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean;
2454 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2455 raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
2457 if (aRedMask <> RedMask) then
2459 if (aGreenMask <> GreenMask) then
2461 if (aBlueMask <> BlueMask) then
2463 if (aAlphaMask <> AlphaMask) then
2468 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2469 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2471 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2472 aPixel.Data := fRange;
2473 aPixel.Range := fRange;
2474 aPixel.Format := fFormat;
2477 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2478 constructor TFormatDescriptor.Create;
2483 fWithAlpha := tfEmpty;
2484 fWithoutAlpha := tfEmpty;
2485 fRGBInverted := tfEmpty;
2486 fUncompressed := tfEmpty;
2488 fIsCompressed := false;
2491 fglInternalFormat := 0;
2494 FillChar(fRange, 0, SizeOf(fRange));
2495 FillChar(fShift, 0, SizeOf(fShift));
2498 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2499 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2500 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2501 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2503 aData^ := aPixel.Data.a;
2507 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2512 aPixel.Data.a := aData^;
2516 constructor TfdAlpha_UB1.Create;
2521 fglFormat := GL_ALPHA;
2522 fglDataFormat := GL_UNSIGNED_BYTE;
2525 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2526 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2527 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2528 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2530 aData^ := LuminanceWeight(aPixel);
2534 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2536 aPixel.Data.r := aData^;
2537 aPixel.Data.g := aData^;
2538 aPixel.Data.b := aData^;
2543 constructor TfdLuminance_UB1.Create;
2550 fglFormat := GL_LUMINANCE;
2551 fglDataFormat := GL_UNSIGNED_BYTE;
2554 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2555 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2556 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2557 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2563 if (fRange.arr[i] > 0) then
2564 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2568 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2573 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2577 constructor TfdUniversal_UB1.Create;
2583 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2584 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2585 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2586 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2588 inherited Map(aPixel, aData, aMapData);
2589 aData^ := aPixel.Data.a;
2593 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2595 inherited Unmap(aData, aPixel, aMapData);
2596 aPixel.Data.a := aData^;
2600 constructor TfdLuminanceAlpha_UB2.Create;
2606 fglFormat := GL_LUMINANCE_ALPHA;
2607 fglDataFormat := GL_UNSIGNED_BYTE;
2610 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2611 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2612 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2613 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2615 aData^ := aPixel.Data.r;
2617 aData^ := aPixel.Data.g;
2619 aData^ := aPixel.Data.b;
2623 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2625 aPixel.Data.r := aData^;
2627 aPixel.Data.g := aData^;
2629 aPixel.Data.b := aData^;
2634 constructor TfdRGB_UB3.Create;
2644 fglFormat := GL_RGB;
2645 fglDataFormat := GL_UNSIGNED_BYTE;
2648 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2649 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2650 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2651 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2653 aData^ := aPixel.Data.b;
2655 aData^ := aPixel.Data.g;
2657 aData^ := aPixel.Data.r;
2661 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2663 aPixel.Data.b := aData^;
2665 aPixel.Data.g := aData^;
2667 aPixel.Data.r := aData^;
2672 constructor TfdBGR_UB3.Create;
2681 fglFormat := GL_BGR;
2682 fglDataFormat := GL_UNSIGNED_BYTE;
2685 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2686 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2687 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2688 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2690 inherited Map(aPixel, aData, aMapData);
2691 aData^ := aPixel.Data.a;
2695 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2697 inherited Unmap(aData, aPixel, aMapData);
2698 aPixel.Data.a := aData^;
2702 constructor TfdRGBA_UB4.Create;
2708 fglFormat := GL_RGBA;
2709 fglDataFormat := GL_UNSIGNED_BYTE;
2712 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2713 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2714 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2715 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2717 inherited Map(aPixel, aData, aMapData);
2718 aData^ := aPixel.Data.a;
2722 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2724 inherited Unmap(aData, aPixel, aMapData);
2725 aPixel.Data.a := aData^;
2729 constructor TfdBGRA_UB4.Create;
2735 fglFormat := GL_BGRA;
2736 fglDataFormat := GL_UNSIGNED_BYTE;
2739 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2740 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2741 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2742 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2744 PWord(aData)^ := aPixel.Data.a;
2748 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2753 aPixel.Data.a := PWord(aData)^;
2757 constructor TfdAlpha_US1.Create;
2762 fglFormat := GL_ALPHA;
2763 fglDataFormat := GL_UNSIGNED_SHORT;
2766 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2767 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2768 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2769 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2771 PWord(aData)^ := LuminanceWeight(aPixel);
2775 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2777 aPixel.Data.r := PWord(aData)^;
2778 aPixel.Data.g := PWord(aData)^;
2779 aPixel.Data.b := PWord(aData)^;
2784 constructor TfdLuminance_US1.Create;
2791 fglFormat := GL_LUMINANCE;
2792 fglDataFormat := GL_UNSIGNED_SHORT;
2795 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2796 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2797 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2798 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2804 if (fRange.arr[i] > 0) then
2805 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2809 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2814 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2818 constructor TfdUniversal_US1.Create;
2824 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2825 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2826 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2827 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2829 PWord(aData)^ := DepthWeight(aPixel);
2833 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2835 aPixel.Data.r := PWord(aData)^;
2836 aPixel.Data.g := PWord(aData)^;
2837 aPixel.Data.b := PWord(aData)^;
2842 constructor TfdDepth_US1.Create;
2849 fglFormat := GL_DEPTH_COMPONENT;
2850 fglDataFormat := GL_UNSIGNED_SHORT;
2853 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2854 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2855 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2856 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2858 inherited Map(aPixel, aData, aMapData);
2859 PWord(aData)^ := aPixel.Data.a;
2863 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2865 inherited Unmap(aData, aPixel, aMapData);
2866 aPixel.Data.a := PWord(aData)^;
2870 constructor TfdLuminanceAlpha_US2.Create;
2876 fglFormat := GL_LUMINANCE_ALPHA;
2877 fglDataFormat := GL_UNSIGNED_SHORT;
2880 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2881 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2882 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2883 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2885 PWord(aData)^ := aPixel.Data.r;
2887 PWord(aData)^ := aPixel.Data.g;
2889 PWord(aData)^ := aPixel.Data.b;
2893 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2895 aPixel.Data.r := PWord(aData)^;
2897 aPixel.Data.g := PWord(aData)^;
2899 aPixel.Data.b := PWord(aData)^;
2904 constructor TfdRGB_US3.Create;
2914 fglFormat := GL_RGB;
2915 fglDataFormat := GL_UNSIGNED_SHORT;
2918 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2919 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2920 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2921 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2923 PWord(aData)^ := aPixel.Data.b;
2925 PWord(aData)^ := aPixel.Data.g;
2927 PWord(aData)^ := aPixel.Data.r;
2931 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2933 aPixel.Data.b := PWord(aData)^;
2935 aPixel.Data.g := PWord(aData)^;
2937 aPixel.Data.r := PWord(aData)^;
2942 constructor TfdBGR_US3.Create;
2952 fglFormat := GL_BGR;
2953 fglDataFormat := GL_UNSIGNED_SHORT;
2956 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2957 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2958 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2959 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2961 inherited Map(aPixel, aData, aMapData);
2962 PWord(aData)^ := aPixel.Data.a;
2966 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2968 inherited Unmap(aData, aPixel, aMapData);
2969 aPixel.Data.a := PWord(aData)^;
2973 constructor TfdRGBA_US4.Create;
2979 fglFormat := GL_RGBA;
2980 fglDataFormat := GL_UNSIGNED_SHORT;
2983 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2984 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2985 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2986 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2988 inherited Map(aPixel, aData, aMapData);
2989 PWord(aData)^ := aPixel.Data.a;
2993 procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2995 inherited Unmap(aData, aPixel, aMapData);
2996 aPixel.Data.a := PWord(aData)^;
3000 constructor TfdBGRA_US4.Create;
3006 fglFormat := GL_BGRA;
3007 fglDataFormat := GL_UNSIGNED_SHORT;
3010 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3011 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3012 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3013 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3017 PCardinal(aData)^ := 0;
3019 if (fRange.arr[i] > 0) then
3020 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
3024 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3029 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
3033 constructor TfdUniversal_UI1.Create;
3039 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3040 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3041 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3042 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3044 PCardinal(aData)^ := DepthWeight(aPixel);
3048 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3050 aPixel.Data.r := PCardinal(aData)^;
3051 aPixel.Data.g := PCardinal(aData)^;
3052 aPixel.Data.b := PCardinal(aData)^;
3057 constructor TfdDepth_UI1.Create;
3061 fRange.r := $FFFFFFFF;
3062 fRange.g := $FFFFFFFF;
3063 fRange.b := $FFFFFFFF;
3064 fglFormat := GL_DEPTH_COMPONENT;
3065 fglDataFormat := GL_UNSIGNED_INT;
3068 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3069 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3070 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3071 constructor TfdAlpha4.Create;
3074 fFormat := tfAlpha4;
3075 fWithAlpha := tfAlpha4;
3076 fglInternalFormat := GL_ALPHA4;
3079 constructor TfdAlpha8.Create;
3082 fFormat := tfAlpha8;
3083 fWithAlpha := tfAlpha8;
3084 fglInternalFormat := GL_ALPHA8;
3087 constructor TfdAlpha12.Create;
3090 fFormat := tfAlpha12;
3091 fWithAlpha := tfAlpha12;
3092 fglInternalFormat := GL_ALPHA12;
3095 constructor TfdAlpha16.Create;
3098 fFormat := tfAlpha16;
3099 fWithAlpha := tfAlpha16;
3100 fglInternalFormat := GL_ALPHA16;
3103 constructor TfdLuminance4.Create;
3106 fFormat := tfLuminance4;
3107 fWithAlpha := tfLuminance4Alpha4;
3108 fWithoutAlpha := tfLuminance4;
3109 fglInternalFormat := GL_LUMINANCE4;
3112 constructor TfdLuminance8.Create;
3115 fFormat := tfLuminance8;
3116 fWithAlpha := tfLuminance8Alpha8;
3117 fWithoutAlpha := tfLuminance8;
3118 fglInternalFormat := GL_LUMINANCE8;
3121 constructor TfdLuminance12.Create;
3124 fFormat := tfLuminance12;
3125 fWithAlpha := tfLuminance12Alpha12;
3126 fWithoutAlpha := tfLuminance12;
3127 fglInternalFormat := GL_LUMINANCE12;
3130 constructor TfdLuminance16.Create;
3133 fFormat := tfLuminance16;
3134 fWithAlpha := tfLuminance16Alpha16;
3135 fWithoutAlpha := tfLuminance16;
3136 fglInternalFormat := GL_LUMINANCE16;
3139 constructor TfdLuminance4Alpha4.Create;
3142 fFormat := tfLuminance4Alpha4;
3143 fWithAlpha := tfLuminance4Alpha4;
3144 fWithoutAlpha := tfLuminance4;
3145 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3148 constructor TfdLuminance6Alpha2.Create;
3151 fFormat := tfLuminance6Alpha2;
3152 fWithAlpha := tfLuminance6Alpha2;
3153 fWithoutAlpha := tfLuminance8;
3154 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3157 constructor TfdLuminance8Alpha8.Create;
3160 fFormat := tfLuminance8Alpha8;
3161 fWithAlpha := tfLuminance8Alpha8;
3162 fWithoutAlpha := tfLuminance8;
3163 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3166 constructor TfdLuminance12Alpha4.Create;
3169 fFormat := tfLuminance12Alpha4;
3170 fWithAlpha := tfLuminance12Alpha4;
3171 fWithoutAlpha := tfLuminance12;
3172 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3175 constructor TfdLuminance12Alpha12.Create;
3178 fFormat := tfLuminance12Alpha12;
3179 fWithAlpha := tfLuminance12Alpha12;
3180 fWithoutAlpha := tfLuminance12;
3181 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3184 constructor TfdLuminance16Alpha16.Create;
3187 fFormat := tfLuminance16Alpha16;
3188 fWithAlpha := tfLuminance16Alpha16;
3189 fWithoutAlpha := tfLuminance16;
3190 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3193 constructor TfdR3G3B2.Create;
3196 fFormat := tfR3G3B2;
3197 fWithAlpha := tfRGBA2;
3198 fWithoutAlpha := tfR3G3B2;
3205 fglFormat := GL_RGB;
3206 fglInternalFormat := GL_R3_G3_B2;
3207 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3210 constructor TfdRGB4.Create;
3214 fWithAlpha := tfRGBA4;
3215 fWithoutAlpha := tfRGB4;
3216 fRGBInverted := tfBGR4;
3223 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3224 fglInternalFormat := GL_RGB4;
3225 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3228 constructor TfdR5G6B5.Create;
3231 fFormat := tfR5G6B5;
3232 fWithAlpha := tfRGBA4;
3233 fWithoutAlpha := tfR5G6B5;
3234 fRGBInverted := tfB5G6R5;
3241 fglFormat := GL_RGB;
3242 fglInternalFormat := GL_RGB565;
3243 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3246 constructor TfdRGB5.Create;
3250 fWithAlpha := tfRGB5A1;
3251 fWithoutAlpha := tfRGB5;
3252 fRGBInverted := tfBGR5;
3259 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3260 fglInternalFormat := GL_RGB5;
3261 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3264 constructor TfdRGB8.Create;
3268 fWithAlpha := tfRGBA8;
3269 fWithoutAlpha := tfRGB8;
3270 fRGBInverted := tfBGR8;
3271 fglInternalFormat := GL_RGB8;
3274 constructor TfdRGB10.Create;
3278 fWithAlpha := tfRGB10A2;
3279 fWithoutAlpha := tfRGB10;
3280 fRGBInverted := tfBGR10;
3287 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3288 fglInternalFormat := GL_RGB10;
3289 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3292 constructor TfdRGB12.Create;
3296 fWithAlpha := tfRGBA12;
3297 fWithoutAlpha := tfRGB12;
3298 fRGBInverted := tfBGR12;
3299 fglInternalFormat := GL_RGB12;
3302 constructor TfdRGB16.Create;
3306 fWithAlpha := tfRGBA16;
3307 fWithoutAlpha := tfRGB16;
3308 fRGBInverted := tfBGR16;
3309 fglInternalFormat := GL_RGB16;
3312 constructor TfdRGBA2.Create;
3316 fWithAlpha := tfRGBA2;
3317 fWithoutAlpha := tfR3G3B2;
3318 fRGBInverted := tfBGRA2;
3319 fglInternalFormat := GL_RGBA2;
3322 constructor TfdRGBA4.Create;
3326 fWithAlpha := tfRGBA4;
3327 fWithoutAlpha := tfRGB4;
3328 fRGBInverted := tfBGRA4;
3337 fglFormat := GL_RGBA;
3338 fglInternalFormat := GL_RGBA4;
3339 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3342 constructor TfdRGB5A1.Create;
3345 fFormat := tfRGB5A1;
3346 fWithAlpha := tfRGB5A1;
3347 fWithoutAlpha := tfRGB5;
3348 fRGBInverted := tfBGR5A1;
3357 fglFormat := GL_RGBA;
3358 fglInternalFormat := GL_RGB5_A1;
3359 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3362 constructor TfdRGBA8.Create;
3366 fWithAlpha := tfRGBA8;
3367 fWithoutAlpha := tfRGB8;
3368 fRGBInverted := tfBGRA8;
3369 fglInternalFormat := GL_RGBA8;
3372 constructor TfdRGB10A2.Create;
3375 fFormat := tfRGB10A2;
3376 fWithAlpha := tfRGB10A2;
3377 fWithoutAlpha := tfRGB10;
3378 fRGBInverted := tfBGR10A2;
3387 fglFormat := GL_RGBA;
3388 fglInternalFormat := GL_RGB10_A2;
3389 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3392 constructor TfdRGBA12.Create;
3395 fFormat := tfRGBA12;
3396 fWithAlpha := tfRGBA12;
3397 fWithoutAlpha := tfRGB12;
3398 fRGBInverted := tfBGRA12;
3399 fglInternalFormat := GL_RGBA12;
3402 constructor TfdRGBA16.Create;
3405 fFormat := tfRGBA16;
3406 fWithAlpha := tfRGBA16;
3407 fWithoutAlpha := tfRGB16;
3408 fRGBInverted := tfBGRA16;
3409 fglInternalFormat := GL_RGBA16;
3412 constructor TfdBGR4.Create;
3417 fWithAlpha := tfBGRA4;
3418 fWithoutAlpha := tfBGR4;
3419 fRGBInverted := tfRGB4;
3428 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3429 fglInternalFormat := GL_RGB4;
3430 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3433 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3434 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3435 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3436 constructor TfdB5G6R5.Create;
3439 fFormat := tfB5G6R5;
3440 fWithAlpha := tfBGRA4;
3441 fWithoutAlpha := tfB5G6R5;
3442 fRGBInverted := tfR5G6B5;
3449 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3450 fglInternalFormat := GL_RGB8;
3451 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3454 constructor TfdBGR5.Create;
3459 fWithAlpha := tfBGR5A1;
3460 fWithoutAlpha := tfBGR5;
3461 fRGBInverted := tfRGB5;
3470 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3471 fglInternalFormat := GL_RGB5;
3472 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3475 constructor TfdBGR8.Create;
3479 fWithAlpha := tfBGRA8;
3480 fWithoutAlpha := tfBGR8;
3481 fRGBInverted := tfRGB8;
3482 fglInternalFormat := GL_RGB8;
3485 constructor TfdBGR10.Create;
3489 fWithAlpha := tfBGR10A2;
3490 fWithoutAlpha := tfBGR10;
3491 fRGBInverted := tfRGB10;
3500 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3501 fglInternalFormat := GL_RGB10;
3502 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3505 constructor TfdBGR12.Create;
3509 fWithAlpha := tfBGRA12;
3510 fWithoutAlpha := tfBGR12;
3511 fRGBInverted := tfRGB12;
3512 fglInternalFormat := GL_RGB12;
3515 constructor TfdBGR16.Create;
3519 fWithAlpha := tfBGRA16;
3520 fWithoutAlpha := tfBGR16;
3521 fRGBInverted := tfRGB16;
3522 fglInternalFormat := GL_RGB16;
3525 constructor TfdBGRA2.Create;
3529 fWithAlpha := tfBGRA4;
3530 fWithoutAlpha := tfBGR4;
3531 fRGBInverted := tfRGBA2;
3532 fglInternalFormat := GL_RGBA2;
3535 constructor TfdBGRA4.Create;
3539 fWithAlpha := tfBGRA4;
3540 fWithoutAlpha := tfBGR4;
3541 fRGBInverted := tfRGBA4;
3550 fglFormat := GL_BGRA;
3551 fglInternalFormat := GL_RGBA4;
3552 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3555 constructor TfdBGR5A1.Create;
3558 fFormat := tfBGR5A1;
3559 fWithAlpha := tfBGR5A1;
3560 fWithoutAlpha := tfBGR5;
3561 fRGBInverted := tfRGB5A1;
3570 fglFormat := GL_BGRA;
3571 fglInternalFormat := GL_RGB5_A1;
3572 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3575 constructor TfdBGRA8.Create;
3579 fWithAlpha := tfBGRA8;
3580 fWithoutAlpha := tfBGR8;
3581 fRGBInverted := tfRGBA8;
3582 fglInternalFormat := GL_RGBA8;
3585 constructor TfdBGR10A2.Create;
3588 fFormat := tfBGR10A2;
3589 fWithAlpha := tfBGR10A2;
3590 fWithoutAlpha := tfBGR10;
3591 fRGBInverted := tfRGB10A2;
3600 fglFormat := GL_BGRA;
3601 fglInternalFormat := GL_RGB10_A2;
3602 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3605 constructor TfdBGRA12.Create;
3608 fFormat := tfBGRA12;
3609 fWithAlpha := tfBGRA12;
3610 fWithoutAlpha := tfBGR12;
3611 fRGBInverted := tfRGBA12;
3612 fglInternalFormat := GL_RGBA12;
3615 constructor TfdBGRA16.Create;
3618 fFormat := tfBGRA16;
3619 fWithAlpha := tfBGRA16;
3620 fWithoutAlpha := tfBGR16;
3621 fRGBInverted := tfRGBA16;
3622 fglInternalFormat := GL_RGBA16;
3625 constructor TfdDepth16.Create;
3628 fFormat := tfDepth16;
3629 fWithAlpha := tfEmpty;
3630 fWithoutAlpha := tfDepth16;
3631 fglInternalFormat := GL_DEPTH_COMPONENT16;
3634 constructor TfdDepth24.Create;
3637 fFormat := tfDepth24;
3638 fWithAlpha := tfEmpty;
3639 fWithoutAlpha := tfDepth24;
3640 fglInternalFormat := GL_DEPTH_COMPONENT24;
3643 constructor TfdDepth32.Create;
3646 fFormat := tfDepth32;
3647 fWithAlpha := tfEmpty;
3648 fWithoutAlpha := tfDepth32;
3649 fglInternalFormat := GL_DEPTH_COMPONENT32;
3652 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3653 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3654 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3655 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3657 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3660 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3662 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3665 constructor TfdS3tcDtx1RGBA.Create;
3668 fFormat := tfS3tcDtx1RGBA;
3669 fWithAlpha := tfS3tcDtx1RGBA;
3670 fUncompressed := tfRGB5A1;
3672 fIsCompressed := true;
3673 fglFormat := GL_COMPRESSED_RGBA;
3674 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3675 fglDataFormat := GL_UNSIGNED_BYTE;
3678 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3679 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3680 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3681 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3683 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3686 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3688 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3691 constructor TfdS3tcDtx3RGBA.Create;
3694 fFormat := tfS3tcDtx3RGBA;
3695 fWithAlpha := tfS3tcDtx3RGBA;
3696 fUncompressed := tfRGBA8;
3698 fIsCompressed := true;
3699 fglFormat := GL_COMPRESSED_RGBA;
3700 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3701 fglDataFormat := GL_UNSIGNED_BYTE;
3704 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3705 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3706 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3707 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3709 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3712 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3714 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3717 constructor TfdS3tcDtx5RGBA.Create;
3720 fFormat := tfS3tcDtx3RGBA;
3721 fWithAlpha := tfS3tcDtx3RGBA;
3722 fUncompressed := tfRGBA8;
3724 fIsCompressed := true;
3725 fglFormat := GL_COMPRESSED_RGBA;
3726 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3727 fglDataFormat := GL_UNSIGNED_BYTE;
3730 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3731 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3732 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3733 class procedure TFormatDescriptor.Init;
3735 if not Assigned(FormatDescriptorCS) then
3736 FormatDescriptorCS := TCriticalSection.Create;
3739 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3740 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3742 FormatDescriptorCS.Enter;
3744 result := FormatDescriptors[aFormat];
3745 if not Assigned(result) then begin
3746 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3747 FormatDescriptors[aFormat] := result;
3750 FormatDescriptorCS.Leave;
3754 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3755 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3757 result := Get(Get(aFormat).WithAlpha);
3760 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3761 class procedure TFormatDescriptor.Clear;
3765 FormatDescriptorCS.Enter;
3767 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3768 FreeAndNil(FormatDescriptors[f]);
3770 FormatDescriptorCS.Leave;
3774 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3775 class procedure TFormatDescriptor.Finalize;
3778 FreeAndNil(FormatDescriptorCS);
3781 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3782 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3783 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3784 procedure TbmpBitfieldFormat.SetRedMask(const aValue: UInt64);
3786 Update(aValue, fRange.r, fShift.r);
3789 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3790 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: UInt64);
3792 Update(aValue, fRange.g, fShift.g);
3795 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3796 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: UInt64);
3798 Update(aValue, fRange.b, fShift.b);
3801 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3802 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: UInt64);
3804 Update(aValue, fRange.a, fShift.a);
3807 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3808 procedure TbmpBitfieldFormat.Update(aMask: UInt64; out aRange: Cardinal; out
3815 while (aMask > 0) and ((aMask and 1) = 0) do begin
3817 aMask := aMask shr 1;
3820 while (aMask > 0) do begin
3821 aRange := aRange shl 1;
3822 aMask := aMask shr 1;
3826 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3829 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3830 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3838 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3839 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3840 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3841 ((aPixel.Data.a and fRange.a) shl fShift.a);
3842 s := Round(fPixelSize);
3845 2: PWord(aData)^ := data;
3846 4: PCardinal(aData)^ := data;
3847 8: PUInt64(aData)^ := data;
3849 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3854 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3855 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3862 s := Round(fPixelSize);
3865 2: data := PWord(aData)^;
3866 4: data := PCardinal(aData)^;
3867 8: data := PUInt64(aData)^;
3869 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3872 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3876 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3877 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3878 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3879 procedure TbmpColorTableFormat.CreateColorTable;
3883 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3884 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3886 if (Format = tfLuminance4) then
3887 SetLength(fColorTable, 16)
3889 SetLength(fColorTable, 256);
3893 for i := 0 to High(fColorTable) do begin
3894 fColorTable[i].r := 16 * i;
3895 fColorTable[i].g := 16 * i;
3896 fColorTable[i].b := 16 * i;
3897 fColorTable[i].a := 0;
3902 for i := 0 to High(fColorTable) do begin
3903 fColorTable[i].r := i;
3904 fColorTable[i].g := i;
3905 fColorTable[i].b := i;
3906 fColorTable[i].a := 0;
3911 for i := 0 to High(fColorTable) do begin
3912 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3913 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3914 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3915 fColorTable[i].a := 0;
3921 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3922 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3926 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3927 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3931 if (aMapData = nil) then
3933 d := LuminanceWeight(aPixel) and Range.r;
3934 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3936 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3943 aData^ := LuminanceWeight(aPixel) and Range.r;
3949 ((aPixel.Data.r and Range.r) shl Shift.r) or
3950 ((aPixel.Data.g and Range.g) shl Shift.g) or
3951 ((aPixel.Data.b and Range.b) shl Shift.b));
3957 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3958 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3967 s := Trunc(fPixelSize);
3968 f := fPixelSize - s;
3969 bits := Round(8 * f);
3971 0: idx := (aData^ shr (8 - bits - {%H-}PtrUInt(aMapData))) and ((1 shl bits) - 1);
3973 2: idx := PWord(aData)^;
3974 4: idx := PCardinal(aData)^;
3975 8: idx := PUInt64(aData)^;
3977 raise EglBitmapException.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3979 if (idx >= Length(fColorTable)) then
3980 raise EglBitmapException.CreateFmt('invalid color index: %d', [idx]);
3981 with fColorTable[idx] do begin
3987 inc(aMapData, bits);
3988 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3995 destructor TbmpColorTableFormat.Destroy;
3997 SetLength(fColorTable, 0);
4001 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4002 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4003 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4004 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
4008 for i := 0 to 3 do begin
4009 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
4010 if (aSourceFD.Range.arr[i] > 0) then
4011 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
4013 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
4018 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4019 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
4021 with aFuncRec do begin
4022 if (Source.Range.r > 0) then
4023 Dest.Data.r := Source.Data.r;
4024 if (Source.Range.g > 0) then
4025 Dest.Data.g := Source.Data.g;
4026 if (Source.Range.b > 0) then
4027 Dest.Data.b := Source.Data.b;
4028 if (Source.Range.a > 0) then
4029 Dest.Data.a := Source.Data.a;
4033 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4034 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4038 with aFuncRec do begin
4040 if (Source.Range.arr[i] > 0) then
4041 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4046 TShiftData = packed record
4048 0: (r, g, b, a: SmallInt);
4049 1: (arr: array[0..3] of SmallInt);
4051 PShiftData = ^TShiftData;
4053 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4054 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4060 if (Source.Range.arr[i] > 0) then
4061 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4064 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4065 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4067 with aFuncRec do begin
4068 Dest.Data := Source.Data;
4069 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4070 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4071 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4072 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4074 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4075 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4080 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4081 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4085 with aFuncRec do begin
4087 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4091 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4092 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4096 with FuncRec do begin
4097 if (FuncRec.Args = nil) then begin //source has no alpha
4099 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4100 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4101 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4102 Dest.Data.a := Round(Dest.Range.a * Temp);
4104 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4108 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4109 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4111 PglBitmapPixelData = ^TglBitmapPixelData;
4113 with FuncRec do begin
4114 Dest.Data.r := Source.Data.r;
4115 Dest.Data.g := Source.Data.g;
4116 Dest.Data.b := Source.Data.b;
4118 with PglBitmapPixelData(Args)^ do
4119 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4120 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4121 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4124 Dest.Data.a := Dest.Range.a;
4128 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4129 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4131 with FuncRec do begin
4132 Dest.Data.r := Source.Data.r;
4133 Dest.Data.g := Source.Data.g;
4134 Dest.Data.b := Source.Data.b;
4135 Dest.Data.a := PCardinal(Args)^;
4139 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4140 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4143 TRGBPix = array [0..2] of byte;
4147 while aWidth > 0 do begin
4148 Temp := PRGBPix(aData)^[0];
4149 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4150 PRGBPix(aData)^[2] := Temp;
4160 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4161 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4162 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4163 function TglBitmap.GetWidth: Integer;
4165 if (ffX in fDimension.Fields) then
4166 result := fDimension.X
4171 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4172 function TglBitmap.GetHeight: Integer;
4174 if (ffY in fDimension.Fields) then
4175 result := fDimension.Y
4180 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4181 function TglBitmap.GetFileWidth: Integer;
4183 result := Max(1, Width);
4186 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4187 function TglBitmap.GetFileHeight: Integer;
4189 result := Max(1, Height);
4192 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4193 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4195 if fCustomData = aValue then
4197 fCustomData := aValue;
4200 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4201 procedure TglBitmap.SetCustomName(const aValue: String);
4203 if fCustomName = aValue then
4205 fCustomName := aValue;
4208 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4209 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4211 if fCustomNameW = aValue then
4213 fCustomNameW := aValue;
4216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4217 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4219 if fDeleteTextureOnFree = aValue then
4221 fDeleteTextureOnFree := aValue;
4224 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4225 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4227 if fFormat = aValue then
4229 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4230 raise EglBitmapUnsupportedFormatFormat.Create('SetInternalFormat - ' + UNSUPPORTED_FORMAT);
4231 SetDataPointer(Data, aValue, Width, Height);
4234 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4235 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4237 if fFreeDataAfterGenTexture = aValue then
4239 fFreeDataAfterGenTexture := aValue;
4242 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4243 procedure TglBitmap.SetID(const aValue: Cardinal);
4245 if fID = aValue then
4250 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4251 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4253 if fMipMap = aValue then
4258 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4259 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4261 if fTarget = aValue then
4266 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4267 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4269 MaxAnisotropic: Integer;
4271 fAnisotropic := aValue;
4272 if (ID > 0) then begin
4273 if GL_EXT_texture_filter_anisotropic then begin
4274 if fAnisotropic > 0 then begin
4276 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4277 if aValue > MaxAnisotropic then
4278 fAnisotropic := MaxAnisotropic;
4279 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4287 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4288 procedure TglBitmap.CreateID;
4291 glDeleteTextures(1, @fID);
4292 glGenTextures(1, @fID);
4296 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4297 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4299 // Set Up Parameters
4300 SetWrap(fWrapS, fWrapT, fWrapR);
4301 SetFilter(fFilterMin, fFilterMag);
4302 SetAnisotropic(fAnisotropic);
4303 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4305 // Mip Maps Generation Mode
4306 aBuildWithGlu := false;
4307 if (MipMap = mmMipmap) then begin
4308 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4309 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4311 aBuildWithGlu := true;
4312 end else if (MipMap = mmMipmapGlu) then
4313 aBuildWithGlu := true;
4316 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4317 procedure TglBitmap.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
4318 const aWidth: Integer; const aHeight: Integer);
4322 if (Data <> aData) then begin
4323 if (Assigned(Data)) then
4328 FillChar(fDimension, SizeOf(fDimension), 0);
4329 if not Assigned(fData) then begin
4334 if aWidth <> -1 then begin
4335 fDimension.Fields := fDimension.Fields + [ffX];
4336 fDimension.X := aWidth;
4339 if aHeight <> -1 then begin
4340 fDimension.Fields := fDimension.Fields + [ffY];
4341 fDimension.Y := aHeight;
4344 s := TFormatDescriptor.Get(aFormat).PixelSize;
4346 fPixelSize := Ceil(s);
4347 fRowSize := Ceil(s * aWidth);
4351 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4352 function TglBitmap.FlipHorz: Boolean;
4357 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4358 function TglBitmap.FlipVert: Boolean;
4363 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4364 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4365 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4366 procedure TglBitmap.AfterConstruction;
4368 inherited AfterConstruction;
4372 fIsResident := false;
4374 fFormat := glBitmapGetDefaultFormat;
4375 fMipMap := glBitmapDefaultMipmap;
4376 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4377 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4379 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4380 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4383 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4384 procedure TglBitmap.BeforeDestruction;
4386 SetDataPointer(nil, tfEmpty);
4387 if (fID > 0) and fDeleteTextureOnFree then
4388 glDeleteTextures(1, @fID);
4389 inherited BeforeDestruction;
4392 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4393 procedure TglBitmap.LoadFromFile(const aFilename: String);
4397 if not FileExists(aFilename) then
4398 raise EglBitmapException.Create('file does not exist: ' + aFilename);
4399 fFilename := aFilename;
4400 fs := TFileStream.Create(fFilename, fmOpenRead);
4409 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4410 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4412 {$IFDEF GLB_SUPPORT_PNG_READ}
4413 if not LoadPNG(aStream) then
4415 {$IFDEF GLB_SUPPORT_JPEG_READ}
4416 if not LoadJPEG(aStream) then
4418 if not LoadDDS(aStream) then
4419 if not LoadTGA(aStream) then
4420 if not LoadBMP(aStream) then
4421 raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4424 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4425 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4426 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4431 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4432 GetMem(tmpData, size);
4434 FillChar(tmpData^, size, #$FF);
4435 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y);
4440 AddFunc(Self, aFunc, false, Format, aArgs);
4444 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4445 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
4447 rs: TResourceStream;
4452 if not Assigned(ResType) then begin
4453 TempPos := Pos('.', Resource);
4454 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
4455 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
4456 TempResType := PChar(ResTypeStr);
4458 TempResType := ResType
4460 rs := TResourceStream.Create(Instance, Resource, TempResType);
4468 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4469 procedure TglBitmap.LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4471 rs: TResourceStream;
4473 rs := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
4482 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4483 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4487 fs := TFileStream.Create(aFileName, fmCreate);
4490 SaveToStream(fs, aFileType);
4496 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4497 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4500 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4501 ftPNG: SavePng(aStream);
4503 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4504 ftJPEG: SaveJPEG(aStream);
4506 ftDDS: SaveDDS(aStream);
4507 ftTGA: SaveTGA(aStream);
4508 ftBMP: SaveBMP(aStream);
4512 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4513 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4515 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4518 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4519 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4520 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4522 DestData, TmpData, SourceData: pByte;
4523 TempHeight, TempWidth: Integer;
4524 SourceFD, DestFD: TFormatDescriptor;
4525 SourceMD, DestMD: Pointer;
4527 FuncRec: TglBitmapFunctionRec;
4529 Assert(Assigned(Data));
4530 Assert(Assigned(aSource));
4531 Assert(Assigned(aSource.Data));
4534 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4535 SourceFD := TFormatDescriptor.Get(aSource.Format);
4536 DestFD := TFormatDescriptor.Get(aFormat);
4538 // inkompatible Formats so CreateTemp
4539 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4540 aCreateTemp := true;
4543 TempHeight := Max(1, aSource.Height);
4544 TempWidth := Max(1, aSource.Width);
4546 FuncRec.Sender := Self;
4547 FuncRec.Args := aArgs;
4550 if aCreateTemp then begin
4551 GetMem(TmpData, TFormatDescriptor.Get(aFormat).GetSize(TempWidth, TempHeight));
4552 DestData := TmpData;
4557 SourceFD.PreparePixel(FuncRec.Source);
4558 DestFD.PreparePixel (FuncRec.Dest);
4560 SourceMD := SourceFD.CreateMappingData;
4561 DestMD := DestFD.CreateMappingData;
4563 FuncRec.Size := aSource.Dimension;
4564 FuncRec.Position.Fields := FuncRec.Size.Fields;
4567 SourceData := aSource.Data;
4568 FuncRec.Position.Y := 0;
4569 while FuncRec.Position.Y < TempHeight do begin
4570 FuncRec.Position.X := 0;
4571 while FuncRec.Position.X < TempWidth do begin
4572 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4574 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4575 inc(FuncRec.Position.X);
4577 inc(FuncRec.Position.Y);
4580 // Updating Image or InternalFormat
4582 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height)
4583 else if (aFormat <> fFormat) then
4588 SourceFD.FreeMappingData(SourceMD);
4589 DestFD.FreeMappingData(DestMD);
4600 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4601 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4603 Row, RowSize: Integer;
4604 SourceData, TmpData: PByte;
4606 Pix: TglBitmapPixelData;
4607 FormatDesc: TglBitmapFormatDescriptor;
4609 function GetRowPointer(Row: Integer): pByte;
4611 result := Surface.pixels;
4612 Inc(result, Row * RowSize);
4619 if not FormatIsUncompressed(InternalFormat) then
4620 raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
4623 FormatDesc := FORMAT_DESCRIPTORS[Format];
4624 if Assigned(Data) then begin
4625 case Trunc(FormatDesc.GetSize) of
4631 raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
4633 FormatDesc.PreparePixel(Pix);
4634 with Pix.PixelDesc do
4635 Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4636 RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift);
4639 RowSize := Ceil(FileWidth * FormatDesc.GetSize);
4641 for Row := 0 to FileHeight -1 do begin
4642 TmpData := GetRowPointer(Row);
4643 if Assigned(TmpData) then begin
4644 Move(SourceData^, TmpData^, RowSize);
4645 inc(SourceData, RowSize);
4652 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4653 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4655 pSource, pData, pTempData: PByte;
4656 Row, RowSize, TempWidth, TempHeight: Integer;
4657 IntFormat, f: TglBitmapInternalFormat;
4658 FormatDesc: TglBitmapFormatDescriptor;
4660 function GetRowPointer(Row: Integer): pByte;
4662 result := Surface^.pixels;
4663 Inc(result, Row * RowSize);
4668 if (Assigned(Surface)) then begin
4669 with Surface^.format^ do begin
4670 IntFormat := tfEmpty;
4671 for f := Low(f) to High(f) do begin
4672 if FORMAT_DESCRIPTORS[f].MaskMatch(RMask, GMask, BMask, AMask) then begin
4677 if (IntFormat = tfEmpty) then
4678 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4681 FormatDesc := FORMAT_DESCRIPTORS[IntFormat];
4682 TempWidth := Surface^.w;
4683 TempHeight := Surface^.h;
4684 RowSize := Trunc(TempWidth * FormatDesc.GetSize);
4685 GetMem(pData, TempHeight * RowSize);
4688 for Row := 0 to TempHeight -1 do begin
4689 pSource := GetRowPointer(Row);
4690 if (Assigned(pSource)) then begin
4691 Move(pSource^, pTempData^, RowSize);
4692 Inc(pTempData, RowSize);
4695 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
4704 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4705 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4707 Row, Col, AlphaInterleave: Integer;
4708 pSource, pDest: PByte;
4710 function GetRowPointer(Row: Integer): pByte;
4712 result := aSurface.pixels;
4713 Inc(result, Row * Width);
4718 if Assigned(Data) then begin
4719 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4720 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4722 AlphaInterleave := 0;
4725 AlphaInterleave := 1;
4727 AlphaInterleave := 3;
4731 for Row := 0 to Height -1 do begin
4732 pDest := GetRowPointer(Row);
4733 if Assigned(pDest) then begin
4734 for Col := 0 to Width -1 do begin
4735 Inc(pSource, AlphaInterleave);
4747 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4748 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4752 bmp := TglBitmap2D.Create;
4754 bmp.AssignFromSurface(Surface);
4755 result := AddAlphaFromGlBitmap(bmp, Func, CustomData);
4763 //TODO rework & test
4764 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4765 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4768 pSource, pData: PByte;
4771 if Assigned(Data) then begin
4772 if Assigned(aBitmap) then begin
4773 aBitmap.Width := Width;
4774 aBitmap.Height := Height;
4777 tfAlpha8, ifLuminance, ifDepth8:
4779 Bitmap.PixelFormat := pf8bit;
4780 Bitmap.Palette := CreateGrayPalette;
4783 Bitmap.PixelFormat := pf15bit;
4785 Bitmap.PixelFormat := pf16bit;
4787 Bitmap.PixelFormat := pf24bit;
4789 Bitmap.PixelFormat := pf32bit;
4791 raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
4795 for Row := 0 to FileHeight -1 do begin
4796 pData := Bitmap.Scanline[Row];
4798 Move(pSource^, pData^, fRowSize);
4799 Inc(pSource, fRowSize);
4801 // swap RGB(A) to BGR(A)
4802 if InternalFormat in [ifRGB8, ifRGBA8] then
4803 SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8);
4811 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4812 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4814 pSource, pData, pTempData: PByte;
4815 Row, RowSize, TempWidth, TempHeight: Integer;
4816 IntFormat: TglBitmapInternalFormat;
4820 if (Assigned(Bitmap)) then begin
4821 case Bitmap.PixelFormat of
4823 IntFormat := ifLuminance;
4825 IntFormat := ifRGB5A1;
4827 IntFormat := ifR5G6B5;
4829 IntFormat := ifBGR8;
4831 IntFormat := ifBGRA8;
4833 raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
4836 TempWidth := Bitmap.Width;
4837 TempHeight := Bitmap.Height;
4839 RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
4841 GetMem(pData, TempHeight * RowSize);
4845 for Row := 0 to TempHeight -1 do begin
4846 pSource := Bitmap.Scanline[Row];
4848 if (Assigned(pSource)) then begin
4849 Move(pSource^, pTempData^, RowSize);
4850 Inc(pTempData, RowSize);
4854 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
4864 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4865 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4867 Row, Col, AlphaInterleave: Integer;
4868 pSource, pDest: PByte;
4872 if Assigned(Data) then begin
4873 if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin
4874 if Assigned(Bitmap) then begin
4875 Bitmap.PixelFormat := pf8bit;
4876 Bitmap.Palette := CreateGrayPalette;
4877 Bitmap.Width := Width;
4878 Bitmap.Height := Height;
4880 case InternalFormat of
4882 AlphaInterleave := 1;
4884 AlphaInterleave := 3;
4886 AlphaInterleave := 0;
4892 for Row := 0 to Height -1 do begin
4893 pDest := Bitmap.Scanline[Row];
4895 if Assigned(pDest) then begin
4896 for Col := 0 to Width -1 do begin
4897 Inc(pSource, AlphaInterleave);
4911 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4912 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4916 tex := TglBitmap2D.Create;
4918 tex.AssignFromBitmap(Bitmap);
4919 result := AddAlphaFromglBitmap(tex, Func, CustomData);
4925 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4926 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar;
4927 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4929 RS: TResourceStream;
4934 if Assigned(ResType) then
4935 TempResType := ResType
4938 TempPos := Pos('.', Resource);
4939 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
4940 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
4941 TempResType := PChar(ResTypeStr);
4944 RS := TResourceStream.Create(Instance, Resource, TempResType);
4946 result := AddAlphaFromStream(RS, Func, CustomData);
4952 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4953 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
4954 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4956 RS: TResourceStream;
4958 RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
4960 result := AddAlphaFromStream(RS, Func, CustomData);
4967 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4968 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4971 if not FormatIsUncompressed(InternalFormat) then
4972 raise EglBitmapUnsupportedFormatFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_FORMAT);
4974 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
4977 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4978 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4982 FS := TFileStream.Create(FileName, fmOpenRead);
4984 result := AddAlphaFromStream(FS, aFunc, aArgs);
4990 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4991 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4995 tex := TglBitmap2D.Create(aStream);
4997 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
5003 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5004 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
5006 DestData, DestData2, SourceData: pByte;
5007 TempHeight, TempWidth: Integer;
5008 SourceFD, DestFD: TFormatDescriptor;
5009 SourceMD, DestMD, DestMD2: Pointer;
5011 FuncRec: TglBitmapFunctionRec;
5015 Assert(Assigned(Data));
5016 Assert(Assigned(aBitmap));
5017 Assert(Assigned(aBitmap.Data));
5019 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
5020 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
5022 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
5023 DestFD := TFormatDescriptor.Get(Format);
5025 if not Assigned(aFunc) then begin
5026 aFunc := glBitmapAlphaFunc;
5027 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5029 FuncRec.Args := aArgs;
5032 TempHeight := aBitmap.FileHeight;
5033 TempWidth := aBitmap.FileWidth;
5035 FuncRec.Sender := Self;
5036 FuncRec.Size := Dimension;
5037 FuncRec.Position.Fields := FuncRec.Size.Fields;
5041 SourceData := aBitmap.Data;
5044 SourceFD.PreparePixel(FuncRec.Source);
5045 DestFD.PreparePixel (FuncRec.Dest);
5047 SourceMD := SourceFD.CreateMappingData;
5048 DestMD := DestFD.CreateMappingData;
5049 DestMD2 := DestFD.CreateMappingData;
5051 FuncRec.Position.Y := 0;
5052 while FuncRec.Position.Y < TempHeight do begin
5053 FuncRec.Position.X := 0;
5054 while FuncRec.Position.X < TempWidth do begin
5055 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5056 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5058 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5059 inc(FuncRec.Position.X);
5061 inc(FuncRec.Position.Y);
5064 SourceFD.FreeMappingData(SourceMD);
5065 DestFD.FreeMappingData(DestMD);
5066 DestFD.FreeMappingData(DestMD2);
5071 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5072 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5074 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5077 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5078 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5080 PixelData: TglBitmapPixelData;
5082 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5083 result := AddAlphaFromColorKeyFloat(
5084 aRed / PixelData.Range.r,
5085 aGreen / PixelData.Range.g,
5086 aBlue / PixelData.Range.b,
5087 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5090 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5091 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5093 values: array[0..2] of Single;
5096 PixelData: TglBitmapPixelData;
5098 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5099 with PixelData do begin
5101 values[1] := aGreen;
5104 for i := 0 to 2 do begin
5105 tmp := Trunc(Range.arr[i] * aDeviation);
5106 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5107 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5112 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5116 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5118 result := AddAlphaFromValueFloat(aAlpha / $FF);
5121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5122 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5124 PixelData: TglBitmapPixelData;
5126 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5127 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5130 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5131 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5133 PixelData: TglBitmapPixelData;
5135 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5137 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5138 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5142 function TglBitmap.RemoveAlpha: Boolean;
5144 FormatDesc: TFormatDescriptor;
5147 FormatDesc := TFormatDescriptor.Get(Format);
5148 if Assigned(Data) then begin
5149 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5150 raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_FORMAT);
5151 result := ConvertTo(FormatDesc.WithoutAlpha);
5155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5156 function TglBitmap.Clone: TglBitmap;
5163 Temp := (ClassType.Create as TglBitmap);
5165 // copy texture data if assigned
5166 if Assigned(Data) then begin
5167 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5168 GetMem(TempPtr, Size);
5170 Move(Data^, TempPtr^, Size);
5171 Temp.SetDataPointer(TempPtr, Format, Width, Height);
5177 Temp.SetDataPointer(nil, Format, Width, Height);
5181 Temp.fTarget := Target;
5182 Temp.fFormat := Format;
5183 Temp.fMipMap := MipMap;
5184 Temp.fAnisotropic := Anisotropic;
5185 Temp.fBorderColor := fBorderColor;
5186 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5187 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5188 Temp.fFilterMin := fFilterMin;
5189 Temp.fFilterMag := fFilterMag;
5190 Temp.fWrapS := fWrapS;
5191 Temp.fWrapT := fWrapT;
5192 Temp.fWrapR := fWrapR;
5193 Temp.fFilename := fFilename;
5194 Temp.fCustomName := fCustomName;
5195 Temp.fCustomNameW := fCustomNameW;
5196 Temp.fCustomData := fCustomData;
5205 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5206 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5208 SourceFD, DestFD: TFormatDescriptor;
5209 SourcePD, DestPD: TglBitmapPixelData;
5210 ShiftData: TShiftData;
5212 function CanCopyDirect: Boolean;
5215 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5216 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5217 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5218 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5221 function CanShift: Boolean;
5224 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5225 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5226 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5227 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5230 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5233 while (aSource > aDest) and (aSource > 0) do begin
5235 aSource := aSource shr 1;
5240 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5241 SourceFD := TFormatDescriptor.Get(Format);
5242 DestFD := TFormatDescriptor.Get(aFormat);
5244 SourceFD.PreparePixel(SourcePD);
5245 DestFD.PreparePixel (DestPD);
5247 if CanCopyDirect then
5248 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5249 else if CanShift then begin
5250 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5251 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5252 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5253 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5254 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5256 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5261 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5262 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5264 if aUseRGB or aUseAlpha then
5265 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5266 ((PtrInt(aUseAlpha) and 1) shl 1) or
5267 (PtrInt(aUseRGB) and 1) ));
5270 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5271 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5273 fBorderColor[0] := aRed;
5274 fBorderColor[1] := aGreen;
5275 fBorderColor[2] := aBlue;
5276 fBorderColor[3] := aAlpha;
5277 if (ID > 0) then begin
5279 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5284 procedure TglBitmap.FreeData;
5286 SetDataPointer(nil, tfEmpty);
5289 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5290 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5291 const aAlpha: Byte);
5293 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5296 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5297 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5299 PixelData: TglBitmapPixelData;
5301 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5303 aRed / PixelData.Range.r,
5304 aGreen / PixelData.Range.g,
5305 aBlue / PixelData.Range.b,
5306 aAlpha / PixelData.Range.a);
5309 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5310 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5312 PixelData: TglBitmapPixelData;
5314 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5315 with PixelData do begin
5316 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5317 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5318 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5319 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5321 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5324 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5325 procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal);
5330 fFilterMin := GL_NEAREST;
5332 fFilterMin := GL_LINEAR;
5333 GL_NEAREST_MIPMAP_NEAREST:
5334 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5335 GL_LINEAR_MIPMAP_NEAREST:
5336 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5337 GL_NEAREST_MIPMAP_LINEAR:
5338 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5339 GL_LINEAR_MIPMAP_LINEAR:
5340 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5342 raise EglBitmapException.Create('SetFilter - Unknow MIN filter.');
5348 fFilterMag := GL_NEAREST;
5350 fFilterMag := GL_LINEAR;
5352 raise EglBitmapException.Create('SetFilter - Unknow MAG filter.');
5356 if (ID > 0) then begin
5358 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5360 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5362 GL_NEAREST, GL_LINEAR:
5363 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5364 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5365 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5366 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5367 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5370 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5374 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5375 procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; const R: Cardinal);
5377 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5381 aTarget := GL_CLAMP;
5384 aTarget := GL_REPEAT;
5386 GL_CLAMP_TO_EDGE: begin
5387 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5388 aTarget := GL_CLAMP_TO_EDGE
5390 aTarget := GL_CLAMP;
5393 GL_CLAMP_TO_BORDER: begin
5394 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5395 aTarget := GL_CLAMP_TO_BORDER
5397 aTarget := GL_CLAMP;
5400 GL_MIRRORED_REPEAT: begin
5401 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5402 aTarget := GL_MIRRORED_REPEAT
5404 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5407 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).');
5412 CheckAndSetWrap(S, fWrapS);
5413 CheckAndSetWrap(T, fWrapT);
5414 CheckAndSetWrap(R, fWrapR);
5416 if (ID > 0) then begin
5418 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5419 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5420 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5424 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5425 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5427 if aEnableTextureUnit then
5430 glBindTexture(Target, ID);
5433 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5434 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5436 if aDisableTextureUnit then
5438 glBindTexture(Target, 0);
5441 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5442 constructor TglBitmap.Create;
5444 {$IFDEF GLB_NATIVE_OGL}
5445 glbReadOpenGLExtensions;
5447 if (ClassType = TglBitmap) then
5448 raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5452 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5453 constructor TglBitmap.Create(const aFileName: String);
5456 LoadFromFile(FileName);
5459 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5460 constructor TglBitmap.Create(const aStream: TStream);
5463 LoadFromStream(aStream);
5466 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5467 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
5473 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5474 GetMem(Image, ImageSize);
5476 FillChar(Image^, ImageSize, #$FF);
5477 SetDataPointer(Image, aFormat, aSize.X, aSize.Y);
5484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5485 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
5486 const aFunc: TglBitmapFunction; const aArgs: Pointer);
5489 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5493 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5494 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5497 LoadFromResource(aInstance, aResource, aResType);
5500 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5501 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5504 LoadFromResourceID(aInstance, aResourceID, aResType);
5508 {$IFDEF GLB_SUPPORT_PNG_READ}
5509 {$IF DEFINED(GLB_SDL_IMAGE)}
5510 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5511 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5512 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5513 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5515 Surface: PSDL_Surface;
5519 RWops := glBitmapCreateRWops(aStream);
5521 if IMG_isPNG(RWops) > 0 then begin
5522 Surface := IMG_LoadPNG_RW(RWops);
5524 AssignFromSurface(Surface);
5527 SDL_FreeSurface(Surface);
5535 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5536 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5537 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5539 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5542 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5543 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5546 signature: array [0..7] of byte;
5548 png_info: png_infop;
5550 TempHeight, TempWidth: Integer;
5551 Format: TglBitmapInternalFormat;
5554 png_rows: array of pByte;
5555 Row, LineSize: Integer;
5559 if not init_libPNG then
5560 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5564 StreamPos := Stream.Position;
5565 Stream.Read(signature, 8);
5566 Stream.Position := StreamPos;
5568 if png_check_sig(@signature, 8) <> 0 then begin
5570 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5572 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5575 png_info := png_create_info_struct(png);
5576 if png_info = nil then begin
5577 png_destroy_read_struct(@png, nil, nil);
5578 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5581 // set read callback
5582 png_set_read_fn(png, stream, glBitmap_libPNG_read_func);
5584 // read informations
5585 png_read_info(png, png_info);
5588 TempHeight := png_get_image_height(png, png_info);
5589 TempWidth := png_get_image_width(png, png_info);
5592 case png_get_color_type(png, png_info) of
5593 PNG_COLOR_TYPE_GRAY:
5594 Format := tfLuminance8;
5595 PNG_COLOR_TYPE_GRAY_ALPHA:
5596 Format := tfLuminance8Alpha8;
5599 PNG_COLOR_TYPE_RGB_ALPHA:
5602 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5605 // cut upper 8 bit from 16 bit formats
5606 if png_get_bit_depth(png, png_info) > 8 then
5607 png_set_strip_16(png);
5609 // expand bitdepth smaller than 8
5610 if png_get_bit_depth(png, png_info) < 8 then
5611 png_set_expand(png);
5613 // allocating mem for scanlines
5614 LineSize := png_get_rowbytes(png, png_info);
5615 GetMem(png_data, TempHeight * LineSize);
5617 SetLength(png_rows, TempHeight);
5618 for Row := Low(png_rows) to High(png_rows) do begin
5619 png_rows[Row] := png_data;
5620 Inc(png_rows[Row], Row * LineSize);
5623 // read complete image into scanlines
5624 png_read_image(png, @png_rows[0]);
5627 png_read_end(png, png_info);
5629 // destroy read struct
5630 png_destroy_read_struct(@png, @png_info, nil);
5632 SetLength(png_rows, 0);
5635 SetDataPointer(png_data, Format, TempWidth, TempHeight);
5648 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5649 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5650 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5654 Header: Array[0..7] of Byte;
5655 Row, Col, PixSize, LineSize: Integer;
5656 NewImage, pSource, pDest, pAlpha: pByte;
5657 Format: TglBitmapInternalFormat;
5660 PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10);
5665 StreamPos := Stream.Position;
5666 Stream.Read(Header[0], SizeOf(Header));
5667 Stream.Position := StreamPos;
5669 {Test if the header matches}
5670 if Header = PngHeader then begin
5671 Png := TPNGObject.Create;
5673 Png.LoadFromStream(Stream);
5675 case Png.Header.ColorType of
5677 Format := ifLuminance;
5678 COLOR_GRAYSCALEALPHA:
5679 Format := ifLuminanceAlpha;
5685 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5688 PixSize := Trunc(FormatGetSize(Format));
5689 LineSize := Integer(Png.Header.Width) * PixSize;
5691 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5695 case Png.Header.ColorType of
5696 COLOR_RGB, COLOR_GRAYSCALE:
5698 for Row := 0 to Png.Height -1 do begin
5699 Move (Png.Scanline[Row]^, pDest^, LineSize);
5700 Inc(pDest, LineSize);
5703 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5705 PixSize := PixSize -1;
5707 for Row := 0 to Png.Height -1 do begin
5708 pSource := Png.Scanline[Row];
5709 pAlpha := pByte(Png.AlphaScanline[Row]);
5711 for Col := 0 to Png.Width -1 do begin
5712 Move (pSource^, pDest^, PixSize);
5713 Inc(pSource, PixSize);
5714 Inc(pDest, PixSize);
5723 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5726 SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height);
5741 {$IFDEF GLB_SUPPORT_PNG_WRITE}
5742 {$IFDEF GLB_LIB_PNG}
5743 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5744 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5746 TStream(png_get_io_ptr(png)).Write(buffer^, size);
5750 {$IF DEFINED(GLB_LIB_PNG)}
5751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5752 procedure TglBitmap.SavePNG(const aStream: TStream);
5755 png_info: png_infop;
5756 png_rows: array of pByte;
5761 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
5762 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5764 if not init_libPNG then
5765 raise Exception.Create('SavePNG - unable to initialize libPNG.');
5768 case FInternalFormat of
5769 ifAlpha, ifLuminance, ifDepth8:
5770 ColorType := PNG_COLOR_TYPE_GRAY;
5772 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
5774 ColorType := PNG_COLOR_TYPE_RGB;
5776 ColorType := PNG_COLOR_TYPE_RGBA;
5778 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5780 LineSize := Trunc(FormatGetSize(FInternalFormat) * Width);
5782 // creating array for scanline
5783 SetLength(png_rows, Height);
5785 for Row := 0 to Height - 1 do begin
5786 png_rows[Row] := Data;
5787 Inc(png_rows[Row], Row * LineSize)
5791 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5793 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
5796 png_info := png_create_info_struct(png);
5797 if png_info = nil then begin
5798 png_destroy_write_struct(@png, nil);
5799 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
5802 // set read callback
5803 png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil);
5806 png_set_compression_level(png, 6);
5808 if InternalFormat in [ifBGR8, ifBGRA8] then
5811 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
5812 png_write_info(png, png_info);
5813 png_write_image(png, @png_rows[0]);
5814 png_write_end(png, png_info);
5815 png_destroy_write_struct(@png, @png_info);
5817 SetLength(png_rows, 0);
5824 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5825 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5826 procedure TglBitmap.SavePNG(const aStream: TStream);
5830 pSource, pDest: pByte;
5831 X, Y, PixSize: Integer;
5832 ColorType: Cardinal;
5838 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
5839 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5841 case FInternalFormat of
5842 ifAlpha, ifLuminance, ifDepth8: begin
5843 ColorType := COLOR_GRAYSCALE;
5847 ifLuminanceAlpha: begin
5848 ColorType := COLOR_GRAYSCALEALPHA;
5852 ifBGR8, ifRGB8: begin
5853 ColorType := COLOR_RGB;
5857 ifBGRA8, ifRGBA8: begin
5858 ColorType := COLOR_RGBALPHA;
5863 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5866 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
5870 for Y := 0 to Height -1 do begin
5871 pDest := png.ScanLine[Y];
5872 for X := 0 to Width -1 do begin
5873 Move(pSource^, pDest^, PixSize);
5874 Inc(pDest, PixSize);
5875 Inc(pSource, PixSize);
5877 png.AlphaScanline[Y]^[X] := pSource^;
5882 // convert RGB line to BGR
5883 if InternalFormat in [ifRGB8, ifRGBA8] then begin
5884 pTemp := png.ScanLine[Y];
5885 for X := 0 to Width -1 do begin
5886 Temp := pByteArray(pTemp)^[0];
5887 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
5888 pByteArray(pTemp)^[2] := Temp;
5895 Png.CompressionLevel := 6;
5896 Png.SaveToStream(Stream);
5904 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5905 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5906 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5907 {$IFDEF GLB_LIB_JPEG}
5909 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
5910 glBitmap_libJPEG_source_mgr = record
5911 pub: jpeg_source_mgr;
5914 SrcBuffer: array [1..4096] of byte;
5917 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
5918 glBitmap_libJPEG_dest_mgr = record
5919 pub: jpeg_destination_mgr;
5921 DestStream: TStream;
5922 DestBuffer: array [1..4096] of byte;
5925 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5927 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
5931 SetLength(Msg, 256);
5932 cinfo^.err^.format_message(cinfo, pChar(Msg));
5933 Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
5934 cinfo^.global_state := 0;
5939 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5941 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
5945 SetLength(Msg, 256);
5946 cinfo^.err^.format_message(cinfo, pChar(Msg));
5947 Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
5948 cinfo^.global_state := 0;
5952 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5954 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
5959 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5960 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
5962 src: glBitmap_libJPEG_source_mgr_ptr;
5965 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5967 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
5968 if (bytes <= 0) then begin
5969 src^.SrcBuffer[1] := $FF;
5970 src^.SrcBuffer[2] := JPEG_EOI;
5974 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
5975 src^.pub.bytes_in_buffer := bytes;
5980 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5981 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
5983 src: glBitmap_libJPEG_source_mgr_ptr;
5985 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5987 if num_bytes > 0 then begin
5988 // wanted byte isn't in buffer so set stream position and read buffer
5989 if num_bytes > src^.pub.bytes_in_buffer then begin
5990 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
5991 src^.pub.fill_input_buffer(cinfo);
5993 // wanted byte is in buffer so only skip
5994 inc(src^.pub.next_input_byte, num_bytes);
5995 dec(src^.pub.bytes_in_buffer, num_bytes);
6000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6002 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
6007 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6009 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
6014 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6015 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
6017 dest: glBitmap_libJPEG_dest_mgr_ptr;
6019 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6021 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
6022 // write complete buffer
6023 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
6026 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
6027 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
6033 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6034 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
6037 dest: glBitmap_libJPEG_dest_mgr_ptr;
6039 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6041 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6042 // check for endblock
6043 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6045 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6050 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6055 {$IFDEF GLB_SUPPORT_JPEG_READ}
6056 {$IF DEFINED(GLB_SDL_IMAGE)}
6057 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6058 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6060 Surface: PSDL_Surface;
6065 RWops := glBitmapCreateRWops(Stream);
6067 if IMG_isJPG(RWops) > 0 then begin
6068 Surface := IMG_LoadJPG_RW(RWops);
6070 AssignFromSurface(Surface);
6073 SDL_FreeSurface(Surface);
6081 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6082 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6083 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6086 Temp: array[0..1]of Byte;
6088 jpeg: jpeg_decompress_struct;
6089 jpeg_err: jpeg_error_mgr;
6091 IntFormat: TglBitmapInternalFormat;
6093 TempHeight, TempWidth: Integer;
6100 if not init_libJPEG then
6101 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6104 // reading first two bytes to test file and set cursor back to begin
6105 StreamPos := Stream.Position;
6106 Stream.Read(Temp[0], 2);
6107 Stream.Position := StreamPos;
6109 // if Bitmap then read file.
6110 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6111 FillChar(jpeg, SizeOf(jpeg_decompress_struct), $00);
6112 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
6115 jpeg.err := jpeg_std_error(@jpeg_err);
6116 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6117 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6119 // decompression struct
6120 jpeg_create_decompress(@jpeg);
6122 // allocation space for streaming methods
6123 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6125 // seeting up custom functions
6126 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6127 pub.init_source := glBitmap_libJPEG_init_source;
6128 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6129 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6130 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6131 pub.term_source := glBitmap_libJPEG_term_source;
6133 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6134 pub.next_input_byte := nil; // until buffer loaded
6136 SrcStream := Stream;
6139 // set global decoding state
6140 jpeg.global_state := DSTATE_START;
6142 // read header of jpeg
6143 jpeg_read_header(@jpeg, false);
6145 // setting output parameter
6146 case jpeg.jpeg_color_space of
6149 jpeg.out_color_space := JCS_GRAYSCALE;
6150 IntFormat := ifLuminance;
6153 jpeg.out_color_space := JCS_RGB;
6154 IntFormat := ifRGB8;
6158 jpeg_start_decompress(@jpeg);
6160 TempHeight := jpeg.output_height;
6161 TempWidth := jpeg.output_width;
6163 // creating new image
6164 GetMem(pImage, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
6168 for Row := 0 to TempHeight -1 do begin
6169 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6170 Inc(pTemp, Trunc(FormatGetSize(IntFormat) * TempWidth));
6173 // finish decompression
6174 jpeg_finish_decompress(@jpeg);
6176 // destroy decompression
6177 jpeg_destroy_decompress(@jpeg);
6179 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight);
6192 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6193 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6194 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6199 Temp: array[0..1]of Byte;
6203 // reading first two bytes to test file and set cursor back to begin
6204 StreamPos := Stream.Position;
6205 Stream.Read(Temp[0], 2);
6206 Stream.Position := StreamPos;
6208 // if Bitmap then read file.
6209 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6210 bmp := TBitmap.Create;
6212 jpg := TJPEGImage.Create;
6214 jpg.LoadFromStream(Stream);
6216 result := AssignFromBitmap(bmp);
6228 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6229 {$IF DEFEFINED(GLB_LIB_JPEG)}
6230 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6231 procedure TglBitmap.SaveJPEG(Stream: TStream);
6233 jpeg: jpeg_compress_struct;
6234 jpeg_err: jpeg_error_mgr;
6236 pTemp, pTemp2: pByte;
6238 procedure CopyRow(pDest, pSource: pByte);
6242 for X := 0 to Width - 1 do begin
6243 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6244 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6245 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6252 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6253 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
6255 if not init_libJPEG then
6256 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6259 FillChar(jpeg, SizeOf(jpeg_compress_struct), $00);
6260 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
6263 jpeg.err := jpeg_std_error(@jpeg_err);
6264 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6265 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6267 // compression struct
6268 jpeg_create_compress(@jpeg);
6270 // allocation space for streaming methods
6271 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6273 // seeting up custom functions
6274 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6275 pub.init_destination := glBitmap_libJPEG_init_destination;
6276 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6277 pub.term_destination := glBitmap_libJPEG_term_destination;
6279 pub.next_output_byte := @DestBuffer[1];
6280 pub.free_in_buffer := Length(DestBuffer);
6282 DestStream := Stream;
6285 // very important state
6286 jpeg.global_state := CSTATE_START;
6287 jpeg.image_width := Width;
6288 jpeg.image_height := Height;
6289 case InternalFormat of
6290 ifAlpha, ifLuminance, ifDepth8: begin
6291 jpeg.input_components := 1;
6292 jpeg.in_color_space := JCS_GRAYSCALE;
6294 ifRGB8, ifBGR8: begin
6295 jpeg.input_components := 3;
6296 jpeg.in_color_space := JCS_RGB;
6300 jpeg_set_defaults(@jpeg);
6301 jpeg_set_quality(@jpeg, 95, true);
6302 jpeg_start_compress(@jpeg, true);
6305 if InternalFormat = ifBGR8 then
6306 GetMem(pTemp2, fRowSize)
6311 for Row := 0 to jpeg.image_height -1 do begin
6313 if InternalFormat = ifBGR8 then
6314 CopyRow(pTemp2, pTemp)
6319 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6320 inc(pTemp, fRowSize);
6324 if InternalFormat = ifBGR8 then
6327 jpeg_finish_compress(@jpeg);
6328 jpeg_destroy_compress(@jpeg);
6334 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6335 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6336 procedure TglBitmap.SaveJPEG(Stream: TStream);
6341 if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then
6342 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
6344 Bmp := TBitmap.Create;
6346 Jpg := TJPEGImage.Create;
6348 AssignToBitmap(Bmp);
6349 if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
6350 Jpg.Grayscale := true;
6351 Jpg.PixelFormat := jf8Bit;
6354 Jpg.SaveToStream(Stream);
6365 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6366 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6367 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6374 BMP_COMP_BITFIELDS = 3;
6377 TBMPHeader = packed record
6382 bfOffBits: Cardinal;
6385 TBMPInfo = packed record
6391 biCompression: Cardinal;
6392 biSizeImage: Cardinal;
6393 biXPelsPerMeter: Longint;
6394 biYPelsPerMeter: Longint;
6395 biClrUsed: Cardinal;
6396 biClrImportant: Cardinal;
6399 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6400 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6402 //////////////////////////////////////////////////////////////////////////////////////////////////
6403 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6406 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6407 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6410 case aInfo.biCompression of
6412 BMP_COMP_RLE8: begin
6413 raise EglBitmapException.Create('RLE compression is not supported');
6415 BMP_COMP_BITFIELDS: begin
6416 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6417 aStream.Read(aMask.r, SizeOf(aMask.r));
6418 aStream.Read(aMask.g, SizeOf(aMask.g));
6419 aStream.Read(aMask.b, SizeOf(aMask.b));
6420 aStream.Read(aMask.a, SizeOf(aMask.a));
6422 raise EglBitmapException.Create('Bitfields are only supported for 16bit and 32bit formats');
6426 //get suitable format
6427 case aInfo.biBitCount of
6428 8: result := tfLuminance8;
6429 16: result := tfBGR5;
6430 24: result := tfBGR8;
6431 32: result := tfBGRA8;
6435 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6438 ColorTable: TbmpColorTable;
6441 if (aInfo.biBitCount >= 16) then
6443 aFormat := tfLuminance8;
6444 c := aInfo.biClrUsed;
6446 c := 1 shl aInfo.biBitCount;
6447 SetLength(ColorTable, c);
6448 for i := 0 to c-1 do begin
6449 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6450 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6454 result := TbmpColorTableFormat.Create;
6455 result.PixelSize := aInfo.biBitCount / 8;
6456 result.ColorTable := ColorTable;
6457 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6460 //////////////////////////////////////////////////////////////////////////////////////////////////
6461 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6462 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6464 TmpFormat: TglBitmapFormat;
6465 FormatDesc: TFormatDescriptor;
6468 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6469 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6470 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6471 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6472 aFormat := FormatDesc.Format;
6477 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6478 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6479 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6480 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6482 result := TbmpBitfieldFormat.Create;
6483 result.PixelSize := aInfo.biBitCount / 8;
6484 result.RedMask := aMask.r;
6485 result.GreenMask := aMask.g;
6486 result.BlueMask := aMask.b;
6487 result.AlphaMask := aMask.a;
6494 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6495 PaddingBuff: Cardinal;
6496 LineBuf, ImageData, TmpData: PByte;
6497 SourceMD, DestMD: Pointer;
6498 BmpFormat: TglBitmapFormat;
6501 Mask: TglBitmapColorRec;
6506 SpecialFormat: TFormatDescriptor;
6507 FormatDesc: TFormatDescriptor;
6509 //////////////////////////////////////////////////////////////////////////////////////////////////
6510 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6513 Pixel: TglBitmapPixelData;
6515 aStream.Read(aLineBuf^, rbLineSize);
6516 SpecialFormat.PreparePixel(Pixel);
6517 for i := 0 to Info.biWidth-1 do begin
6518 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6519 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6520 FormatDesc.Map(Pixel, aData, DestMD);
6526 BmpFormat := tfEmpty;
6527 SpecialFormat := nil;
6533 StartPos := aStream.Position;
6534 aStream.Read(Header{%H-}, SizeOf(Header));
6536 if Header.bfType = BMP_MAGIC then begin
6538 BmpFormat := ReadInfo(Info, Mask);
6539 SpecialFormat := ReadColorTable(BmpFormat, Info);
6540 if not Assigned(SpecialFormat) then
6541 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6542 aStream.Position := StartPos + Header.bfOffBits;
6544 if (BmpFormat <> tfEmpty) then begin
6545 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6546 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6547 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6548 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6551 DestMD := FormatDesc.CreateMappingData;
6552 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6553 GetMem(ImageData, ImageSize);
6554 if Assigned(SpecialFormat) then begin
6555 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6556 SourceMD := SpecialFormat.CreateMappingData;
6561 FillChar(ImageData^, ImageSize, $FF);
6562 TmpData := ImageData;
6563 if (Info.biHeight > 0) then
6564 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6565 for i := 0 to Abs(Info.biHeight)-1 do begin
6566 if Assigned(SpecialFormat) then
6567 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6569 aStream.Read(TmpData^, wbLineSize); //else only read data
6570 if (Info.biHeight > 0) then
6571 dec(TmpData, wbLineSize)
6573 inc(TmpData, wbLineSize);
6574 aStream.Read(PaddingBuff{%H-}, Padding);
6576 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight));
6579 if Assigned(LineBuf) then
6581 if Assigned(SourceMD) then
6582 SpecialFormat.FreeMappingData(SourceMD);
6583 FormatDesc.FreeMappingData(DestMD);
6590 raise EglBitmapException.Create('LoadBMP - No suitable format found');
6592 aStream.Position := StartPos;
6596 FreeAndNil(SpecialFormat);
6599 else aStream.Position := StartPos;
6602 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6603 procedure TglBitmap.SaveBMP(const aStream: TStream);
6607 Converter: TbmpColorTableFormat;
6608 FormatDesc: TFormatDescriptor;
6609 SourceFD, DestFD: Pointer;
6610 pData, srcData, dstData, ConvertBuffer: pByte;
6612 Pixel: TglBitmapPixelData;
6613 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6614 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6616 PaddingBuff: Cardinal;
6618 function GetLineWidth : Integer;
6620 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6624 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6625 raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
6628 FormatDesc := TFormatDescriptor.Get(Format);
6629 ImageSize := FormatDesc.GetSize(Dimension);
6631 FillChar(Header{%H-}, SizeOf(Header), 0);
6632 Header.bfType := BMP_MAGIC;
6633 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6634 Header.bfReserved1 := 0;
6635 Header.bfReserved2 := 0;
6636 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6638 FillChar(Info{%H-}, SizeOf(Info), 0);
6639 Info.biSize := SizeOf(Info);
6640 Info.biWidth := Width;
6641 Info.biHeight := Height;
6643 Info.biCompression := BMP_COMP_RGB;
6644 Info.biSizeImage := ImageSize;
6649 Info.biBitCount := 4;
6650 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6651 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6652 Converter := TbmpColorTableFormat.Create;
6653 Converter.PixelSize := 0.5;
6654 Converter.Format := Format;
6655 Converter.Range := glBitmapColorRec($F, $F, $F, $0);
6656 Converter.CreateColorTable;
6659 tfR3G3B2, tfLuminance8: begin
6660 Info.biBitCount := 8;
6661 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6662 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6663 Converter := TbmpColorTableFormat.Create;
6664 Converter.PixelSize := 1;
6665 Converter.Format := Format;
6666 if (Format = tfR3G3B2) then begin
6667 Converter.Range := glBitmapColorRec($7, $7, $3, $0);
6668 Converter.Shift := glBitmapShiftRec(0, 3, 6, 0);
6670 Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0);
6671 Converter.CreateColorTable;
6674 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6675 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6676 Info.biBitCount := 16;
6677 Info.biCompression := BMP_COMP_BITFIELDS;
6680 tfBGR8, tfRGB8: begin
6681 Info.biBitCount := 24;
6684 tfRGB10, tfRGB10A2, tfRGBA8,
6685 tfBGR10, tfBGR10A2, tfBGRA8: begin
6686 Info.biBitCount := 32;
6687 Info.biCompression := BMP_COMP_BITFIELDS;
6690 raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
6692 Info.biXPelsPerMeter := 2835;
6693 Info.biYPelsPerMeter := 2835;
6696 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6697 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
6698 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
6700 RedMask := FormatDesc.RedMask;
6701 GreenMask := FormatDesc.GreenMask;
6702 BlueMask := FormatDesc.BlueMask;
6703 AlphaMask := FormatDesc.AlphaMask;
6707 aStream.Write(Header, SizeOf(Header));
6708 aStream.Write(Info, SizeOf(Info));
6711 if Assigned(Converter) then
6712 aStream.Write(Converter.ColorTable[0].b,
6713 SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable));
6716 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6717 aStream.Write(RedMask, SizeOf(Cardinal));
6718 aStream.Write(GreenMask, SizeOf(Cardinal));
6719 aStream.Write(BlueMask, SizeOf(Cardinal));
6720 aStream.Write(AlphaMask, SizeOf(Cardinal));
6724 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
6725 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
6726 Padding := GetLineWidth - wbLineSize;
6730 inc(pData, (Height-1) * rbLineSize);
6732 // prepare row buffer. But only for RGB because RGBA supports color masks
6733 // so it's possible to change color within the image.
6734 if Assigned(Converter) then begin
6735 FormatDesc.PreparePixel(Pixel);
6736 GetMem(ConvertBuffer, wbLineSize);
6737 SourceFD := FormatDesc.CreateMappingData;
6738 DestFD := Converter.CreateMappingData;
6740 ConvertBuffer := nil;
6743 for LineIdx := 0 to Height - 1 do begin
6745 if Assigned(Converter) then begin
6747 dstData := ConvertBuffer;
6748 for PixelIdx := 0 to Info.biWidth-1 do begin
6749 FormatDesc.Unmap(srcData, Pixel, SourceFD);
6750 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
6751 Converter.Map(Pixel, dstData, DestFD);
6753 aStream.Write(ConvertBuffer^, wbLineSize);
6755 aStream.Write(pData^, rbLineSize);
6757 dec(pData, rbLineSize);
6758 if (Padding > 0) then
6759 aStream.Write(PaddingBuff, Padding);
6762 // destroy row buffer
6763 if Assigned(ConvertBuffer) then begin
6764 FormatDesc.FreeMappingData(SourceFD);
6765 Converter.FreeMappingData(DestFD);
6766 FreeMem(ConvertBuffer);
6770 if Assigned(Converter) then
6775 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6776 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6777 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6779 TTGAHeader = packed record
6783 //ColorMapSpec: Array[0..4] of Byte;
6784 ColorMapStart: Word;
6785 ColorMapLength: Word;
6786 ColorMapEntrySize: Byte;
6796 TGA_UNCOMPRESSED_RGB = 2;
6797 TGA_UNCOMPRESSED_GRAY = 3;
6798 TGA_COMPRESSED_RGB = 10;
6799 TGA_COMPRESSED_GRAY = 11;
6801 TGA_NONE_COLOR_TABLE = 0;
6803 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6804 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
6808 StartPosition: Int64;
6809 PixelSize, LineSize: Integer;
6810 tgaFormat: TglBitmapFormat;
6811 FormatDesc: TFormatDescriptor;
6812 Counter: packed record
6814 low, high, dir: Integer;
6821 ////////////////////////////////////////////////////////////////////////////////////////
6822 procedure ReadUncompressed;
6825 buf, tmp1, tmp2: PByte;
6828 if (Counter.X.dir < 0) then
6829 buf := GetMem(LineSize);
6831 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
6832 tmp1 := ImageData + (Counter.Y.low * LineSize); //pointer to LineStart
6833 if (Counter.X.dir < 0) then begin //flip X
6834 aStream.Read(buf^, LineSize);
6835 tmp2 := buf + LineSize - PixelSize; //pointer to last pixel in line
6836 for i := 0 to Header.Width-1 do begin //for all pixels in line
6837 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
6842 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
6845 aStream.Read(tmp1^, LineSize);
6846 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
6849 if Assigned(buf) then
6854 ////////////////////////////////////////////////////////////////////////////////////////
6855 procedure ReadCompressed;
6857 /////////////////////////////////////////////////////////////////
6860 LinePixelsRead: Integer;
6861 procedure CheckLine;
6863 if (LinePixelsRead >= Header.Width) then begin
6864 LinePixelsRead := 0;
6865 inc(Counter.Y.low, Counter.Y.dir); //next line index
6866 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6867 if (Counter.X.dir < 0) then //if x flipped then
6868 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6872 /////////////////////////////////////////////////////////////////
6875 CacheSize, CachePos: Integer;
6876 procedure CachedRead(out Buffer; Count: Integer);
6880 if (CachePos + Count > CacheSize) then begin
6881 //if buffer overflow save non read bytes
6883 if (CacheSize - CachePos > 0) then begin
6884 BytesRead := CacheSize - CachePos;
6885 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
6886 inc(CachePos, BytesRead);
6889 //load cache from file
6890 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
6891 aStream.Read(Cache^, CacheSize);
6894 //read rest of requested bytes
6895 if (Count - BytesRead > 0) then begin
6896 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
6897 inc(CachePos, Count - BytesRead);
6900 //if no buffer overflow just read the data
6901 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
6902 inc(CachePos, Count);
6906 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
6911 inc(aBuffer, Counter.X.dir);
6914 PWord(aBuffer)^ := PWord(aData)^;
6915 inc(aBuffer, 2 * Counter.X.dir);
6918 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
6919 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
6920 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
6921 inc(aBuffer, 3 * Counter.X.dir);
6924 PCardinal(aBuffer)^ := PCardinal(aData)^;
6925 inc(aBuffer, 4 * Counter.X.dir);
6931 TotalPixelsToRead, TotalPixelsRead: Integer;
6933 buf: array [0..3] of Byte; //1 pixel is max 32bit long
6934 PixelRepeat: Boolean;
6935 PixelsToRead, PixelCount: Integer;
6940 TotalPixelsToRead := Header.Width * Header.Height;
6941 TotalPixelsRead := 0;
6942 LinePixelsRead := 0;
6944 GetMem(Cache, CACHE_SIZE);
6946 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6947 if (Counter.X.dir < 0) then //if x flipped then
6948 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6952 CachedRead(Temp, 1);
6953 PixelRepeat := (Temp and $80) > 0;
6954 PixelsToRead := (Temp and $7F) + 1;
6955 inc(TotalPixelsRead, PixelsToRead);
6958 CachedRead(buf[0], PixelSize);
6959 while (PixelsToRead > 0) do begin
6961 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
6962 while (PixelCount > 0) do begin
6963 if not PixelRepeat then
6964 CachedRead(buf[0], PixelSize);
6965 PixelToBuffer(@buf[0], TmpData);
6966 inc(LinePixelsRead);
6971 until (TotalPixelsRead >= TotalPixelsToRead);
6977 function IsGrayFormat: Boolean;
6979 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
6985 // reading header to test file and set cursor back to begin
6986 StartPosition := aStream.Position;
6987 aStream.Read(Header{%H-}, SizeOf(Header));
6989 // no colormapped files
6990 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
6991 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
6994 if Header.ImageID <> 0 then // skip image ID
6995 aStream.Position := aStream.Position + Header.ImageID;
6998 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
6999 0: tgaFormat := tfLuminance8;
7000 8: tgaFormat := tfAlpha8;
7003 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
7004 0: tgaFormat := tfLuminance16;
7005 8: tgaFormat := tfLuminance8Alpha8;
7006 end else case (Header.ImageDesc and $F) of
7007 0: tgaFormat := tfBGR5;
7008 1: tgaFormat := tfBGR5A1;
7009 4: tgaFormat := tfBGRA4;
7012 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7013 0: tgaFormat := tfBGR8;
7016 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
7017 2: tgaFormat := tfBGR10A2;
7018 8: tgaFormat := tfBGRA8;
7022 if (tgaFormat = tfEmpty) then
7023 raise EglBitmapException.Create('LoadTga - unsupported format');
7025 FormatDesc := TFormatDescriptor.Get(tgaFormat);
7026 PixelSize := FormatDesc.GetSize(1, 1);
7027 LineSize := FormatDesc.GetSize(Header.Width, 1);
7029 GetMem(ImageData, LineSize * Header.Height);
7032 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
7033 Counter.X.low := Header.Height-1;;
7034 Counter.X.high := 0;
7035 Counter.X.dir := -1;
7038 Counter.X.high := Header.Height-1;
7043 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7045 Counter.Y.high := Header.Height-1;
7048 Counter.Y.low := Header.Height-1;;
7049 Counter.Y.high := 0;
7050 Counter.Y.dir := -1;
7054 case Header.ImageType of
7055 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7057 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7061 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height);
7068 aStream.Position := StartPosition;
7071 else aStream.Position := StartPosition;
7074 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7075 procedure TglBitmap.SaveTGA(const aStream: TStream);
7078 LineSize, Size, x, y: Integer;
7079 Pixel: TglBitmapPixelData;
7080 LineBuf, SourceData, DestData: PByte;
7081 SourceMD, DestMD: Pointer;
7082 FormatDesc: TFormatDescriptor;
7083 Converter: TFormatDescriptor;
7085 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7086 raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT);
7089 FillChar(Header{%H-}, SizeOf(Header), 0);
7092 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7093 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7094 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7096 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7099 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7101 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7102 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7104 else if (Format in [tfBGR8, tfRGB8]) then
7112 Header.ImageDesc := 1 and $F;
7113 tfRGB10A2, tfBGR10A2:
7114 Header.ImageDesc := 2 and $F;
7116 Header.ImageDesc := 4 and $F;
7117 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7118 Header.ImageDesc := 8 and $F;
7121 Header.Width := Width;
7122 Header.Height := Height;
7123 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7124 aStream.Write(Header, SizeOf(Header));
7126 // convert RGB(A) to BGR(A)
7128 FormatDesc := TFormatDescriptor.Get(Format);
7129 Size := FormatDesc.GetSize(Dimension);
7130 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7131 if (FormatDesc.RGBInverted = tfEmpty) then
7132 raise EglBitmapException.Create('inverted RGB format is empty');
7133 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7134 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7135 (Converter.PixelSize <> FormatDesc.PixelSize) then
7136 raise EglBitmapException.Create('invalid inverted RGB format');
7139 if Assigned(Converter) then begin
7140 LineSize := FormatDesc.GetSize(Width, 1);
7141 LineBuf := GetMem(LineSize);
7142 SourceMD := FormatDesc.CreateMappingData;
7143 DestMD := Converter.CreateMappingData;
7146 for y := 0 to Height-1 do begin
7147 DestData := LineBuf;
7148 for x := 0 to Width-1 do begin
7149 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7150 Converter.Map(Pixel, DestData, DestMD);
7152 aStream.Write(LineBuf^, LineSize);
7156 FormatDesc.FreeMappingData(SourceMD);
7157 FormatDesc.FreeMappingData(DestMD);
7160 aStream.Write(Data^, Size);
7163 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7164 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7165 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7167 DDS_MAGIC: Cardinal = $20534444;
7169 // DDS_header.dwFlags
7170 DDSD_CAPS = $00000001;
7171 DDSD_HEIGHT = $00000002;
7172 DDSD_WIDTH = $00000004;
7173 DDSD_PIXELFORMAT = $00001000;
7175 // DDS_header.sPixelFormat.dwFlags
7176 DDPF_ALPHAPIXELS = $00000001;
7177 DDPF_ALPHA = $00000002;
7178 DDPF_FOURCC = $00000004;
7179 DDPF_RGB = $00000040;
7180 DDPF_LUMINANCE = $00020000;
7182 // DDS_header.sCaps.dwCaps1
7183 DDSCAPS_TEXTURE = $00001000;
7185 // DDS_header.sCaps.dwCaps2
7186 DDSCAPS2_CUBEMAP = $00000200;
7188 D3DFMT_DXT1 = $31545844;
7189 D3DFMT_DXT3 = $33545844;
7190 D3DFMT_DXT5 = $35545844;
7193 TDDSPixelFormat = packed record
7197 dwRGBBitCount: Cardinal;
7198 dwRBitMask: Cardinal;
7199 dwGBitMask: Cardinal;
7200 dwBBitMask: Cardinal;
7201 dwABitMask: Cardinal;
7204 TDDSCaps = packed record
7208 dwReserved: Cardinal;
7211 TDDSHeader = packed record
7216 dwPitchOrLinearSize: Cardinal;
7218 dwMipMapCount: Cardinal;
7219 dwReserved: array[0..10] of Cardinal;
7220 PixelFormat: TDDSPixelFormat;
7222 dwReserved2: Cardinal;
7225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7226 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7229 Converter: TbmpBitfieldFormat;
7231 function GetDDSFormat: TglBitmapFormat;
7233 fd: TFormatDescriptor;
7235 Range: TglBitmapColorRec;
7239 with Header.PixelFormat do begin
7241 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7242 case Header.PixelFormat.dwFourCC of
7243 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7244 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7245 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7247 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7249 //find matching format
7250 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7251 fd := TFormatDescriptor.Get(result);
7252 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7253 (8 * fd.PixelSize = dwRGBBitCount) then
7257 //find format with same Range
7258 Range.r := dwRBitMask;
7259 Range.g := dwGBitMask;
7260 Range.b := dwBBitMask;
7261 Range.a := dwABitMask;
7262 for i := 0 to 3 do begin
7263 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7264 Range.arr[i] := Range.arr[i] shr 1;
7266 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7267 fd := TFormatDescriptor.Get(result);
7270 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7278 //no format with same range found -> use default
7279 if (result = tfEmpty) then begin
7280 if (dwABitMask > 0) then
7286 Converter := TbmpBitfieldFormat.Create;
7287 Converter.RedMask := dwRBitMask;
7288 Converter.GreenMask := dwGBitMask;
7289 Converter.BlueMask := dwBBitMask;
7290 Converter.AlphaMask := dwABitMask;
7291 Converter.PixelSize := dwRGBBitCount / 8;
7298 x, y, LineSize, RowSize, Magic: Cardinal;
7299 NewImage, TmpData, RowData, SrcData: PByte;
7300 SourceMD, DestMD: Pointer;
7301 Pixel: TglBitmapPixelData;
7302 ddsFormat: TglBitmapFormat;
7303 FormatDesc: TFormatDescriptor;
7308 StreamPos := aStream.Position;
7311 aStream.Read(Magic{%H-}, sizeof(Magic));
7312 if (Magic <> DDS_MAGIC) then begin
7313 aStream.Position := StreamPos;
7318 aStream.Read(Header{%H-}, sizeof(Header));
7319 if (Header.dwSize <> SizeOf(Header)) or
7320 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7321 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7323 aStream.Position := StreamPos;
7327 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7328 raise EglBitmapException.Create('LoadDDS - CubeMaps are not supported');
7330 ddsFormat := GetDDSFormat;
7332 if (ddsFormat = tfEmpty) then
7333 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7335 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7336 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7337 GetMem(NewImage, Header.dwHeight * LineSize);
7339 TmpData := NewImage;
7342 if Assigned(Converter) then begin
7343 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7344 GetMem(RowData, RowSize);
7345 SourceMD := Converter.CreateMappingData;
7346 DestMD := FormatDesc.CreateMappingData;
7348 for y := 0 to Header.dwHeight-1 do begin
7349 TmpData := NewImage + y * LineSize;
7351 aStream.Read(SrcData^, RowSize);
7352 for x := 0 to Header.dwWidth-1 do begin
7353 Converter.Unmap(SrcData, Pixel, SourceMD);
7354 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7355 FormatDesc.Map(Pixel, TmpData, DestMD);
7359 Converter.FreeMappingData(SourceMD);
7360 FormatDesc.FreeMappingData(DestMD);
7366 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7367 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7368 for Y := 0 to Header.dwHeight-1 do begin
7369 aStream.Read(TmpData^, RowSize);
7370 Inc(TmpData, LineSize);
7375 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7376 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7377 for Y := 0 to Header.dwHeight-1 do begin
7378 aStream.Read(TmpData^, RowSize);
7379 Inc(TmpData, LineSize);
7382 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7384 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
7391 FreeAndNil(Converter);
7395 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7396 procedure TglBitmap.SaveDDS(const aStream: TStream);
7399 FormatDesc: TFormatDescriptor;
7401 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7402 raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_FORMAT);
7404 FormatDesc := TFormatDescriptor.Get(Format);
7407 FillChar(Header{%H-}, SizeOf(Header), 0);
7408 Header.dwSize := SizeOf(Header);
7409 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7411 Header.dwWidth := Max(1, Width);
7412 Header.dwHeight := Max(1, Height);
7415 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7418 Header.PixelFormat.dwSize := sizeof(Header);
7419 if (FormatDesc.IsCompressed) then begin
7420 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7422 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7423 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7424 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7426 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7427 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7428 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7429 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7430 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7431 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7432 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7433 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7434 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7436 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7437 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7438 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7439 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7440 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7441 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7444 if (FormatDesc.HasAlpha) then
7445 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7447 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7448 aStream.Write(Header, SizeOf(Header));
7449 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7452 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7453 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7454 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7455 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7457 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7458 result := fLines[aIndex]
7463 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7464 procedure TglBitmap2D.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
7465 const aWidth: Integer; const aHeight: Integer);
7467 Idx, LineWidth: Integer;
7469 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7471 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7473 fGetPixelFunc := GetPixel2DUnmap;
7474 fSetPixelFunc := SetPixel2DUnmap;
7477 if Assigned(Data) then begin
7478 SetLength(fLines, GetHeight);
7479 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7481 for Idx := 0 to GetHeight -1 do begin
7482 fLines[Idx] := Data;
7483 Inc(fLines[Idx], Idx * LineWidth);
7486 else SetLength(fLines, 0);
7488 SetLength(fLines, 0);
7490 fSetPixelFunc := nil;
7494 fGetPixelFunc := GetPixel2DDXT1;
7496 fGetPixelFunc := GetPixel2DDXT3;
7498 fGetPixelFunc := GetPixel2DDXT5;
7500 fGetPixelFunc := nil;
7506 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7507 procedure TglBitmap2D.UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
7509 FormatDesc: TFormatDescriptor;
7511 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7513 FormatDesc := TFormatDescriptor.Get(Format);
7514 if FormatDesc.IsCompressed then begin
7515 glCompressedTexImage2D(Target, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7516 end else if aBuildWithGlu then begin
7517 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7518 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7520 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7521 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7525 if (FreeDataAfterGenTexture) then
7529 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7530 procedure TglBitmap2D.AfterConstruction;
7533 Target := GL_TEXTURE_2D;
7536 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7537 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7540 Size, w, h: Integer;
7541 FormatDesc: TFormatDescriptor;
7543 FormatDesc := TFormatDescriptor.Get(Format);
7544 if FormatDesc.IsCompressed then
7545 raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_FORMAT);
7547 w := aRight - aLeft;
7548 h := aBottom - aTop;
7549 Size := FormatDesc.GetSize(w, h);
7552 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7553 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7554 SetDataPointer(Temp, Format, w, h);
7562 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7563 procedure TglBitmap2D.GetDataFromTexture;
7566 TempWidth, TempHeight: Integer;
7567 TempIntFormat: Cardinal;
7568 IntFormat, f: TglBitmapFormat;
7569 FormatDesc: TFormatDescriptor;
7574 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7575 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7576 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7578 IntFormat := tfEmpty;
7579 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
7580 FormatDesc := TFormatDescriptor.Get(f);
7581 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
7582 IntFormat := FormatDesc.Format;
7587 // Getting data from OpenGL
7588 FormatDesc := TFormatDescriptor.Get(IntFormat);
7589 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
7591 if FormatDesc.IsCompressed then
7592 glGetCompressedTexImage(Target, 0, Temp)
7594 glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
7595 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
7602 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7603 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
7605 BuildWithGlu, PotTex, TexRec: Boolean;
7608 if Assigned(Data) then begin
7609 // Check Texture Size
7610 if (aTestTextureSize) then begin
7611 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7613 if ((Height > TexSize) or (Width > TexSize)) then
7614 raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7616 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
7617 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
7619 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7620 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7624 SetupParameters(BuildWithGlu);
7625 UploadData(Target, BuildWithGlu);
7626 glAreTexturesResident(1, @fID, @fIsResident);
7630 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7631 function TglBitmap2D.FlipHorz: Boolean;
7634 TempDestData, DestData, SourceData: PByte;
7637 result := inherited FlipHorz;
7638 if Assigned(Data) then begin
7640 ImgSize := Height * fRowSize;
7641 GetMem(DestData, ImgSize);
7643 TempDestData := DestData;
7644 Dec(TempDestData, fRowSize + fPixelSize);
7645 for Row := 0 to Height -1 do begin
7646 Inc(TempDestData, fRowSize * 2);
7647 for Col := 0 to Width -1 do begin
7648 Move(SourceData^, TempDestData^, fPixelSize);
7649 Inc(SourceData, fPixelSize);
7650 Dec(TempDestData, fPixelSize);
7653 SetDataPointer(DestData, Format);
7662 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7663 function TglBitmap2D.FlipVert: Boolean;
7666 TempDestData, DestData, SourceData: PByte;
7668 result := inherited FlipVert;
7669 if Assigned(Data) then begin
7671 GetMem(DestData, Height * fRowSize);
7673 TempDestData := DestData;
7674 Inc(TempDestData, Width * (Height -1) * fPixelSize);
7675 for Row := 0 to Height -1 do begin
7676 Move(SourceData^, TempDestData^, fRowSize);
7677 Dec(TempDestData, fRowSize);
7678 Inc(SourceData, fRowSize);
7680 SetDataPointer(DestData, Format);
7689 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7690 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7691 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7693 TMatrixItem = record
7698 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
7699 TglBitmapToNormalMapRec = Record
7701 Heights: array of Single;
7702 MatrixU : array of TMatrixItem;
7703 MatrixV : array of TMatrixItem;
7707 ONE_OVER_255 = 1 / 255;
7709 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7710 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
7714 with FuncRec do begin
7716 Source.Data.r * LUMINANCE_WEIGHT_R +
7717 Source.Data.g * LUMINANCE_WEIGHT_G +
7718 Source.Data.b * LUMINANCE_WEIGHT_B;
7719 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
7723 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7724 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
7727 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
7730 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7731 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
7733 TVec = Array[0..2] of Single;
7740 function GetHeight(X, Y: Integer): Single;
7742 with FuncRec do begin
7743 X := Max(0, Min(Size.X -1, X));
7744 Y := Max(0, Min(Size.Y -1, Y));
7745 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
7750 with FuncRec do begin
7751 with PglBitmapToNormalMapRec(Args)^ do begin
7753 for Idx := Low(MatrixU) to High(MatrixU) do
7754 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
7757 for Idx := Low(MatrixU) to High(MatrixU) do
7758 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
7760 Vec[0] := -du * Scale;
7761 Vec[1] := -dv * Scale;
7766 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
7767 if Len <> 0 then begin
7768 Vec[0] := Vec[0] * Len;
7769 Vec[1] := Vec[1] * Len;
7770 Vec[2] := Vec[2] * Len;
7774 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
7775 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
7776 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
7780 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7781 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
7783 Rec: TglBitmapToNormalMapRec;
7785 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
7787 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
7788 Matrix[Index].X := X;
7789 Matrix[Index].Y := Y;
7790 Matrix[Index].W := W;
7796 if not FormatIsUncompressed(InternalFormat) then
7797 raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_FORMAT);
7800 if aScale > 100 then
7802 else if aScale < -100 then
7805 Rec.Scale := aScale;
7807 SetLength(Rec.Heights, Width * Height);
7811 SetLength(Rec.MatrixU, 2);
7812 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
7813 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
7815 SetLength(Rec.MatrixV, 2);
7816 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
7817 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
7821 SetLength(Rec.MatrixU, 6);
7822 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
7823 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
7824 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
7825 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
7826 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
7827 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
7829 SetLength(Rec.MatrixV, 6);
7830 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
7831 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
7832 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
7833 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
7834 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
7835 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
7839 SetLength(Rec.MatrixU, 6);
7840 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
7841 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
7842 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
7843 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
7844 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
7845 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
7847 SetLength(Rec.MatrixV, 6);
7848 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
7849 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
7850 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
7851 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
7852 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
7853 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
7857 SetLength(Rec.MatrixU, 20);
7858 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
7859 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
7860 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
7861 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
7862 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
7863 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
7864 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
7865 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
7866 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
7867 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
7868 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
7869 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
7870 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
7871 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
7872 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
7873 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
7874 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
7875 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
7876 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
7877 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
7879 SetLength(Rec.MatrixV, 20);
7880 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
7881 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
7882 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
7883 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
7884 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
7885 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
7886 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
7887 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
7888 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
7889 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
7890 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
7891 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
7892 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
7893 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
7894 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
7895 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
7896 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
7897 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
7898 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
7899 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
7904 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
7905 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
7907 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
7908 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
7910 SetLength(Rec.Heights, 0);
7923 procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
7928 if Height > 1 then begin
7929 // extract first line of the data
7930 Size := FormatGetImageSize(glBitmapPosition(Width), Format);
7931 GetMem(pTemp, Size);
7933 Move(Data^, pTemp^, Size);
7940 inherited SetDataPointer(pTemp, Format, Width);
7942 if FormatIsUncompressed(Format) then begin
7943 fUnmapFunc := FormatGetUnMapFunc(Format);
7944 fGetPixelFunc := GetPixel1DUnmap;
7949 procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
7954 Inc(pTemp, Pos.X * fPixelSize);
7956 fUnmapFunc(pTemp, Pixel);
7960 function TglBitmap1D.FlipHorz: Boolean;
7963 pTempDest, pDest, pSource: pByte;
7965 result := inherited FlipHorz;
7967 if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin
7970 GetMem(pDest, fRowSize);
7974 Inc(pTempDest, fRowSize);
7975 for Col := 0 to Width -1 do begin
7976 Move(pSource^, pTempDest^, fPixelSize);
7978 Inc(pSource, fPixelSize);
7979 Dec(pTempDest, fPixelSize);
7982 SetDataPointer(pDest, InternalFormat);
7992 procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
7995 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
7996 glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data)
8000 if BuildWithGlu then
8001 gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data)
8003 glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data);
8006 if (FreeDataAfterGenTexture) then
8011 procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean);
8013 BuildWithGlu, TexRec: Boolean;
8014 glFormat, glInternalFormat, glType: Cardinal;
8017 if Assigned(Data) then begin
8018 // Check Texture Size
8019 if (TestTextureSize) then begin
8020 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
8022 if (Width > TexSize) then
8023 raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
8025 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
8026 (Target = GL_TEXTURE_RECTANGLE_ARB);
8028 if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
8029 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
8034 SetupParameters(BuildWithGlu);
8035 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
8037 UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
8040 glAreTexturesResident(1, @fID, @fIsResident);
8045 procedure TglBitmap1D.AfterConstruction;
8049 Target := GL_TEXTURE_1D;
8053 { TglBitmapCubeMap }
8055 procedure TglBitmapCubeMap.AfterConstruction;
8059 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8060 raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8062 SetWrap; // set all to GL_CLAMP_TO_EDGE
8063 Target := GL_TEXTURE_CUBE_MAP;
8064 fGenMode := GL_REFLECTION_MAP;
8068 procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean);
8070 inherited Bind (EnableTextureUnit);
8072 if EnableTexCoordsGen then begin
8073 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8074 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8075 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8076 glEnable(GL_TEXTURE_GEN_S);
8077 glEnable(GL_TEXTURE_GEN_T);
8078 glEnable(GL_TEXTURE_GEN_R);
8083 procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean);
8085 glFormat, glInternalFormat, glType: Cardinal;
8086 BuildWithGlu: Boolean;
8089 // Check Texture Size
8090 if (TestTextureSize) then begin
8091 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8093 if ((Height > TexSize) or (Width > TexSize)) then
8094 raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8096 if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8097 raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8101 if ID = 0 then begin
8103 SetupParameters(BuildWithGlu);
8106 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
8108 UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu);
8112 procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean);
8114 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8118 procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen,
8119 DisableTextureUnit: Boolean);
8121 inherited Unbind (DisableTextureUnit);
8123 if DisableTexCoordsGen then begin
8124 glDisable(GL_TEXTURE_GEN_S);
8125 glDisable(GL_TEXTURE_GEN_T);
8126 glDisable(GL_TEXTURE_GEN_R);
8131 { TglBitmapNormalMap }
8134 TVec = Array[0..2] of Single;
8135 TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8137 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8138 TglBitmapNormalMapRec = record
8140 Func: TglBitmapNormalMapGetVectorFunc;
8144 procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8147 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8148 Vec[2] := - (Position.X + 0.5 - HalfSize);
8152 procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8154 Vec[0] := - HalfSize;
8155 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8156 Vec[2] := Position.X + 0.5 - HalfSize;
8160 procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8162 Vec[0] := Position.X + 0.5 - HalfSize;
8164 Vec[2] := Position.Y + 0.5 - HalfSize;
8168 procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8170 Vec[0] := Position.X + 0.5 - HalfSize;
8171 Vec[1] := - HalfSize;
8172 Vec[2] := - (Position.Y + 0.5 - HalfSize);
8176 procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8178 Vec[0] := Position.X + 0.5 - HalfSize;
8179 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8184 procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8186 Vec[0] := - (Position.X + 0.5 - HalfSize);
8187 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8188 Vec[2] := - HalfSize;
8192 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8197 with FuncRec do begin
8198 with PglBitmapNormalMapRec (CustomData)^ do begin
8199 Func(Vec, Position, HalfSize);
8202 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8203 if Len <> 0 then begin
8204 Vec[0] := Vec[0] * Len;
8205 Vec[1] := Vec[1] * Len;
8206 Vec[2] := Vec[2] * Len;
8209 // Scale Vector and AddVectro
8210 Vec[0] := Vec[0] * 0.5 + 0.5;
8211 Vec[1] := Vec[1] * 0.5 + 0.5;
8212 Vec[2] := Vec[2] * 0.5 + 0.5;
8216 Dest.Red := Round(Vec[0] * 255);
8217 Dest.Green := Round(Vec[1] * 255);
8218 Dest.Blue := Round(Vec[2] * 255);
8223 procedure TglBitmapNormalMap.AfterConstruction;
8227 fGenMode := GL_NORMAL_MAP;
8231 procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer;
8232 TestTextureSize: Boolean);
8234 Rec: TglBitmapNormalMapRec;
8235 SizeRec: TglBitmapPixelPosition;
8237 Rec.HalfSize := Size div 2;
8239 FreeDataAfterGenTexture := false;
8241 SizeRec.Fields := [ffX, ffY];
8246 Rec.Func := glBitmapNormalMapPosX;
8247 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8248 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize);
8251 Rec.Func := glBitmapNormalMapNegX;
8252 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8253 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize);
8256 Rec.Func := glBitmapNormalMapPosY;
8257 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8258 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize);
8261 Rec.Func := glBitmapNormalMapNegY;
8262 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8263 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize);
8266 Rec.Func := glBitmapNormalMapPosZ;
8267 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8268 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize);
8271 Rec.Func := glBitmapNormalMapNegZ;
8272 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8273 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize);
8278 glBitmapSetDefaultFormat(tfEmpty);
8279 glBitmapSetDefaultMipmap(mmMipmap);
8280 glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8281 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8283 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8284 glBitmapSetDefaultDeleteTextureOnFree (true);
8286 TFormatDescriptor.Init;
8288 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8289 OpenGLInitialized := false;
8290 InitOpenGLCS := TCriticalSection.Create;
8294 TFormatDescriptor.Finalize;
8296 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8297 FreeAndNil(InitOpenGLCS);