1 {***********************************************************
2 glBitmap by Steffen Xonna aka Lossy eX (2003-2008)
3 http://www.opengl24.de/index.php?cat=header&file=glbitmap
5 modified by Delphi OpenGL Community (http://delphigl.com/)
8 ------------------------------------------------------------
9 The contents of this file are used with permission, subject to
10 the Mozilla Public License Version 1.1 (the "License"); you may
11 not use this file except in compliance with the License. You may
12 obtain a copy of the License at
13 http://www.mozilla.org/MPL/MPL-1.1.html
14 ------------------------------------------------------------
16 ------------------------------------------------------------
19 - The define GLB_DELPHI dosn't check versions anymore. If you say you are using delphi
20 then it's your problem if that isn't true. This prevents the unit for incompatibility
21 with newer versions of Delphi.
22 - Problems with D2009+ resolved (Thanks noeska and all i forgot)
23 - GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson)
25 - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson)
26 - Additional Datapointer for functioninterface now has the name CustomData
28 - AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson)
29 - If you load an texture from an file the property Filename will be set to the name of the file
30 - Three new properties to attach custom data to the Texture objects
31 - CustomName (free for use string)
32 - CustomNameW (free for use widestring)
33 - CustomDataPointer (free for use pointer to attach other objects or complex structures)
35 - RLE TGAs loaded much faster
37 - fixed some problem with reading RLE TGAs.
39 - function clone now only copys data if it's assigned and now it also copies the ID
40 - it seems that lazarus dont like comments in comments.
42 - It's possible to set the id of the texture
43 - define GLB_NO_NATIVE_GL deactivated by default
45 - Now supports the following libraries
49 - Linux compatibillity via free pascal compatibility (delphi sources optional)
50 - BMPs now loaded manuel
52 - Property DataPtr now has the name Data
53 - Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR
54 - Unused Depth removed
55 - Function FreeData to freeing image data added
57 - ImageID flag of TGAs was ignored. (Thanks Zwoetzen)
59 - Function SetBorderColor implemented (only used by opengl if wrap is set to GL_CLAMP_TO_BORDER)
60 - Function AddAlphaFromValue implemented to use an fixed Value as Alphachannel
61 - Function ReadOpenGLExtension is now only intern
63 - pngimage now disabled by default like all other versions.
65 - Setting up an anisotropic filter of 0 isnt allowed by nvidia (Thanks Ogridi)
67 - Fixed some Problem with Delphi 5
68 - Now uses the newest version of pngimage. Makes saving pngs much easier.
70 - Property IsCompressed and Size removed. Not really supported by Spec (Thanks Ogridi)
72 - Internal Format ifDepth8 added
73 - function GrabScreen now supports all uncompressed formats
75 - AddAlphaFromglBitmap implemented
77 - LoadFromResource and LoadFromResourceId now needs an Instance and an ResourceType (for ID)
79 - Width, Height and Depth internal changed to TglBitmapPixelPosition.
80 property Width, Height, Depth are still existing and new property Dimension are avail
82 - Added native OpenGL Support. Breaking the dglOpenGL "barrier".
84 - Added function GrabScreen to class TglBitmap2D
86 - Added support to Save images
87 - Added function Clone to Clone Instance
89 - Functions now works with Cardinals for each channel. Up to 32 Bits per channel.
91 - Several speed optimizations
93 - Internal structure change. Loading of TGA, PNG and DDS improved.
94 Data, format and size will now set directly with SetDataPtr.
95 - AddFunc now works with all Types of Images and Formats
96 - Some Funtions moved to Baseclass TglBitmap
98 - Added Support to decompress DXT3 and DXT5 compressed Images.
99 - Added Mapping to convert data from one format into an other.
101 - Added method ConvertTo in Class TglBitmap2D. Method allows to convert every
102 supported Input format (supported by GetPixel) into any uncompresed Format
103 - Added Support to decompress DXT1 compressed Images.
104 - SwapColors replaced by ConvertTo
106 - Added Support for compressed DDSs
107 - Added new internal formats (DXT1, DXT3, DXT5)
109 - Parameter Components renamed to InternalFormat
111 - Some AllocMem replaced with GetMem (little speed change)
112 - better exception handling. Better protection from memory leaks.
114 - Added support for Direct Draw Surfaces (.DDS) (uncompressed images only)
115 - Added new internal formats (RGB8, RGBA8, RGBA4, RGB5A1, RGB10A2, R5G6B5)
117 - Added support for Grayscale textures
118 - Added internal formats (Alpha, Luminance, LuminanceAlpha, BGR8, BGRA8)
120 - Added support for GL_VERSION_2_0
121 - Added support for GL_EXT_texture_filter_anisotropic
123 - Function FillWithColor fills the Image with one Color
124 - Function LoadNormalMap added
126 - ToNormalMap allows to Create an NormalMap from the Alphachannel
127 - ToNormalMap now supports Sobel (nmSobel) function.
129 - support for RLE Compressed RGB TGAs added
131 - Class TglBitmapNormalMap added to support Normalmap generation
132 - Added function ToNormalMap in class TglBitmap2D to genereate normal maps from textures.
133 3 Filters are supported. (4 Samples, 3x3 and 5x5)
135 - Method LoadCubeMapClass removed
136 - LoadCubeMap returnvalue is now the Texture paramter. Such as LoadTextures
137 - virtual abstract method GenTexture in class TglBitmap now is protected
139 - now support DescriptionFlag in LoadTga. Allows vertical flipped images to be loaded as normal
141 - little enhancement for IsPowerOfTwo
142 - TglBitmap1D.GenTexture now tests NPOT Textures
144 - some little name changes. All properties or function with Texture in name are
145 now without texture in name. We have allways texture so we dosn't name it.
147 - GenTexture now tests if texture is NPOT and NPOT-Texture are supported or
148 TextureTarget is GL_TEXTURE_RECTANGLE. Else it raised an exception.
150 - added support for GL_ARB_texture_rectangle, GL_EXT_texture_rectangle and GL_NV_texture_rectangle
152 - Function Unbind added
153 - call of SetFilter or SetTextureWrap if TextureID exists results in setting properties to opengl texture.
155 - class TglBitmapCubeMap added (allows to Create Cubemaps)
157 - Added Support for PNG Images. (http://pngdelphi.sourceforge.net/)
158 To Enable png's use the define pngimage
160 - New Functioninterface added
161 - Function GetPixel added
163 - Property BuildMipMaps renamed to MipMap
165 - property Name removed.
166 - BuildMipMaps is now a set of 3 values. None, GluBuildMipmaps and SGIS_generate_mipmap
168 - property name added. Only used in glForms!
170 - property FreeDataAfterGenTexture is now available as default (default = true)
171 - BuildMipmaps now implemented in TglBitmap1D (i've forgotten it)
172 - function MoveMemory replaced with function Move (little speed change)
173 - several calculations stored in variables (little speed change)
175 - property BuildMipsMaps added (default = true)
176 if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps
177 - property FreeDataAfterGenTexture added (default = true)
178 if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated.
179 - parameter DisableOtherTextureUnits of Bind removed
180 - parameter FreeDataAfterGeneration of GenTextures removed
182 - TglBitmap dosn't delete data if class was destroyed (fixed)
184 - Bind now enables TextureUnits (by params)
185 - GenTextures can leave data (by param)
186 - LoadTextures now optimal
188 - Performance optimization in AddFunc
189 - procedure Bind moved to subclasses
190 - Added new Class TglBitmap1D to support real OpenGL 1D Textures
192 - Texturefilter and texturewrap now also as defaults
193 Minfilter = GL_LINEAR_MIPMAP_LINEAR
194 Magfilter = GL_LINEAR
195 Wrap(str) = GL_CLAMP_TO_EDGE
196 - Added new format tfCompressed to create a compressed texture.
197 - propertys IsCompressed, TextureSize and IsResident added
198 IsCompressed and TextureSize only contains data from level 0
200 - Added function AddFunc to add PerPixelEffects to Image
201 - LoadFromFunc now based on AddFunc
202 - Invert now based on AddFunc
203 - SwapColors now based on AddFunc
205 - Added function FlipHorz
207 - Added function LaodFromFunc to create images with function
208 - Added function FlipVert
209 - Added internal format RGB(A) if GL_EXT_bgra or OpenGL 1.2 isn't supported
211 - Added Alphafunctions to calculate alpha per function
212 - Added Alpha from ColorKey using alphafunctions
214 - First full functionally Version of glBitmap
215 - Support for 24Bit and 32Bit TGA Pictures added
217 - begin of programming
218 ***********************************************************}
221 {.$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
222 // Please uncomment the defines below to configure the glBitmap to your preferences.
223 // If you have configured the unit you can uncomment the warning above.
225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
226 // Preferences ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
227 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
228 // activate to enable build-in OpenGL support with statically linked methods
229 // use dglOpenGL.pas if not enabled
230 {.$DEFINE GLB_NATIVE_OGL_STATIC}
232 // activate to enable build-in OpenGL support with dynamically linked methods
233 // use dglOpenGL.pas if not enabled
234 {.$DEFINE GLB_NATIVE_OGL_DYNAMIC}
236 // activate to enable the support for SDL_surfaces
239 // activate to enable the support for TBitmap from Delphi (not lazarus)
240 {.$DEFINE GLB_DELPHI}
243 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
244 // activate to enable the support of SDL_image to load files. (READ ONLY)
245 // If you enable SDL_image all other libraries will be ignored!
246 {.$DEFINE GLB_SDL_IMAGE}
248 // activate to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/
249 // if you enable pngimage the libPNG will be ignored
250 {.$DEFINE GLB_PNGIMAGE}
252 // activate to use the libPNG http://www.libpng.org/
253 // You will need an aditional header.
254 // http://www.opengl24.de/index.php?cat=header&file=libpng
255 {$DEFINE GLB_LIB_PNG}
257 // if you enable delphi jpegs the libJPEG will be ignored
258 {.$DEFINE GLB_DELPHI_JPEG}
260 // activateto use the libJPEG http://www.ijg.org/
261 // You will need an aditional header.
262 // http://www.opengl24.de/index.php?cat=header&file=libjpeg
263 {.$DEFINE GLB_LIB_JPEG}
266 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
267 // PRIVATE: do not change anything! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
268 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
284 {$IF DEFINED(WIN32) or DEFINED(WIN64)}
286 {$ELSEIF DEFINED(LINUX)}
290 // native OpenGL Support
291 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) OR DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
292 {$DEFINE GLB_NATIVE_OGL}
295 // checking define combinations
297 {$IFDEF GLB_SDL_IMAGE}
299 {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
302 {$IFDEF GLB_PNGIMAGE}
303 {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
304 {$undef GLB_PNGIMAGE}
306 {$IFDEF GLB_DELPHI_JPEG}
307 {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
308 {$undef GLB_DELPHI_JPEG}
311 {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
314 {$IFDEF GLB_LIB_JPEG}
315 {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
316 {$undef GLB_LIB_JPEG}
319 {$DEFINE GLB_SUPPORT_PNG_READ}
320 {$DEFINE GLB_SUPPORT_JPEG_READ}
324 {$IFDEF GLB_PNGIMAGE}
326 {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'}
330 {$DEFINE GLB_SUPPORT_PNG_READ}
331 {$DEFINE GLB_SUPPORT_PNG_WRITE}
336 {$DEFINE GLB_SUPPORT_PNG_READ}
337 {$DEFINE GLB_SUPPORT_PNG_WRITE}
341 {$IFDEF GLB_DELPHI_JPEG}
342 {$IFDEF GLB_LIB_JPEG}
343 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
344 {$undef GLB_LIB_JPEG}
347 {$DEFINE GLB_SUPPORT_JPEG_READ}
348 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
352 {$IFDEF GLB_LIB_JPEG}
353 {$DEFINE GLB_SUPPORT_JPEG_READ}
354 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
358 {$IF DEFINED(GLB_NATIVE_OGL_STATIC) AND DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
359 {$MESSAGE warn 'GLB_NATIVE_OGL_STATIC will be ignored because you enabled GLB_NATIVE_OGL_DYNAMIC'}
373 {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF}
374 {$IF DEFINED(GLB_WIN) AND
375 DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND}
377 {$IFDEF GLB_SDL} SDL, {$ENDIF}
378 {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF}
380 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
382 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
383 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
385 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
386 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
396 TRGBQuad = packed record
404 {$IFDEF GLB_NATIVE_OGL}
410 GL_EXTENSIONS = $1F03;
412 GL_TEXTURE_1D = $0DE0;
413 GL_TEXTURE_2D = $0DE1;
414 GL_TEXTURE_RECTANGLE = $84F5;
416 GL_TEXTURE_WIDTH = $1000;
417 GL_TEXTURE_HEIGHT = $1001;
418 GL_TEXTURE_INTERNAL_FORMAT = $1003;
426 GL_LUMINANCE = $1909;
427 GL_LUMINANCE4 = $803F;
428 GL_LUMINANCE8 = $8040;
429 GL_LUMINANCE12 = $8041;
430 GL_LUMINANCE16 = $8042;
432 GL_LUMINANCE_ALPHA = $190A;
433 GL_LUMINANCE4_ALPHA4 = $8043;
434 GL_LUMINANCE6_ALPHA2 = $8044;
435 GL_LUMINANCE8_ALPHA8 = $8045;
436 GL_LUMINANCE12_ALPHA4 = $8046;
437 GL_LUMINANCE12_ALPHA12 = $8047;
438 GL_LUMINANCE16_ALPHA16 = $8048;
461 GL_DEPTH_COMPONENT = $1902;
462 GL_DEPTH_COMPONENT16 = $81A5;
463 GL_DEPTH_COMPONENT24 = $81A6;
464 GL_DEPTH_COMPONENT32 = $81A7;
466 GL_COMPRESSED_RGB = $84ED;
467 GL_COMPRESSED_RGBA = $84EE;
468 GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
469 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
470 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
471 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
473 GL_UNSIGNED_BYTE = $1401;
474 GL_UNSIGNED_BYTE_3_3_2 = $8032;
475 GL_UNSIGNED_BYTE_2_3_3_REV = $8362;
477 GL_UNSIGNED_SHORT = $1403;
478 GL_UNSIGNED_SHORT_5_6_5 = $8363;
479 GL_UNSIGNED_SHORT_4_4_4_4 = $8033;
480 GL_UNSIGNED_SHORT_5_5_5_1 = $8034;
481 GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
482 GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
483 GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
485 GL_UNSIGNED_INT = $1405;
486 GL_UNSIGNED_INT_8_8_8_8 = $8035;
487 GL_UNSIGNED_INT_10_10_10_2 = $8036;
488 GL_UNSIGNED_INT_8_8_8_8_REV = $8367;
489 GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
492 GL_TEXTURE_MAG_FILTER = $2800;
493 GL_TEXTURE_MIN_FILTER = $2801;
495 GL_NEAREST_MIPMAP_NEAREST = $2700;
496 GL_NEAREST_MIPMAP_LINEAR = $2702;
498 GL_LINEAR_MIPMAP_NEAREST = $2701;
499 GL_LINEAR_MIPMAP_LINEAR = $2703;
502 GL_TEXTURE_WRAP_S = $2802;
503 GL_TEXTURE_WRAP_T = $2803;
504 GL_TEXTURE_WRAP_R = $8072;
507 GL_CLAMP_TO_EDGE = $812F;
508 GL_CLAMP_TO_BORDER = $812D;
509 GL_MIRRORED_REPEAT = $8370;
512 GL_GENERATE_MIPMAP = $8191;
513 GL_TEXTURE_BORDER_COLOR = $1004;
514 GL_MAX_TEXTURE_SIZE = $0D33;
515 GL_PACK_ALIGNMENT = $0D05;
516 GL_UNPACK_ALIGNMENT = $0CF5;
518 GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
519 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
522 libglu = 'libGLU.so.1';
523 libopengl = 'libGL.so.1';
525 libglu = 'glu32.dll';
526 libopengl = 'opengl32.dll';
530 GLboolean = BYTEBOOL;
538 PGLboolean = ^GLboolean;
543 TglCompressedTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
544 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}
545 TglGetCompressedTexImage = procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
547 {$IF DEFINED(GLB_NATIVE_OGL_DYNAMIC)}
548 TglEnable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
549 TglDisable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
551 TglGetString = function(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
552 TglGetIntegerv = procedure(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
554 TglTexParameteri = procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
555 TglTexParameterfv = procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
556 TglGetTexParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
557 TglGetTexParameterfv = procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
558 TglGetTexLevelParameteriv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
559 TglGetTexLevelParameterfv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
561 TglGenTextures = procedure(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
562 TglBindTexture = procedure(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
563 TglDeleteTextures = procedure(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
565 TglAreTexturesResident = function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
566 TglReadPixels = procedure(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
567 TglPixelStorei = procedure(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
569 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}
570 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}
571 TglGetTexImage = procedure(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
573 TgluBuild1DMipmaps = function(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
574 TgluBuild2DMipmaps = function(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}
577 TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl;
579 TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall;
582 {$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)}
583 procedure glEnable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
584 procedure glDisable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
586 function glGetString(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
587 procedure glGetIntegerv(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
589 procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
590 procedure glTexParameterfv(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
591 procedure glGetTexParameteriv(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
592 procedure glGetTexParameterfv(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
593 procedure glGetTexLevelParameteriv(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
594 procedure glGetTexLevelParameterfv(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
596 procedure glGenTextures(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
597 procedure glBindTexture(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
598 procedure glDeleteTextures(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
600 function glAreTexturesResident(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
601 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;
602 procedure glPixelStorei(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
604 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;
605 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;
606 procedure glGetTexImage(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl;
608 function gluBuild1DMipmaps(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
609 function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu;
618 GL_SGIS_generate_mipmap,
620 GL_ARB_texture_border_clamp,
621 GL_ARB_texture_mirrored_repeat,
622 GL_ARB_texture_rectangle,
623 GL_ARB_texture_non_power_of_two,
625 GL_IBM_texture_mirrored_repeat,
627 GL_NV_texture_rectangle,
629 GL_EXT_texture_edge_clamp,
630 GL_EXT_texture_rectangle,
631 GL_EXT_texture_filter_anisotropic: Boolean;
633 glCompressedTexImage1D: TglCompressedTexImage1D;
634 glCompressedTexImage2D: TglCompressedTexImage2D;
635 glGetCompressedTexImage: TglGetCompressedTexImage;
637 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
639 glDisable: TglDisable;
641 glGetString: TglGetString;
642 glGetIntegerv: TglGetIntegerv;
644 glTexParameteri: TglTexParameteri;
645 glTexParameterfv: TglTexParameterfv;
646 glGetTexParameteriv: TglGetTexParameteriv;
647 glGetTexParameterfv: TglGetTexParameterfv;
648 glGetTexLevelParameteriv: TglGetTexLevelParameteriv;
649 glGetTexLevelParameterfv: TglGetTexLevelParameterfv;
651 glGenTextures: TglGenTextures;
652 glBindTexture: TglBindTexture;
653 glDeleteTextures: TglDeleteTextures;
655 glAreTexturesResident: TglAreTexturesResident;
656 glReadPixels: TglReadPixels;
657 glPixelStorei: TglPixelStorei;
659 glTexImage1D: TglTexImage1D;
660 glTexImage2D: TglTexImage2D;
661 glGetTexImage: TglGetTexImage;
663 gluBuild1DMipmaps: TgluBuild1DMipmaps;
664 gluBuild2DMipmaps: TgluBuild2DMipmaps;
666 {$IF DEFINED(GLB_WIN)}
667 wglGetProcAddress: TwglGetProcAddress;
668 {$ELSEIF DEFINED(GLB_LINUX)}
669 glXGetProcAddress: TglXGetProcAddress;
670 glXGetProcAddressARB: TglXGetProcAddressARB;
684 ////////////////////////////////////////////////////////////////////////////////////////////////////
686 tfEmpty = 0, //must be smallest value!
702 tfLuminance12Alpha12,
703 tfLuminance16Alpha16,
747 TglBitmapFileType = (
748 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
749 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
753 TglBitmapFileTypes = set of TglBitmapFileType;
760 TglBitmapNormalMapFunc = (
766 ////////////////////////////////////////////////////////////////////////////////////////////////////
767 EglBitmapException = class(Exception);
768 EglBitmapSizeToLargeException = class(EglBitmapException);
769 EglBitmapNonPowerOfTwoException = class(EglBitmapException);
770 EglBitmapUnsupportedFormat = class(EglBitmapException)
771 constructor Create(const aFormat: TglBitmapFormat);
774 ////////////////////////////////////////////////////////////////////////////////////////////////////
775 TglBitmapColorRec = packed record
777 0: (r, g, b, a: Cardinal);
778 1: (arr: array[0..3] of Cardinal);
781 TglBitmapPixelData = packed record
782 Data, Range: TglBitmapColorRec;
783 Format: TglBitmapFormat;
785 PglBitmapPixelData = ^TglBitmapPixelData;
787 ////////////////////////////////////////////////////////////////////////////////////////////////////
788 TglBitmapPixelPositionFields = set of (ffX, ffY);
789 TglBitmapPixelPosition = record
790 Fields : TglBitmapPixelPositionFields;
795 ////////////////////////////////////////////////////////////////////////////////////////////////////
797 TglBitmapFunctionRec = record
799 Size: TglBitmapPixelPosition;
800 Position: TglBitmapPixelPosition;
801 Source: TglBitmapPixelData;
802 Dest: TglBitmapPixelData;
805 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
807 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
812 fAnisotropic: Integer;
813 fDeleteTextureOnFree: Boolean;
814 fFreeDataAfterGenTexture: Boolean;
816 fIsResident: Boolean;
817 fBorderColor: array[0..3] of Single;
819 fDimension: TglBitmapPixelPosition;
820 fMipMap: TglBitmapMipMap;
821 fFormat: TglBitmapFormat;
828 fFilterMin: Cardinal;
829 fFilterMag: Cardinal;
839 fCustomNameW: WideString;
840 fCustomData: Pointer;
843 function GetWidth: Integer; virtual;
844 function GetHeight: Integer; virtual;
846 function GetFileWidth: Integer; virtual;
847 function GetFileHeight: Integer; virtual;
850 procedure SetCustomData(const aValue: Pointer);
851 procedure SetCustomName(const aValue: String);
852 procedure SetCustomNameW(const aValue: WideString);
853 procedure SetDeleteTextureOnFree(const aValue: Boolean);
854 procedure SetFormat(const aValue: TglBitmapFormat);
855 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
856 procedure SetID(const aValue: Cardinal);
857 procedure SetMipMap(const aValue: TglBitmapMipMap);
858 procedure SetTarget(const aValue: Cardinal);
859 procedure SetAnisotropic(const aValue: Integer);
862 procedure SetupParameters(out aBuildWithGlu: Boolean);
863 procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
864 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual;
865 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
867 function FlipHorz: Boolean; virtual;
868 function FlipVert: Boolean; virtual;
870 property Width: Integer read GetWidth;
871 property Height: Integer read GetHeight;
873 property FileWidth: Integer read GetFileWidth;
874 property FileHeight: Integer read GetFileHeight;
877 property ID: Cardinal read fID write SetID;
878 property Target: Cardinal read fTarget write SetTarget;
879 property Format: TglBitmapFormat read fFormat write SetFormat;
880 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
881 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
883 property Filename: String read fFilename;
884 property CustomName: String read fCustomName write SetCustomName;
885 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
886 property CustomData: Pointer read fCustomData write SetCustomData;
888 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
889 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
891 property Dimension: TglBitmapPixelPosition read fDimension;
892 property Data: PByte read fData;
893 property IsResident: Boolean read fIsResident;
895 procedure AfterConstruction; override;
896 procedure BeforeDestruction; override;
899 procedure LoadFromFile(const aFilename: String);
900 procedure LoadFromStream(const aStream: TStream); virtual;
901 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
902 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil);
904 procedure LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
905 procedure LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
909 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
910 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
913 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload;
914 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
915 const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload;
919 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
920 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
921 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
922 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
923 const aArgs: Pointer = nil): Boolean;
927 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
928 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
929 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
930 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
931 const aArgs: Pointer = nil): Boolean;
932 function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil;
933 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
934 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
935 const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
938 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual;
939 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
940 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
941 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
943 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
944 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
945 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
947 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
948 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
949 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
951 function RemoveAlpha: Boolean; virtual;
954 function Clone: TglBitmap;
955 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
956 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
957 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
961 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
962 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
963 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
966 procedure SetFilter(const aMin, aMag: Cardinal);
968 const S: Cardinal = GL_CLAMP_TO_EDGE;
969 const T: Cardinal = GL_CLAMP_TO_EDGE;
970 const R: Cardinal = GL_CLAMP_TO_EDGE);
972 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
973 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
976 constructor Create; overload;
977 constructor Create(const aFileName: String); overload;
978 constructor Create(const aStream: TStream); overload;
979 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload;
980 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload;
982 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
983 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
986 {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF}
987 {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF}
989 {$IFDEF GLB_SUPPORT_JPEG_READ} function LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF}
990 {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF}
992 function LoadBMP(const aStream: TStream): Boolean; virtual;
993 procedure SaveBMP(const aStream: TStream); virtual;
995 function LoadTGA(const aStream: TStream): Boolean; virtual;
996 procedure SaveTGA(const aStream: TStream); virtual;
998 function LoadDDS(const aStream: TStream): Boolean; virtual;
999 procedure SaveDDS(const aStream: TStream); virtual;
1002 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1003 TglBitmap2D = class(TglBitmap)
1005 // Bildeinstellungen
1006 fLines: array of PByte;
1009 procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
1010 procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1011 procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1012 procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1013 procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1014 procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
1017 function GetScanline(const aIndex: Integer): Pointer;
1018 procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
1019 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
1020 procedure UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
1024 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
1026 procedure AfterConstruction; override;
1028 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
1029 procedure GetDataFromTexture;
1030 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
1032 function FlipHorz: Boolean; override;
1033 function FlipVert: Boolean; override;
1035 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
1036 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1040 TglBitmapCubeMap = class(TglBitmap2D)
1045 procedure GenTexture(TestTextureSize: Boolean = true); reintroduce;
1047 procedure AfterConstruction; override;
1049 procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true);
1051 procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = true); reintroduce; virtual;
1052 procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = true); reintroduce; virtual;
1056 TglBitmapNormalMap = class(TglBitmapCubeMap)
1058 procedure AfterConstruction; override;
1060 procedure GenerateNormalMap(Size: Integer = 32; TestTextureSize: Boolean = true);
1064 TglBitmap1D = class(TglBitmap)
1066 procedure GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1068 procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override;
1069 procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
1074 procedure AfterConstruction; override;
1077 function FlipHorz: Boolean; override;
1080 procedure GenTexture(TestTextureSize: Boolean = true); override;
1085 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1087 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1088 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1089 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1090 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1091 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1092 procedure glBitmapSetDefaultWrap(
1093 const S: Cardinal = GL_CLAMP_TO_EDGE;
1094 const T: Cardinal = GL_CLAMP_TO_EDGE;
1095 const R: Cardinal = GL_CLAMP_TO_EDGE);
1097 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1098 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1099 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1100 function glBitmapGetDefaultFormat: TglBitmapFormat;
1101 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1102 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1104 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1105 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1106 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1109 glBitmapDefaultDeleteTextureOnFree: Boolean;
1110 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1111 glBitmapDefaultFormat: TglBitmapFormat;
1112 glBitmapDefaultMipmap: TglBitmapMipMap;
1113 glBitmapDefaultFilterMin: Cardinal;
1114 glBitmapDefaultFilterMag: Cardinal;
1115 glBitmapDefaultWrapS: Cardinal;
1116 glBitmapDefaultWrapT: Cardinal;
1117 glBitmapDefaultWrapR: Cardinal;
1120 function CreateGrayPalette: HPALETTE;
1127 function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
1128 function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
1129 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
1130 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
1131 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
1135 Math, syncobjs, typinfo;
1138 ////////////////////////////////////////////////////////////////////////////////////////////////////
1139 TShiftRec = packed record
1141 0: (r, g, b, a: Byte);
1142 1: (arr: array[0..3] of Byte);
1145 TFormatDescriptor = class(TObject)
1147 function GetRedMask: QWord;
1148 function GetGreenMask: QWord;
1149 function GetBlueMask: QWord;
1150 function GetAlphaMask: QWord;
1152 fFormat: TglBitmapFormat;
1153 fWithAlpha: TglBitmapFormat;
1154 fWithoutAlpha: TglBitmapFormat;
1155 fRGBInverted: TglBitmapFormat;
1156 fUncompressed: TglBitmapFormat;
1158 fIsCompressed: Boolean;
1160 fRange: TglBitmapColorRec;
1163 fglFormat: Cardinal;
1164 fglInternalFormat: Cardinal;
1165 fglDataFormat: Cardinal;
1167 function GetComponents: Integer; virtual;
1169 property Format: TglBitmapFormat read fFormat;
1170 property WithAlpha: TglBitmapFormat read fWithAlpha;
1171 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1172 property RGBInverted: TglBitmapFormat read fRGBInverted;
1173 property Components: Integer read GetComponents;
1174 property PixelSize: Single read fPixelSize;
1175 property IsCompressed: Boolean read fIsCompressed;
1177 property glFormat: Cardinal read fglFormat;
1178 property glInternalFormat: Cardinal read fglInternalFormat;
1179 property glDataFormat: Cardinal read fglDataFormat;
1181 property Range: TglBitmapColorRec read fRange;
1182 property Shift: TShiftRec read fShift;
1184 property RedMask: QWord read GetRedMask;
1185 property GreenMask: QWord read GetGreenMask;
1186 property BlueMask: QWord read GetBlueMask;
1187 property AlphaMask: QWord read GetAlphaMask;
1189 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1190 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1192 function GetSize(const aSize: TglBitmapPixelPosition): Integer; virtual; overload;
1193 function GetSize(const aWidth, aHeight: Integer): Integer; virtual; overload;
1195 function CreateMappingData: Pointer; virtual;
1196 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1198 function IsEmpty: Boolean; virtual;
1199 function HasAlpha: Boolean; virtual;
1200 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual;
1202 procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
1204 constructor Create; virtual;
1206 class procedure Init;
1207 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1208 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1209 class procedure Clear;
1210 class procedure Finalize;
1212 TFormatDescriptorClass = class of TFormatDescriptor;
1214 TfdEmpty = class(TFormatDescriptor);
1216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1217 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1218 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1219 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1220 constructor Create; override;
1223 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1224 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1225 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1226 constructor Create; override;
1229 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1230 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1231 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1232 constructor Create; override;
1235 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1236 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1237 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1238 constructor Create; override;
1241 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1242 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1243 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1244 constructor Create; override;
1247 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1248 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1249 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1250 constructor Create; override;
1253 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1254 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1255 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1256 constructor Create; override;
1259 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1260 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1261 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1262 constructor Create; override;
1265 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1266 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1267 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1268 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1269 constructor Create; override;
1272 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1273 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1274 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1275 constructor Create; override;
1278 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1279 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1280 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1281 constructor Create; override;
1284 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1285 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1286 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1287 constructor Create; override;
1290 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1291 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1292 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1293 constructor Create; override;
1296 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1297 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1298 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1299 constructor Create; override;
1302 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1303 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1304 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1305 constructor Create; override;
1308 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1309 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1310 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1311 constructor Create; override;
1314 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1315 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1316 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1317 constructor Create; override;
1320 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1321 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1322 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1323 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1324 constructor Create; override;
1327 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1328 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1329 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1330 constructor Create; override;
1333 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1334 TfdAlpha4 = class(TfdAlpha_UB1)
1335 constructor Create; override;
1338 TfdAlpha8 = class(TfdAlpha_UB1)
1339 constructor Create; override;
1342 TfdAlpha12 = class(TfdAlpha_US1)
1343 constructor Create; override;
1346 TfdAlpha16 = class(TfdAlpha_US1)
1347 constructor Create; override;
1350 TfdLuminance4 = class(TfdLuminance_UB1)
1351 constructor Create; override;
1354 TfdLuminance8 = class(TfdLuminance_UB1)
1355 constructor Create; override;
1358 TfdLuminance12 = class(TfdLuminance_US1)
1359 constructor Create; override;
1362 TfdLuminance16 = class(TfdLuminance_US1)
1363 constructor Create; override;
1366 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1367 constructor Create; override;
1370 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1371 constructor Create; override;
1374 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1375 constructor Create; override;
1378 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1379 constructor Create; override;
1382 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1383 constructor Create; override;
1386 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1387 constructor Create; override;
1390 TfdR3G3B2 = class(TfdUniversal_UB1)
1391 constructor Create; override;
1394 TfdRGB4 = class(TfdUniversal_US1)
1395 constructor Create; override;
1398 TfdR5G6B5 = class(TfdUniversal_US1)
1399 constructor Create; override;
1402 TfdRGB5 = class(TfdUniversal_US1)
1403 constructor Create; override;
1406 TfdRGB8 = class(TfdRGB_UB3)
1407 constructor Create; override;
1410 TfdRGB10 = class(TfdUniversal_UI1)
1411 constructor Create; override;
1414 TfdRGB12 = class(TfdRGB_US3)
1415 constructor Create; override;
1418 TfdRGB16 = class(TfdRGB_US3)
1419 constructor Create; override;
1422 TfdRGBA2 = class(TfdRGBA_UB4)
1423 constructor Create; override;
1426 TfdRGBA4 = class(TfdUniversal_US1)
1427 constructor Create; override;
1430 TfdRGB5A1 = class(TfdUniversal_US1)
1431 constructor Create; override;
1434 TfdRGBA8 = class(TfdRGBA_UB4)
1435 constructor Create; override;
1438 TfdRGB10A2 = class(TfdUniversal_UI1)
1439 constructor Create; override;
1442 TfdRGBA12 = class(TfdRGBA_US4)
1443 constructor Create; override;
1446 TfdRGBA16 = class(TfdRGBA_US4)
1447 constructor Create; override;
1450 TfdBGR4 = class(TfdUniversal_US1)
1451 constructor Create; override;
1454 TfdB5G6R5 = class(TfdUniversal_US1)
1455 constructor Create; override;
1458 TfdBGR5 = class(TfdUniversal_US1)
1459 constructor Create; override;
1462 TfdBGR8 = class(TfdBGR_UB3)
1463 constructor Create; override;
1466 TfdBGR10 = class(TfdUniversal_UI1)
1467 constructor Create; override;
1470 TfdBGR12 = class(TfdBGR_US3)
1471 constructor Create; override;
1474 TfdBGR16 = class(TfdBGR_US3)
1475 constructor Create; override;
1478 TfdBGRA2 = class(TfdBGRA_UB4)
1479 constructor Create; override;
1482 TfdBGRA4 = class(TfdUniversal_US1)
1483 constructor Create; override;
1486 TfdBGR5A1 = class(TfdUniversal_US1)
1487 constructor Create; override;
1490 TfdBGRA8 = class(TfdBGRA_UB4)
1491 constructor Create; override;
1494 TfdBGR10A2 = class(TfdUniversal_UI1)
1495 constructor Create; override;
1498 TfdBGRA12 = class(TfdBGRA_US4)
1499 constructor Create; override;
1502 TfdBGRA16 = class(TfdBGRA_US4)
1503 constructor Create; override;
1506 TfdDepth16 = class(TfdDepth_US1)
1507 constructor Create; override;
1510 TfdDepth24 = class(TfdDepth_UI1)
1511 constructor Create; override;
1514 TfdDepth32 = class(TfdDepth_UI1)
1515 constructor Create; override;
1518 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1519 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1520 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1521 constructor Create; override;
1524 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1525 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1526 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1527 constructor Create; override;
1530 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1531 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1532 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1533 constructor Create; override;
1536 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1537 TbmpBitfieldFormat = class(TFormatDescriptor)
1539 procedure SetRedMask (const aValue: QWord);
1540 procedure SetGreenMask(const aValue: QWord);
1541 procedure SetBlueMask (const aValue: QWord);
1542 procedure SetAlphaMask(const aValue: QWord);
1544 procedure Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte);
1546 property RedMask: QWord read GetRedMask write SetRedMask;
1547 property GreenMask: QWord read GetGreenMask write SetGreenMask;
1548 property BlueMask: QWord read GetBlueMask write SetBlueMask;
1549 property AlphaMask: QWord read GetAlphaMask write SetAlphaMask;
1551 property PixelSize: Single read fPixelSize write fPixelSize;
1553 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1554 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1557 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1558 TbmpColorTableEnty = packed record
1561 TbmpColorTable = array of TbmpColorTableEnty;
1562 TbmpColorTableFormat = class(TFormatDescriptor)
1564 fColorTable: TbmpColorTable;
1566 property PixelSize: Single read fPixelSize write fPixelSize;
1567 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1568 property Range: TglBitmapColorRec read fRange write fRange;
1569 property Shift: TShiftRec read fShift write fShift;
1570 property Format: TglBitmapFormat read fFormat write fFormat;
1572 procedure CreateColorTable;
1574 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1575 procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1576 destructor Destroy; override;
1580 LUMINANCE_WEIGHT_R = 0.30;
1581 LUMINANCE_WEIGHT_G = 0.59;
1582 LUMINANCE_WEIGHT_B = 0.11;
1584 ALPHA_WEIGHT_R = 0.30;
1585 ALPHA_WEIGHT_G = 0.59;
1586 ALPHA_WEIGHT_B = 0.11;
1588 DEPTH_WEIGHT_R = 0.333333333;
1589 DEPTH_WEIGHT_G = 0.333333333;
1590 DEPTH_WEIGHT_B = 0.333333333;
1592 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1594 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1607 TfdLuminance4Alpha4,
1608 TfdLuminance6Alpha2,
1609 TfdLuminance8Alpha8,
1610 TfdLuminance12Alpha4,
1611 TfdLuminance12Alpha12,
1612 TfdLuminance16Alpha16,
1657 FormatDescriptorCS: TCriticalSection;
1658 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1660 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1661 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
1663 inherited Create(GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
1666 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1667 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1669 result.Fields := [];
1672 result.Fields := result.Fields + [ffX];
1674 result.Fields := result.Fields + [ffY];
1676 result.X := Max(0, X);
1677 result.Y := Max(0, Y);
1680 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1681 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1689 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1690 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1695 for i := 0 to high(r1.arr) do
1696 if (r1.arr[i] <> r2.arr[i]) then
1701 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1702 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1710 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1711 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1720 tfR3G3B2, tfLuminance8,
1723 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1724 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1730 tfRGB10, tfRGB10A2, tfRGBA8,
1731 tfBGR10, tfBGR10A2, tfBGRA8]) then
1732 result := result + [ftBMP];
1736 tfLuminance8, tfAlpha8,
1739 tfLuminance16, tfLuminance8Alpha8,
1740 tfRGB5, tfRGB5A1, tfRGBA4,
1741 tfBGR5, tfBGR5A1, tfBGRA4,
1747 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1748 result := result + [ftTGA];
1752 tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2,
1753 tfR3G3B2, tfRGBA2, tfBGRA2,
1756 tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4,
1757 tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1,
1758 tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1,
1764 tfLuminance16Alpha16,
1769 tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then
1770 result := result + [ftDDS];
1772 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1774 tfAlpha8, tfLuminance8, tfLuminance8Alpha8,
1776 tfBGR8, tfBGRA8] then
1777 result := result + [ftPNG];
1781 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1783 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1784 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1785 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1786 tfDepth16, tfDepth24, tfDepth32]
1788 result := result + [ftJPEG];
1793 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1794 function IsPowerOfTwo(aNumber: Integer): Boolean;
1796 while (aNumber and 1) = 0 do
1797 aNumber := aNumber shr 1;
1798 result := aNumber = 1;
1801 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1802 function GetTopMostBit(aBitSet: QWord): Integer;
1805 while aBitSet > 0 do begin
1807 aBitSet := aBitSet shr 1;
1811 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1812 function CountSetBits(aBitSet: QWord): Integer;
1815 while aBitSet > 0 do begin
1816 if (aBitSet and 1) = 1 then
1818 aBitSet := aBitSet shr 1;
1822 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1823 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1826 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1827 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1828 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1831 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1832 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1835 DEPTH_WEIGHT_R * aPixel.Data.r +
1836 DEPTH_WEIGHT_G * aPixel.Data.g +
1837 DEPTH_WEIGHT_B * aPixel.Data.b);
1840 {$IFDEF GLB_NATIVE_OGL}
1841 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1842 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1843 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1845 GL_LibHandle: Pointer = nil;
1847 function glbGetProcAddress(aProcName: PChar; aLibHandle: Pointer = nil): Pointer;
1851 if not Assigned(aLibHandle) then
1852 aLibHandle := GL_LibHandle;
1854 {$IF DEFINED(GLB_WIN)}
1855 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1856 if Assigned(result) then
1859 if Assigned(wglGetProcAddress) then
1860 result := wglGetProcAddress(aProcName);
1861 {$ELSEIF DEFINED(GLB_LINUX)}
1862 if Assigned(glXGetProcAddress) then begin
1863 result := glXGetProcAddress(aProcName);
1864 if Assigned(result) then
1868 if Assigned(glXGetProcAddressARB) then begin
1869 result := glXGetProcAddressARB(aProcName);
1870 if Assigned(result) then
1874 result := dlsym(aLibHandle, aProcName);
1876 if not Assigned(result) then
1877 raise EglBitmapException.Create('unable to load procedure form library: ' + aProcName);
1880 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1882 GLU_LibHandle: Pointer = nil;
1883 OpenGLInitialized: Boolean;
1884 InitOpenGLCS: TCriticalSection;
1886 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1887 procedure glbInitOpenGL;
1889 ////////////////////////////////////////////////////////////////////////////////
1890 function glbLoadLibrary(const aName: PChar): Pointer;
1892 {$IF DEFINED(GLB_WIN)}
1893 result := {%H-}Pointer(LoadLibrary(aName));
1894 {$ELSEIF DEFINED(GLB_LINUX)}
1895 result := dlopen(Name, RTLD_LAZY);
1901 ////////////////////////////////////////////////////////////////////////////////
1902 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
1905 if not Assigned(aLibHandle) then
1908 {$IF DEFINED(GLB_WIN)}
1909 Result := FreeLibrary({%H-}HINST(aLibHandle));
1910 {$ELSEIF DEFINED(GLB_LINUX)}
1911 Result := dlclose(aLibHandle) = 0;
1916 if Assigned(GL_LibHandle) then
1917 glbFreeLibrary(GL_LibHandle);
1919 if Assigned(GLU_LibHandle) then
1920 glbFreeLibrary(GLU_LibHandle);
1922 GL_LibHandle := glbLoadLibrary(libopengl);
1923 if not Assigned(GL_LibHandle) then
1924 raise EglBitmapException.Create('unable to load library: ' + libopengl);
1926 GLU_LibHandle := glbLoadLibrary(libglu);
1927 if not Assigned(GLU_LibHandle) then
1928 raise EglBitmapException.Create('unable to load library: ' + libglu);
1931 {$IF DEFINED(GLB_WIN)}
1932 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
1933 {$ELSEIF DEFINED(GLB_LINUX)}
1934 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
1935 glXGetProcAddressARB := dglGetProcAddress('glXGetProcAddressARB');
1938 glEnable := glbGetProcAddress('glEnable');
1939 glDisable := glbGetProcAddress('glDisable');
1940 glGetString := glbGetProcAddress('glGetString');
1941 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
1942 glTexParameteri := glbGetProcAddress('glTexParameteri');
1943 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
1944 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
1945 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
1946 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
1947 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
1948 glGenTextures := glbGetProcAddress('glGenTextures');
1949 glBindTexture := glbGetProcAddress('glBindTexture');
1950 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
1951 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
1952 glReadPixels := glbGetProcAddress('glReadPixels');
1953 glPixelStorei := glbGetProcAddress('glPixelStorei');
1954 glTexImage1D := glbGetProcAddress('glTexImage1D');
1955 glTexImage2D := glbGetProcAddress('glTexImage2D');
1956 glGetTexImage := glbGetProcAddress('glGetTexImage');
1958 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
1959 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
1961 glbFreeLibrary(GL_LibHandle);
1962 glbFreeLibrary(GLU_LibHandle);
1967 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1968 procedure glbReadOpenGLExtensions;
1974 MajorVersion, MinorVersion: Integer;
1976 ///////////////////////////////////////////////////////////////////////////////////////////
1977 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
1984 Separator := Pos(AnsiString('.'), aBuffer);
1985 if (Separator > 1) and (Separator < Length(aBuffer)) and
1986 (aBuffer[Separator - 1] in ['0'..'9']) and
1987 (aBuffer[Separator + 1] in ['0'..'9']) then begin
1990 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
1993 Delete(aBuffer, 1, Separator);
1994 Separator := Pos(AnsiString('.'), aBuffer) + 1;
1996 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
1999 Delete(aBuffer, Separator, 255);
2000 Separator := Pos(AnsiString('.'), aBuffer);
2002 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
2003 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2007 ///////////////////////////////////////////////////////////////////////////////////////////
2008 function CheckExtension(const Extension: AnsiString): Boolean;
2012 ExtPos := Pos(Extension, Buffer);
2013 result := ExtPos > 0;
2015 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2019 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2022 if not OpenGLInitialized then begin
2024 OpenGLInitialized := true;
2032 Context := wglGetCurrentContext;
2033 if (Context <> gLastContext) then begin
2034 gLastContext := Context;
2038 Buffer := glGetString(GL_VERSION);
2039 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2041 GL_VERSION_1_2 := false;
2042 GL_VERSION_1_3 := false;
2043 GL_VERSION_1_4 := false;
2044 GL_VERSION_2_0 := false;
2045 if MajorVersion = 1 then begin
2046 if MinorVersion >= 2 then
2047 GL_VERSION_1_2 := true;
2049 if MinorVersion >= 3 then
2050 GL_VERSION_1_3 := true;
2052 if MinorVersion >= 4 then
2053 GL_VERSION_1_4 := true;
2054 end else if MajorVersion >= 2 then begin
2055 GL_VERSION_1_2 := true;
2056 GL_VERSION_1_3 := true;
2057 GL_VERSION_1_4 := true;
2058 GL_VERSION_2_0 := true;
2062 Buffer := glGetString(GL_EXTENSIONS);
2063 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2064 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2065 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2066 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2067 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2068 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2069 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2070 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2071 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2072 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2074 if GL_VERSION_1_3 then begin
2075 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2076 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2077 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2079 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB');
2080 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB');
2081 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB');
2091 function CreateGrayPalette: HPALETTE;
2096 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
2098 Pal.palVersion := $300;
2099 Pal.palNumEntries := 256;
2102 {$DEFINE GLB_TEMPRANGECHECK}
2106 for Idx := 0 to 256 - 1 do begin
2107 Pal.palPalEntry[Idx].peRed := Idx;
2108 Pal.palPalEntry[Idx].peGreen := Idx;
2109 Pal.palPalEntry[Idx].peBlue := Idx;
2110 Pal.palPalEntry[Idx].peFlags := 0;
2113 {$IFDEF GLB_TEMPRANGECHECK}
2114 {$UNDEF GLB_TEMPRANGECHECK}
2118 result := CreatePalette(Pal^);
2125 {$IFDEF GLB_SDL_IMAGE}
2126 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2127 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2128 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2129 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2131 result := TStream(context^.unknown.data1).Seek(offset, whence);
2134 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2136 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2139 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2141 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2144 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2149 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2151 result := SDL_AllocRW;
2153 if result = nil then
2154 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2156 result^.seek := glBitmapRWseek;
2157 result^.read := glBitmapRWread;
2158 result^.write := glBitmapRWwrite;
2159 result^.close := glBitmapRWclose;
2160 result^.unknown.data1 := Stream;
2165 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
2167 glBitmap: TglBitmap2D;
2173 if Instance = 0 then
2174 Instance := HInstance;
2176 if (LoadFromRes) then
2177 glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName)
2180 glBitmap := TglBitmap2D.Create(FileName);
2183 glBitmap.DeleteTextureOnFree := false;
2184 glBitmap.FreeDataAfterGenTexture := false;
2185 glBitmap.GenTexture(true);
2186 if (glBitmap.ID > 0) then begin
2187 Texture := glBitmap.ID;
2195 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
2197 CM: TglBitmapCubeMap;
2202 if Instance = 0 then
2203 Instance := HInstance;
2206 CM := TglBitmapCubeMap.Create;
2208 CM.DeleteTextureOnFree := false;
2212 if (LoadFromRes) then
2213 CM.LoadFromResource(Instance, PositiveX)
2216 CM.LoadFromFile(PositiveX);
2217 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
2220 if (LoadFromRes) then
2221 CM.LoadFromResource(Instance, NegativeX)
2224 CM.LoadFromFile(NegativeX);
2225 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
2228 if (LoadFromRes) then
2229 CM.LoadFromResource(Instance, PositiveY)
2232 CM.LoadFromFile(PositiveY);
2233 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
2236 if (LoadFromRes) then
2237 CM.LoadFromResource(Instance, NegativeY)
2240 CM.LoadFromFile(NegativeY);
2241 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
2244 if (LoadFromRes) then
2245 CM.LoadFromResource(Instance, PositiveZ)
2248 CM.LoadFromFile(PositiveZ);
2249 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
2252 if (LoadFromRes) then
2253 CM.LoadFromResource(Instance, NegativeZ)
2256 CM.LoadFromFile(NegativeZ);
2257 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
2266 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
2268 NM: TglBitmapNormalMap;
2272 NM := TglBitmapNormalMap.Create;
2274 NM.DeleteTextureOnFree := false;
2275 NM.GenerateNormalMap(Size);
2285 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2286 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2288 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2291 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2292 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2294 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2297 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2298 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2300 glBitmapDefaultMipmap := aValue;
2303 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2304 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2306 glBitmapDefaultFormat := aFormat;
2309 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2310 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2312 glBitmapDefaultFilterMin := aMin;
2313 glBitmapDefaultFilterMag := aMag;
2316 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2317 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2319 glBitmapDefaultWrapS := S;
2320 glBitmapDefaultWrapT := T;
2321 glBitmapDefaultWrapR := R;
2324 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2325 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2327 result := glBitmapDefaultDeleteTextureOnFree;
2330 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2331 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2333 result := glBitmapDefaultFreeDataAfterGenTextures;
2336 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2337 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2339 result := glBitmapDefaultMipmap;
2342 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2343 function glBitmapGetDefaultFormat: TglBitmapFormat;
2345 result := glBitmapDefaultFormat;
2348 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2349 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
2351 aMin := glBitmapDefaultFilterMin;
2352 aMag := glBitmapDefaultFilterMag;
2355 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2356 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
2358 S := glBitmapDefaultWrapS;
2359 T := glBitmapDefaultWrapT;
2360 R := glBitmapDefaultWrapR;
2363 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2364 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2365 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2366 function TFormatDescriptor.GetRedMask: QWord;
2368 result := fRange.r shl fShift.r;
2371 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2372 function TFormatDescriptor.GetGreenMask: QWord;
2374 result := fRange.g shl fShift.g;
2377 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2378 function TFormatDescriptor.GetBlueMask: QWord;
2380 result := fRange.b shl fShift.b;
2383 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2384 function TFormatDescriptor.GetAlphaMask: QWord;
2386 result := fRange.a shl fShift.a;
2389 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2390 function TFormatDescriptor.GetComponents: Integer;
2396 if (fRange.arr[i] > 0) then
2400 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2401 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2405 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2406 w := Max(1, aSize.X);
2407 h := Max(1, aSize.Y);
2408 result := GetSize(w, h);
2413 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2414 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2417 if (aWidth <= 0) or (aHeight <= 0) then
2419 result := Ceil(aWidth * aHeight * fPixelSize);
2422 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2423 function TFormatDescriptor.CreateMappingData: Pointer;
2428 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2429 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2434 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2435 function TFormatDescriptor.IsEmpty: Boolean;
2437 result := (fFormat = tfEmpty);
2440 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2441 function TFormatDescriptor.HasAlpha: Boolean;
2443 result := (fRange.a > 0);
2446 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2447 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2451 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2452 raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
2454 if (aRedMask <> RedMask) then
2456 if (aGreenMask <> GreenMask) then
2458 if (aBlueMask <> BlueMask) then
2460 if (aAlphaMask <> AlphaMask) then
2465 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2466 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2468 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2469 aPixel.Data := fRange;
2470 aPixel.Range := fRange;
2471 aPixel.Format := fFormat;
2474 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2475 constructor TFormatDescriptor.Create;
2480 fWithAlpha := tfEmpty;
2481 fWithoutAlpha := tfEmpty;
2482 fRGBInverted := tfEmpty;
2483 fUncompressed := tfEmpty;
2485 fIsCompressed := false;
2488 fglInternalFormat := 0;
2491 FillChar(fRange, 0, SizeOf(fRange));
2492 FillChar(fShift, 0, SizeOf(fShift));
2495 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2496 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2497 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2498 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2500 aData^ := aPixel.Data.a;
2504 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2509 aPixel.Data.a := aData^;
2513 constructor TfdAlpha_UB1.Create;
2518 fglFormat := GL_ALPHA;
2519 fglDataFormat := GL_UNSIGNED_BYTE;
2522 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2523 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2524 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2525 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2527 aData^ := LuminanceWeight(aPixel);
2531 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2533 aPixel.Data.r := aData^;
2534 aPixel.Data.g := aData^;
2535 aPixel.Data.b := aData^;
2540 constructor TfdLuminance_UB1.Create;
2547 fglFormat := GL_LUMINANCE;
2548 fglDataFormat := GL_UNSIGNED_BYTE;
2551 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2552 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2553 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2554 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2560 if (fRange.arr[i] > 0) then
2561 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2565 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2570 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2574 constructor TfdUniversal_UB1.Create;
2580 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2581 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2582 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2583 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2585 inherited Map(aPixel, aData, aMapData);
2586 aData^ := aPixel.Data.a;
2590 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2592 inherited Unmap(aData, aPixel, aMapData);
2593 aPixel.Data.a := aData^;
2597 constructor TfdLuminanceAlpha_UB2.Create;
2603 fglFormat := GL_LUMINANCE_ALPHA;
2604 fglDataFormat := GL_UNSIGNED_BYTE;
2607 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2608 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2609 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2610 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2612 aData^ := aPixel.Data.r;
2614 aData^ := aPixel.Data.g;
2616 aData^ := aPixel.Data.b;
2620 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2622 aPixel.Data.r := aData^;
2624 aPixel.Data.g := aData^;
2626 aPixel.Data.b := aData^;
2631 constructor TfdRGB_UB3.Create;
2641 fglFormat := GL_RGB;
2642 fglDataFormat := GL_UNSIGNED_BYTE;
2645 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2646 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2647 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2648 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2650 aData^ := aPixel.Data.b;
2652 aData^ := aPixel.Data.g;
2654 aData^ := aPixel.Data.r;
2658 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2660 aPixel.Data.b := aData^;
2662 aPixel.Data.g := aData^;
2664 aPixel.Data.r := aData^;
2669 constructor TfdBGR_UB3.Create;
2678 fglFormat := GL_BGR;
2679 fglDataFormat := GL_UNSIGNED_BYTE;
2682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2683 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2684 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2685 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2687 inherited Map(aPixel, aData, aMapData);
2688 aData^ := aPixel.Data.a;
2692 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2694 inherited Unmap(aData, aPixel, aMapData);
2695 aPixel.Data.a := aData^;
2699 constructor TfdRGBA_UB4.Create;
2705 fglFormat := GL_RGBA;
2706 fglDataFormat := GL_UNSIGNED_BYTE;
2709 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2710 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2711 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2712 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2714 inherited Map(aPixel, aData, aMapData);
2715 aData^ := aPixel.Data.a;
2719 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2721 inherited Unmap(aData, aPixel, aMapData);
2722 aPixel.Data.a := aData^;
2726 constructor TfdBGRA_UB4.Create;
2732 fglFormat := GL_BGRA;
2733 fglDataFormat := GL_UNSIGNED_BYTE;
2736 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2737 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2738 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2739 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2741 PWord(aData)^ := aPixel.Data.a;
2745 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2750 aPixel.Data.a := PWord(aData)^;
2754 constructor TfdAlpha_US1.Create;
2759 fglFormat := GL_ALPHA;
2760 fglDataFormat := GL_UNSIGNED_SHORT;
2763 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2764 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2765 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2766 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2768 PWord(aData)^ := LuminanceWeight(aPixel);
2772 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2774 aPixel.Data.r := PWord(aData)^;
2775 aPixel.Data.g := PWord(aData)^;
2776 aPixel.Data.b := PWord(aData)^;
2781 constructor TfdLuminance_US1.Create;
2788 fglFormat := GL_LUMINANCE;
2789 fglDataFormat := GL_UNSIGNED_SHORT;
2792 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2793 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2794 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2795 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2801 if (fRange.arr[i] > 0) then
2802 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2806 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2811 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2815 constructor TfdUniversal_US1.Create;
2821 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2822 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2823 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2824 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2826 PWord(aData)^ := DepthWeight(aPixel);
2830 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2832 aPixel.Data.r := PWord(aData)^;
2833 aPixel.Data.g := PWord(aData)^;
2834 aPixel.Data.b := PWord(aData)^;
2839 constructor TfdDepth_US1.Create;
2846 fglFormat := GL_DEPTH_COMPONENT;
2847 fglDataFormat := GL_UNSIGNED_SHORT;
2850 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2851 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2852 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2853 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2855 inherited Map(aPixel, aData, aMapData);
2856 PWord(aData)^ := aPixel.Data.a;
2860 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2862 inherited Unmap(aData, aPixel, aMapData);
2863 aPixel.Data.a := PWord(aData)^;
2867 constructor TfdLuminanceAlpha_US2.Create;
2873 fglFormat := GL_LUMINANCE_ALPHA;
2874 fglDataFormat := GL_UNSIGNED_SHORT;
2877 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2878 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2879 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2880 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2882 PWord(aData)^ := aPixel.Data.r;
2884 PWord(aData)^ := aPixel.Data.g;
2886 PWord(aData)^ := aPixel.Data.b;
2890 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2892 aPixel.Data.r := PWord(aData)^;
2894 aPixel.Data.g := PWord(aData)^;
2896 aPixel.Data.b := PWord(aData)^;
2901 constructor TfdRGB_US3.Create;
2911 fglFormat := GL_RGB;
2912 fglDataFormat := GL_UNSIGNED_SHORT;
2915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2916 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2917 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2918 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2920 PWord(aData)^ := aPixel.Data.b;
2922 PWord(aData)^ := aPixel.Data.g;
2924 PWord(aData)^ := aPixel.Data.r;
2928 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2930 aPixel.Data.b := PWord(aData)^;
2932 aPixel.Data.g := PWord(aData)^;
2934 aPixel.Data.r := PWord(aData)^;
2939 constructor TfdBGR_US3.Create;
2949 fglFormat := GL_BGR;
2950 fglDataFormat := GL_UNSIGNED_SHORT;
2953 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2954 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2955 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2956 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2958 inherited Map(aPixel, aData, aMapData);
2959 PWord(aData)^ := aPixel.Data.a;
2963 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2965 inherited Unmap(aData, aPixel, aMapData);
2966 aPixel.Data.a := PWord(aData)^;
2970 constructor TfdRGBA_US4.Create;
2976 fglFormat := GL_RGBA;
2977 fglDataFormat := GL_UNSIGNED_SHORT;
2980 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2981 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2982 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2983 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2985 inherited Map(aPixel, aData, aMapData);
2986 PWord(aData)^ := aPixel.Data.a;
2990 procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2992 inherited Unmap(aData, aPixel, aMapData);
2993 aPixel.Data.a := PWord(aData)^;
2997 constructor TfdBGRA_US4.Create;
3003 fglFormat := GL_BGRA;
3004 fglDataFormat := GL_UNSIGNED_SHORT;
3007 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3008 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3009 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3010 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3014 PCardinal(aData)^ := 0;
3016 if (fRange.arr[i] > 0) then
3017 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
3021 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3026 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
3030 constructor TfdUniversal_UI1.Create;
3036 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3037 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3038 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3039 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3041 PCardinal(aData)^ := DepthWeight(aPixel);
3045 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3047 aPixel.Data.r := PCardinal(aData)^;
3048 aPixel.Data.g := PCardinal(aData)^;
3049 aPixel.Data.b := PCardinal(aData)^;
3054 constructor TfdDepth_UI1.Create;
3058 fRange.r := $FFFFFFFF;
3059 fRange.g := $FFFFFFFF;
3060 fRange.b := $FFFFFFFF;
3061 fglFormat := GL_DEPTH_COMPONENT;
3062 fglDataFormat := GL_UNSIGNED_INT;
3065 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3066 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3067 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3068 constructor TfdAlpha4.Create;
3071 fFormat := tfAlpha4;
3072 fWithAlpha := tfAlpha4;
3073 fglInternalFormat := GL_ALPHA4;
3076 constructor TfdAlpha8.Create;
3079 fFormat := tfAlpha8;
3080 fWithAlpha := tfAlpha8;
3081 fglInternalFormat := GL_ALPHA8;
3084 constructor TfdAlpha12.Create;
3087 fFormat := tfAlpha12;
3088 fWithAlpha := tfAlpha12;
3089 fglInternalFormat := GL_ALPHA12;
3092 constructor TfdAlpha16.Create;
3095 fFormat := tfAlpha16;
3096 fWithAlpha := tfAlpha16;
3097 fglInternalFormat := GL_ALPHA16;
3100 constructor TfdLuminance4.Create;
3103 fFormat := tfLuminance4;
3104 fWithAlpha := tfLuminance4Alpha4;
3105 fWithoutAlpha := tfLuminance4;
3106 fglInternalFormat := GL_LUMINANCE4;
3109 constructor TfdLuminance8.Create;
3112 fFormat := tfLuminance8;
3113 fWithAlpha := tfLuminance8Alpha8;
3114 fWithoutAlpha := tfLuminance8;
3115 fglInternalFormat := GL_LUMINANCE8;
3118 constructor TfdLuminance12.Create;
3121 fFormat := tfLuminance12;
3122 fWithAlpha := tfLuminance12Alpha12;
3123 fWithoutAlpha := tfLuminance12;
3124 fglInternalFormat := GL_LUMINANCE12;
3127 constructor TfdLuminance16.Create;
3130 fFormat := tfLuminance16;
3131 fWithAlpha := tfLuminance16Alpha16;
3132 fWithoutAlpha := tfLuminance16;
3133 fglInternalFormat := GL_LUMINANCE16;
3136 constructor TfdLuminance4Alpha4.Create;
3139 fFormat := tfLuminance4Alpha4;
3140 fWithAlpha := tfLuminance4Alpha4;
3141 fWithoutAlpha := tfLuminance4;
3142 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3145 constructor TfdLuminance6Alpha2.Create;
3148 fFormat := tfLuminance6Alpha2;
3149 fWithAlpha := tfLuminance6Alpha2;
3150 fWithoutAlpha := tfLuminance8;
3151 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3154 constructor TfdLuminance8Alpha8.Create;
3157 fFormat := tfLuminance8Alpha8;
3158 fWithAlpha := tfLuminance8Alpha8;
3159 fWithoutAlpha := tfLuminance8;
3160 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3163 constructor TfdLuminance12Alpha4.Create;
3166 fFormat := tfLuminance12Alpha4;
3167 fWithAlpha := tfLuminance12Alpha4;
3168 fWithoutAlpha := tfLuminance12;
3169 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3172 constructor TfdLuminance12Alpha12.Create;
3175 fFormat := tfLuminance12Alpha12;
3176 fWithAlpha := tfLuminance12Alpha12;
3177 fWithoutAlpha := tfLuminance12;
3178 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3181 constructor TfdLuminance16Alpha16.Create;
3184 fFormat := tfLuminance16Alpha16;
3185 fWithAlpha := tfLuminance16Alpha16;
3186 fWithoutAlpha := tfLuminance16;
3187 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3190 constructor TfdR3G3B2.Create;
3193 fFormat := tfR3G3B2;
3194 fWithAlpha := tfRGBA2;
3195 fWithoutAlpha := tfR3G3B2;
3202 fglFormat := GL_RGB;
3203 fglInternalFormat := GL_R3_G3_B2;
3204 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3207 constructor TfdRGB4.Create;
3211 fWithAlpha := tfRGBA4;
3212 fWithoutAlpha := tfRGB4;
3213 fRGBInverted := tfBGR4;
3220 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3221 fglInternalFormat := GL_RGB4;
3222 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3225 constructor TfdR5G6B5.Create;
3228 fFormat := tfR5G6B5;
3229 fWithAlpha := tfRGBA4;
3230 fWithoutAlpha := tfR5G6B5;
3231 fRGBInverted := tfB5G6R5;
3238 fglFormat := GL_RGB;
3239 fglInternalFormat := GL_RGB565;
3240 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3243 constructor TfdRGB5.Create;
3247 fWithAlpha := tfRGB5A1;
3248 fWithoutAlpha := tfRGB5;
3249 fRGBInverted := tfBGR5;
3256 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3257 fglInternalFormat := GL_RGB5;
3258 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3261 constructor TfdRGB8.Create;
3265 fWithAlpha := tfRGBA8;
3266 fWithoutAlpha := tfRGB8;
3267 fRGBInverted := tfBGR8;
3268 fglInternalFormat := GL_RGB8;
3271 constructor TfdRGB10.Create;
3275 fWithAlpha := tfRGB10A2;
3276 fWithoutAlpha := tfRGB10;
3277 fRGBInverted := tfBGR10;
3284 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3285 fglInternalFormat := GL_RGB10;
3286 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3289 constructor TfdRGB12.Create;
3293 fWithAlpha := tfRGBA12;
3294 fWithoutAlpha := tfRGB12;
3295 fRGBInverted := tfBGR12;
3296 fglInternalFormat := GL_RGB12;
3299 constructor TfdRGB16.Create;
3303 fWithAlpha := tfRGBA16;
3304 fWithoutAlpha := tfRGB16;
3305 fRGBInverted := tfBGR16;
3306 fglInternalFormat := GL_RGB16;
3309 constructor TfdRGBA2.Create;
3313 fWithAlpha := tfRGBA2;
3314 fWithoutAlpha := tfR3G3B2;
3315 fRGBInverted := tfBGRA2;
3316 fglInternalFormat := GL_RGBA2;
3319 constructor TfdRGBA4.Create;
3323 fWithAlpha := tfRGBA4;
3324 fWithoutAlpha := tfRGB4;
3325 fRGBInverted := tfBGRA4;
3334 fglFormat := GL_RGBA;
3335 fglInternalFormat := GL_RGBA4;
3336 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3339 constructor TfdRGB5A1.Create;
3342 fFormat := tfRGB5A1;
3343 fWithAlpha := tfRGB5A1;
3344 fWithoutAlpha := tfRGB5;
3345 fRGBInverted := tfBGR5A1;
3354 fglFormat := GL_RGBA;
3355 fglInternalFormat := GL_RGB5_A1;
3356 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3359 constructor TfdRGBA8.Create;
3363 fWithAlpha := tfRGBA8;
3364 fWithoutAlpha := tfRGB8;
3365 fRGBInverted := tfBGRA8;
3366 fglInternalFormat := GL_RGBA8;
3369 constructor TfdRGB10A2.Create;
3372 fFormat := tfRGB10A2;
3373 fWithAlpha := tfRGB10A2;
3374 fWithoutAlpha := tfRGB10;
3375 fRGBInverted := tfBGR10A2;
3384 fglFormat := GL_RGBA;
3385 fglInternalFormat := GL_RGB10_A2;
3386 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3389 constructor TfdRGBA12.Create;
3392 fFormat := tfRGBA12;
3393 fWithAlpha := tfRGBA12;
3394 fWithoutAlpha := tfRGB12;
3395 fRGBInverted := tfBGRA12;
3396 fglInternalFormat := GL_RGBA12;
3399 constructor TfdRGBA16.Create;
3402 fFormat := tfRGBA16;
3403 fWithAlpha := tfRGBA16;
3404 fWithoutAlpha := tfRGB16;
3405 fRGBInverted := tfBGRA16;
3406 fglInternalFormat := GL_RGBA16;
3409 constructor TfdBGR4.Create;
3414 fWithAlpha := tfBGRA4;
3415 fWithoutAlpha := tfBGR4;
3416 fRGBInverted := tfRGB4;
3425 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3426 fglInternalFormat := GL_RGB4;
3427 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3430 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3431 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3432 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3433 constructor TfdB5G6R5.Create;
3436 fFormat := tfB5G6R5;
3437 fWithAlpha := tfBGRA4;
3438 fWithoutAlpha := tfB5G6R5;
3439 fRGBInverted := tfR5G6B5;
3446 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3447 fglInternalFormat := GL_RGB8;
3448 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3451 constructor TfdBGR5.Create;
3456 fWithAlpha := tfBGR5A1;
3457 fWithoutAlpha := tfBGR5;
3458 fRGBInverted := tfRGB5;
3467 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3468 fglInternalFormat := GL_RGB5;
3469 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3472 constructor TfdBGR8.Create;
3476 fWithAlpha := tfBGRA8;
3477 fWithoutAlpha := tfBGR8;
3478 fRGBInverted := tfRGB8;
3479 fglInternalFormat := GL_RGB8;
3482 constructor TfdBGR10.Create;
3486 fWithAlpha := tfBGR10A2;
3487 fWithoutAlpha := tfBGR10;
3488 fRGBInverted := tfRGB10;
3497 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3498 fglInternalFormat := GL_RGB10;
3499 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3502 constructor TfdBGR12.Create;
3506 fWithAlpha := tfBGRA12;
3507 fWithoutAlpha := tfBGR12;
3508 fRGBInverted := tfRGB12;
3509 fglInternalFormat := GL_RGB12;
3512 constructor TfdBGR16.Create;
3516 fWithAlpha := tfBGRA16;
3517 fWithoutAlpha := tfBGR16;
3518 fRGBInverted := tfRGB16;
3519 fglInternalFormat := GL_RGB16;
3522 constructor TfdBGRA2.Create;
3526 fWithAlpha := tfBGRA4;
3527 fWithoutAlpha := tfBGR4;
3528 fRGBInverted := tfRGBA2;
3529 fglInternalFormat := GL_RGBA2;
3532 constructor TfdBGRA4.Create;
3536 fWithAlpha := tfBGRA4;
3537 fWithoutAlpha := tfBGR4;
3538 fRGBInverted := tfRGBA4;
3547 fglFormat := GL_BGRA;
3548 fglInternalFormat := GL_RGBA4;
3549 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3552 constructor TfdBGR5A1.Create;
3555 fFormat := tfBGR5A1;
3556 fWithAlpha := tfBGR5A1;
3557 fWithoutAlpha := tfBGR5;
3558 fRGBInverted := tfRGB5A1;
3567 fglFormat := GL_BGRA;
3568 fglInternalFormat := GL_RGB5_A1;
3569 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3572 constructor TfdBGRA8.Create;
3576 fWithAlpha := tfBGRA8;
3577 fWithoutAlpha := tfBGR8;
3578 fRGBInverted := tfRGBA8;
3579 fglInternalFormat := GL_RGBA8;
3582 constructor TfdBGR10A2.Create;
3585 fFormat := tfBGR10A2;
3586 fWithAlpha := tfBGR10A2;
3587 fWithoutAlpha := tfBGR10;
3588 fRGBInverted := tfRGB10A2;
3597 fglFormat := GL_BGRA;
3598 fglInternalFormat := GL_RGB10_A2;
3599 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3602 constructor TfdBGRA12.Create;
3605 fFormat := tfBGRA12;
3606 fWithAlpha := tfBGRA12;
3607 fWithoutAlpha := tfBGR12;
3608 fRGBInverted := tfRGBA12;
3609 fglInternalFormat := GL_RGBA12;
3612 constructor TfdBGRA16.Create;
3615 fFormat := tfBGRA16;
3616 fWithAlpha := tfBGRA16;
3617 fWithoutAlpha := tfBGR16;
3618 fRGBInverted := tfRGBA16;
3619 fglInternalFormat := GL_RGBA16;
3622 constructor TfdDepth16.Create;
3625 fFormat := tfDepth16;
3626 fWithAlpha := tfEmpty;
3627 fWithoutAlpha := tfDepth16;
3628 fglInternalFormat := GL_DEPTH_COMPONENT16;
3631 constructor TfdDepth24.Create;
3634 fFormat := tfDepth24;
3635 fWithAlpha := tfEmpty;
3636 fWithoutAlpha := tfDepth24;
3637 fglInternalFormat := GL_DEPTH_COMPONENT24;
3640 constructor TfdDepth32.Create;
3643 fFormat := tfDepth32;
3644 fWithAlpha := tfEmpty;
3645 fWithoutAlpha := tfDepth32;
3646 fglInternalFormat := GL_DEPTH_COMPONENT32;
3649 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3650 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3651 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3652 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3654 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3657 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3659 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3662 constructor TfdS3tcDtx1RGBA.Create;
3665 fFormat := tfS3tcDtx1RGBA;
3666 fWithAlpha := tfS3tcDtx1RGBA;
3667 fUncompressed := tfRGB5A1;
3669 fIsCompressed := true;
3670 fglFormat := GL_COMPRESSED_RGBA;
3671 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3672 fglDataFormat := GL_UNSIGNED_BYTE;
3675 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3676 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3677 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3678 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3680 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3683 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3685 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3688 constructor TfdS3tcDtx3RGBA.Create;
3691 fFormat := tfS3tcDtx3RGBA;
3692 fWithAlpha := tfS3tcDtx3RGBA;
3693 fUncompressed := tfRGBA8;
3695 fIsCompressed := true;
3696 fglFormat := GL_COMPRESSED_RGBA;
3697 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3698 fglDataFormat := GL_UNSIGNED_BYTE;
3701 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3702 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3703 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3704 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3706 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3709 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3711 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3714 constructor TfdS3tcDtx5RGBA.Create;
3717 fFormat := tfS3tcDtx3RGBA;
3718 fWithAlpha := tfS3tcDtx3RGBA;
3719 fUncompressed := tfRGBA8;
3721 fIsCompressed := true;
3722 fglFormat := GL_COMPRESSED_RGBA;
3723 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3724 fglDataFormat := GL_UNSIGNED_BYTE;
3727 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3728 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3729 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3730 class procedure TFormatDescriptor.Init;
3732 if not Assigned(FormatDescriptorCS) then
3733 FormatDescriptorCS := TCriticalSection.Create;
3736 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3737 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3739 FormatDescriptorCS.Enter;
3741 result := FormatDescriptors[aFormat];
3742 if not Assigned(result) then begin
3743 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3744 FormatDescriptors[aFormat] := result;
3747 FormatDescriptorCS.Leave;
3751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3752 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3754 result := Get(Get(aFormat).WithAlpha);
3757 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3758 class procedure TFormatDescriptor.Clear;
3762 FormatDescriptorCS.Enter;
3764 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3765 FreeAndNil(FormatDescriptors[f]);
3767 FormatDescriptorCS.Leave;
3771 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3772 class procedure TFormatDescriptor.Finalize;
3775 FreeAndNil(FormatDescriptorCS);
3778 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3779 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3780 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3781 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3783 Update(aValue, fRange.r, fShift.r);
3786 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3787 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3789 Update(aValue, fRange.g, fShift.g);
3792 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3793 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3795 Update(aValue, fRange.b, fShift.b);
3798 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3799 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3801 Update(aValue, fRange.a, fShift.a);
3804 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3805 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3812 while (aMask > 0) and ((aMask and 1) = 0) do begin
3814 aMask := aMask shr 1;
3817 while (aMask > 0) do begin
3818 aRange := aRange shl 1;
3819 aMask := aMask shr 1;
3823 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3826 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3827 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3833 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3834 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3835 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3836 ((aPixel.Data.a and fRange.a) shl fShift.a);
3837 s := Round(fPixelSize);
3840 2: PWord(aData)^ := data;
3841 4: PCardinal(aData)^ := data;
3842 8: PQWord(aData)^ := data;
3844 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3849 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3850 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3855 s := Round(fPixelSize);
3858 2: data := PWord(aData)^;
3859 4: data := PCardinal(aData)^;
3860 8: data := PQWord(aData)^;
3862 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3865 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3869 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3870 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3871 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3872 procedure TbmpColorTableFormat.CreateColorTable;
3876 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3877 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3879 if (Format = tfLuminance4) then
3880 SetLength(fColorTable, 16)
3882 SetLength(fColorTable, 256);
3886 for i := 0 to High(fColorTable) do begin
3887 fColorTable[i].r := 16 * i;
3888 fColorTable[i].g := 16 * i;
3889 fColorTable[i].b := 16 * i;
3890 fColorTable[i].a := 0;
3895 for i := 0 to High(fColorTable) do begin
3896 fColorTable[i].r := i;
3897 fColorTable[i].g := i;
3898 fColorTable[i].b := i;
3899 fColorTable[i].a := 0;
3904 for i := 0 to High(fColorTable) do begin
3905 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3906 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3907 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3908 fColorTable[i].a := 0;
3914 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3915 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3919 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3920 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3924 if (aMapData = nil) then
3926 d := LuminanceWeight(aPixel) and Range.r;
3927 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3929 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3936 aData^ := LuminanceWeight(aPixel) and Range.r;
3942 ((aPixel.Data.r and Range.r) shl Shift.r) or
3943 ((aPixel.Data.g and Range.g) shl Shift.g) or
3944 ((aPixel.Data.b and Range.b) shl Shift.b));
3950 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3951 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3958 s := Trunc(fPixelSize);
3959 f := fPixelSize - s;
3960 bits := Round(8 * f);
3962 0: idx := (aData^ shr (8 - bits - {%H-}PtrUInt(aMapData))) and ((1 shl bits) - 1);
3964 2: idx := PWord(aData)^;
3965 4: idx := PCardinal(aData)^;
3966 8: idx := PQWord(aData)^;
3968 raise EglBitmapException.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3970 if (idx >= Length(fColorTable)) then
3971 raise EglBitmapException.CreateFmt('invalid color index: %d', [idx]);
3972 with fColorTable[idx] do begin
3978 inc(aMapData, bits);
3979 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3986 destructor TbmpColorTableFormat.Destroy;
3988 SetLength(fColorTable, 0);
3992 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3993 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3994 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3995 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
3999 for i := 0 to 3 do begin
4000 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
4001 if (aSourceFD.Range.arr[i] > 0) then
4002 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
4004 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
4009 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4010 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
4012 with aFuncRec do begin
4013 if (Source.Range.r > 0) then
4014 Dest.Data.r := Source.Data.r;
4015 if (Source.Range.g > 0) then
4016 Dest.Data.g := Source.Data.g;
4017 if (Source.Range.b > 0) then
4018 Dest.Data.b := Source.Data.b;
4019 if (Source.Range.a > 0) then
4020 Dest.Data.a := Source.Data.a;
4024 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4025 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4029 with aFuncRec do begin
4031 if (Source.Range.arr[i] > 0) then
4032 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4037 TShiftData = packed record
4039 0: (r, g, b, a: SmallInt);
4040 1: (arr: array[0..3] of SmallInt);
4042 PShiftData = ^TShiftData;
4044 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4045 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4051 if (Source.Range.arr[i] > 0) then
4052 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4055 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4056 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4058 with aFuncRec do begin
4059 Dest.Data := Source.Data;
4060 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4061 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4062 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4063 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4065 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4066 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4071 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4072 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4076 with aFuncRec do begin
4078 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4082 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4083 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4087 with FuncRec do begin
4088 if (FuncRec.Args = nil) then begin //source has no alpha
4090 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4091 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4092 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4093 Dest.Data.a := Round(Dest.Range.a * Temp);
4095 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4099 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4100 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4102 PglBitmapPixelData = ^TglBitmapPixelData;
4104 with FuncRec do begin
4105 Dest.Data.r := Source.Data.r;
4106 Dest.Data.g := Source.Data.g;
4107 Dest.Data.b := Source.Data.b;
4109 with PglBitmapPixelData(Args)^ do
4110 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4111 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4112 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4115 Dest.Data.a := Dest.Range.a;
4119 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4120 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4122 with FuncRec do begin
4123 Dest.Data.r := Source.Data.r;
4124 Dest.Data.g := Source.Data.g;
4125 Dest.Data.b := Source.Data.b;
4126 Dest.Data.a := PCardinal(Args)^;
4130 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4131 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4134 TRGBPix = array [0..2] of byte;
4138 while aWidth > 0 do begin
4139 Temp := PRGBPix(aData)^[0];
4140 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4141 PRGBPix(aData)^[2] := Temp;
4151 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4152 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4153 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4154 function TglBitmap.GetWidth: Integer;
4156 if (ffX in fDimension.Fields) then
4157 result := fDimension.X
4162 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4163 function TglBitmap.GetHeight: Integer;
4165 if (ffY in fDimension.Fields) then
4166 result := fDimension.Y
4171 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4172 function TglBitmap.GetFileWidth: Integer;
4174 result := Max(1, Width);
4177 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4178 function TglBitmap.GetFileHeight: Integer;
4180 result := Max(1, Height);
4183 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4184 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4186 if fCustomData = aValue then
4188 fCustomData := aValue;
4191 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4192 procedure TglBitmap.SetCustomName(const aValue: String);
4194 if fCustomName = aValue then
4196 fCustomName := aValue;
4199 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4200 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4202 if fCustomNameW = aValue then
4204 fCustomNameW := aValue;
4207 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4208 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4210 if fDeleteTextureOnFree = aValue then
4212 fDeleteTextureOnFree := aValue;
4215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4216 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4218 if fFormat = aValue then
4220 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4221 raise EglBitmapUnsupportedFormat.Create(Format);
4222 SetDataPointer(Data, aValue, Width, Height);
4225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4226 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4228 if fFreeDataAfterGenTexture = aValue then
4230 fFreeDataAfterGenTexture := aValue;
4233 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4234 procedure TglBitmap.SetID(const aValue: Cardinal);
4236 if fID = aValue then
4241 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4242 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4244 if fMipMap = aValue then
4249 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4250 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4252 if fTarget = aValue then
4257 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4258 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4260 MaxAnisotropic: Integer;
4262 fAnisotropic := aValue;
4263 if (ID > 0) then begin
4264 if GL_EXT_texture_filter_anisotropic then begin
4265 if fAnisotropic > 0 then begin
4267 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4268 if aValue > MaxAnisotropic then
4269 fAnisotropic := MaxAnisotropic;
4270 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4278 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4279 procedure TglBitmap.CreateID;
4282 glDeleteTextures(1, @fID);
4283 glGenTextures(1, @fID);
4287 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4288 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4290 // Set Up Parameters
4291 SetWrap(fWrapS, fWrapT, fWrapR);
4292 SetFilter(fFilterMin, fFilterMag);
4293 SetAnisotropic(fAnisotropic);
4294 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4296 // Mip Maps Generation Mode
4297 aBuildWithGlu := false;
4298 if (MipMap = mmMipmap) then begin
4299 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4300 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4302 aBuildWithGlu := true;
4303 end else if (MipMap = mmMipmapGlu) then
4304 aBuildWithGlu := true;
4307 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4308 procedure TglBitmap.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
4309 const aWidth: Integer; const aHeight: Integer);
4313 if (Data <> aData) then begin
4314 if (Assigned(Data)) then
4319 FillChar(fDimension, SizeOf(fDimension), 0);
4320 if not Assigned(fData) then begin
4325 if aWidth <> -1 then begin
4326 fDimension.Fields := fDimension.Fields + [ffX];
4327 fDimension.X := aWidth;
4330 if aHeight <> -1 then begin
4331 fDimension.Fields := fDimension.Fields + [ffY];
4332 fDimension.Y := aHeight;
4335 s := TFormatDescriptor.Get(aFormat).PixelSize;
4337 fPixelSize := Ceil(s);
4338 fRowSize := Ceil(s * aWidth);
4342 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4343 function TglBitmap.FlipHorz: Boolean;
4348 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4349 function TglBitmap.FlipVert: Boolean;
4354 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4355 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4356 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4357 procedure TglBitmap.AfterConstruction;
4359 inherited AfterConstruction;
4363 fIsResident := false;
4365 fFormat := glBitmapGetDefaultFormat;
4366 fMipMap := glBitmapDefaultMipmap;
4367 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4368 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4370 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4371 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4374 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4375 procedure TglBitmap.BeforeDestruction;
4377 SetDataPointer(nil, tfEmpty);
4378 if (fID > 0) and fDeleteTextureOnFree then
4379 glDeleteTextures(1, @fID);
4380 inherited BeforeDestruction;
4383 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4384 procedure TglBitmap.LoadFromFile(const aFilename: String);
4388 if not FileExists(aFilename) then
4389 raise EglBitmapException.Create('file does not exist: ' + aFilename);
4390 fFilename := aFilename;
4391 fs := TFileStream.Create(fFilename, fmOpenRead);
4400 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4401 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4403 {$IFDEF GLB_SUPPORT_PNG_READ}
4404 if not LoadPNG(aStream) then
4406 {$IFDEF GLB_SUPPORT_JPEG_READ}
4407 if not LoadJPEG(aStream) then
4409 if not LoadDDS(aStream) then
4410 if not LoadTGA(aStream) then
4411 if not LoadBMP(aStream) then
4412 raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4416 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4417 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4422 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4423 GetMem(tmpData, size);
4425 FillChar(tmpData^, size, #$FF);
4426 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y);
4431 AddFunc(Self, aFunc, false, Format, aArgs);
4435 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4436 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
4438 rs: TResourceStream;
4443 if not Assigned(ResType) then begin
4444 TempPos := Pos('.', Resource);
4445 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
4446 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
4447 TempResType := PChar(ResTypeStr);
4449 TempResType := ResType
4451 rs := TResourceStream.Create(Instance, Resource, TempResType);
4459 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4460 procedure TglBitmap.LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4462 rs: TResourceStream;
4464 rs := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
4473 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4474 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4478 fs := TFileStream.Create(aFileName, fmCreate);
4481 SaveToStream(fs, aFileType);
4487 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4488 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4491 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4492 ftPNG: SavePNG(aStream);
4494 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4495 ftJPEG: SaveJPEG(aStream);
4497 ftDDS: SaveDDS(aStream);
4498 ftTGA: SaveTGA(aStream);
4499 ftBMP: SaveBMP(aStream);
4503 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4504 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4506 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4509 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4510 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4511 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4513 DestData, TmpData, SourceData: pByte;
4514 TempHeight, TempWidth: Integer;
4515 SourceFD, DestFD: TFormatDescriptor;
4516 SourceMD, DestMD: Pointer;
4518 FuncRec: TglBitmapFunctionRec;
4520 Assert(Assigned(Data));
4521 Assert(Assigned(aSource));
4522 Assert(Assigned(aSource.Data));
4525 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4526 SourceFD := TFormatDescriptor.Get(aSource.Format);
4527 DestFD := TFormatDescriptor.Get(aFormat);
4529 // inkompatible Formats so CreateTemp
4530 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4531 aCreateTemp := true;
4534 TempHeight := Max(1, aSource.Height);
4535 TempWidth := Max(1, aSource.Width);
4537 FuncRec.Sender := Self;
4538 FuncRec.Args := aArgs;
4541 if aCreateTemp then begin
4542 GetMem(TmpData, TFormatDescriptor.Get(aFormat).GetSize(TempWidth, TempHeight));
4543 DestData := TmpData;
4548 SourceFD.PreparePixel(FuncRec.Source);
4549 DestFD.PreparePixel (FuncRec.Dest);
4551 SourceMD := SourceFD.CreateMappingData;
4552 DestMD := DestFD.CreateMappingData;
4554 FuncRec.Size := aSource.Dimension;
4555 FuncRec.Position.Fields := FuncRec.Size.Fields;
4558 SourceData := aSource.Data;
4559 FuncRec.Position.Y := 0;
4560 while FuncRec.Position.Y < TempHeight do begin
4561 FuncRec.Position.X := 0;
4562 while FuncRec.Position.X < TempWidth do begin
4563 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4565 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4566 inc(FuncRec.Position.X);
4568 inc(FuncRec.Position.Y);
4571 // Updating Image or InternalFormat
4573 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height)
4574 else if (aFormat <> fFormat) then
4579 SourceFD.FreeMappingData(SourceMD);
4580 DestFD.FreeMappingData(DestMD);
4591 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4592 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4594 Row, RowSize: Integer;
4595 SourceData, TmpData: PByte;
4597 FormatDesc: TFormatDescriptor;
4599 function GetRowPointer(Row: Integer): pByte;
4601 result := aSurface.pixels;
4602 Inc(result, Row * RowSize);
4608 FormatDesc := TFormatDescriptor.Get(Format);
4609 if FormatDesc.IsCompressed then
4610 raise EglBitmapUnsupportedFormat.Create(Format);
4612 if Assigned(Data) then begin
4613 case Trunc(FormatDesc.PixelSize) of
4619 raise EglBitmapUnsupportedFormat.Create(Format);
4622 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4623 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4625 RowSize := FormatDesc.GetSize(FileWidth, 1);
4627 for Row := 0 to FileHeight-1 do begin
4628 TmpData := GetRowPointer(Row);
4629 if Assigned(TmpData) then begin
4630 Move(SourceData^, TmpData^, RowSize);
4631 inc(SourceData, RowSize);
4638 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4639 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4641 pSource, pData, pTempData: PByte;
4642 Row, RowSize, TempWidth, TempHeight: Integer;
4643 IntFormat: TglBitmapFormat;
4644 FormatDesc: TFormatDescriptor;
4646 function GetRowPointer(Row: Integer): pByte;
4648 result := aSurface^.pixels;
4649 Inc(result, Row * RowSize);
4654 if (Assigned(aSurface)) then begin
4655 with aSurface^.format^ do begin
4656 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4657 FormatDesc := TFormatDescriptor.Get(IntFormat);
4658 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4661 if (IntFormat = tfEmpty) then
4662 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4665 TempWidth := aSurface^.w;
4666 TempHeight := aSurface^.h;
4667 RowSize := FormatDesc.GetSize(TempWidth, 1);
4668 GetMem(pData, TempHeight * RowSize);
4671 for Row := 0 to TempHeight -1 do begin
4672 pSource := GetRowPointer(Row);
4673 if (Assigned(pSource)) then begin
4674 Move(pSource^, pTempData^, RowSize);
4675 Inc(pTempData, RowSize);
4678 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
4687 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4688 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4690 Row, Col, AlphaInterleave: Integer;
4691 pSource, pDest: PByte;
4693 function GetRowPointer(Row: Integer): pByte;
4695 result := aSurface.pixels;
4696 Inc(result, Row * Width);
4701 if Assigned(Data) then begin
4702 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4703 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4705 AlphaInterleave := 0;
4708 AlphaInterleave := 1;
4710 AlphaInterleave := 3;
4714 for Row := 0 to Height -1 do begin
4715 pDest := GetRowPointer(Row);
4716 if Assigned(pDest) then begin
4717 for Col := 0 to Width -1 do begin
4718 Inc(pSource, AlphaInterleave);
4730 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4731 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4735 bmp := TglBitmap2D.Create;
4737 bmp.AssignFromSurface(aSurface);
4738 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4746 //TODO rework & test
4747 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4748 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4751 pSource, pData: PByte;
4754 if Assigned(Data) then begin
4755 if Assigned(aBitmap) then begin
4756 aBitmap.Width := Width;
4757 aBitmap.Height := Height;
4760 tfAlpha8, ifLuminance, ifDepth8:
4762 Bitmap.PixelFormat := pf8bit;
4763 Bitmap.Palette := CreateGrayPalette;
4766 Bitmap.PixelFormat := pf15bit;
4768 Bitmap.PixelFormat := pf16bit;
4770 Bitmap.PixelFormat := pf24bit;
4772 Bitmap.PixelFormat := pf32bit;
4774 raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
4778 for Row := 0 to FileHeight -1 do begin
4779 pData := Bitmap.Scanline[Row];
4781 Move(pSource^, pData^, fRowSize);
4782 Inc(pSource, fRowSize);
4784 // swap RGB(A) to BGR(A)
4785 if InternalFormat in [ifRGB8, ifRGBA8] then
4786 SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8);
4794 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4795 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4797 pSource, pData, pTempData: PByte;
4798 Row, RowSize, TempWidth, TempHeight: Integer;
4799 IntFormat: TglBitmapInternalFormat;
4803 if (Assigned(Bitmap)) then begin
4804 case Bitmap.PixelFormat of
4806 IntFormat := ifLuminance;
4808 IntFormat := ifRGB5A1;
4810 IntFormat := ifR5G6B5;
4812 IntFormat := ifBGR8;
4814 IntFormat := ifBGRA8;
4816 raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
4819 TempWidth := Bitmap.Width;
4820 TempHeight := Bitmap.Height;
4822 RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
4824 GetMem(pData, TempHeight * RowSize);
4828 for Row := 0 to TempHeight -1 do begin
4829 pSource := Bitmap.Scanline[Row];
4831 if (Assigned(pSource)) then begin
4832 Move(pSource^, pTempData^, RowSize);
4833 Inc(pTempData, RowSize);
4837 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
4847 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4848 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4850 Row, Col, AlphaInterleave: Integer;
4851 pSource, pDest: PByte;
4855 if Assigned(Data) then begin
4856 if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin
4857 if Assigned(Bitmap) then begin
4858 Bitmap.PixelFormat := pf8bit;
4859 Bitmap.Palette := CreateGrayPalette;
4860 Bitmap.Width := Width;
4861 Bitmap.Height := Height;
4863 case InternalFormat of
4865 AlphaInterleave := 1;
4867 AlphaInterleave := 3;
4869 AlphaInterleave := 0;
4875 for Row := 0 to Height -1 do begin
4876 pDest := Bitmap.Scanline[Row];
4878 if Assigned(pDest) then begin
4879 for Col := 0 to Width -1 do begin
4880 Inc(pSource, AlphaInterleave);
4894 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4895 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4899 tex := TglBitmap2D.Create;
4901 tex.AssignFromBitmap(Bitmap);
4902 result := AddAlphaFromglBitmap(tex, Func, CustomData);
4908 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4909 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar;
4910 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4912 RS: TResourceStream;
4917 if Assigned(ResType) then
4918 TempResType := ResType
4921 TempPos := Pos('.', Resource);
4922 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
4923 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
4924 TempResType := PChar(ResTypeStr);
4927 RS := TResourceStream.Create(Instance, Resource, TempResType);
4929 result := AddAlphaFromStream(RS, Func, CustomData);
4935 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4936 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
4937 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4939 RS: TResourceStream;
4941 RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
4943 result := AddAlphaFromStream(RS, Func, CustomData);
4950 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4951 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4953 if TFormatDescriptor.Get(Format).IsCompressed then
4954 raise EglBitmapUnsupportedFormat.Create(Format);
4955 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
4958 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4959 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4963 FS := TFileStream.Create(FileName, fmOpenRead);
4965 result := AddAlphaFromStream(FS, aFunc, aArgs);
4971 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4972 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4976 tex := TglBitmap2D.Create(aStream);
4978 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4984 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4985 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4987 DestData, DestData2, SourceData: pByte;
4988 TempHeight, TempWidth: Integer;
4989 SourceFD, DestFD: TFormatDescriptor;
4990 SourceMD, DestMD, DestMD2: Pointer;
4992 FuncRec: TglBitmapFunctionRec;
4996 Assert(Assigned(Data));
4997 Assert(Assigned(aBitmap));
4998 Assert(Assigned(aBitmap.Data));
5000 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
5001 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
5003 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
5004 DestFD := TFormatDescriptor.Get(Format);
5006 if not Assigned(aFunc) then begin
5007 aFunc := glBitmapAlphaFunc;
5008 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5010 FuncRec.Args := aArgs;
5013 TempHeight := aBitmap.FileHeight;
5014 TempWidth := aBitmap.FileWidth;
5016 FuncRec.Sender := Self;
5017 FuncRec.Size := Dimension;
5018 FuncRec.Position.Fields := FuncRec.Size.Fields;
5022 SourceData := aBitmap.Data;
5025 SourceFD.PreparePixel(FuncRec.Source);
5026 DestFD.PreparePixel (FuncRec.Dest);
5028 SourceMD := SourceFD.CreateMappingData;
5029 DestMD := DestFD.CreateMappingData;
5030 DestMD2 := DestFD.CreateMappingData;
5032 FuncRec.Position.Y := 0;
5033 while FuncRec.Position.Y < TempHeight do begin
5034 FuncRec.Position.X := 0;
5035 while FuncRec.Position.X < TempWidth do begin
5036 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5037 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5039 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5040 inc(FuncRec.Position.X);
5042 inc(FuncRec.Position.Y);
5045 SourceFD.FreeMappingData(SourceMD);
5046 DestFD.FreeMappingData(DestMD);
5047 DestFD.FreeMappingData(DestMD2);
5052 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5053 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5055 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5058 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5059 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5061 PixelData: TglBitmapPixelData;
5063 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5064 result := AddAlphaFromColorKeyFloat(
5065 aRed / PixelData.Range.r,
5066 aGreen / PixelData.Range.g,
5067 aBlue / PixelData.Range.b,
5068 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5071 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5072 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5074 values: array[0..2] of Single;
5077 PixelData: TglBitmapPixelData;
5079 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5080 with PixelData do begin
5082 values[1] := aGreen;
5085 for i := 0 to 2 do begin
5086 tmp := Trunc(Range.arr[i] * aDeviation);
5087 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5088 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5093 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5096 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5097 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5099 result := AddAlphaFromValueFloat(aAlpha / $FF);
5102 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5103 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5105 PixelData: TglBitmapPixelData;
5107 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5108 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5111 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5112 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5114 PixelData: TglBitmapPixelData;
5116 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5118 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5119 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5123 function TglBitmap.RemoveAlpha: Boolean;
5125 FormatDesc: TFormatDescriptor;
5128 FormatDesc := TFormatDescriptor.Get(Format);
5129 if Assigned(Data) then begin
5130 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5131 raise EglBitmapUnsupportedFormat.Create(Format);
5132 result := ConvertTo(FormatDesc.WithoutAlpha);
5136 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5137 function TglBitmap.Clone: TglBitmap;
5144 Temp := (ClassType.Create as TglBitmap);
5146 // copy texture data if assigned
5147 if Assigned(Data) then begin
5148 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5149 GetMem(TempPtr, Size);
5151 Move(Data^, TempPtr^, Size);
5152 Temp.SetDataPointer(TempPtr, Format, Width, Height);
5158 Temp.SetDataPointer(nil, Format, Width, Height);
5162 Temp.fTarget := Target;
5163 Temp.fFormat := Format;
5164 Temp.fMipMap := MipMap;
5165 Temp.fAnisotropic := Anisotropic;
5166 Temp.fBorderColor := fBorderColor;
5167 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5168 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5169 Temp.fFilterMin := fFilterMin;
5170 Temp.fFilterMag := fFilterMag;
5171 Temp.fWrapS := fWrapS;
5172 Temp.fWrapT := fWrapT;
5173 Temp.fWrapR := fWrapR;
5174 Temp.fFilename := fFilename;
5175 Temp.fCustomName := fCustomName;
5176 Temp.fCustomNameW := fCustomNameW;
5177 Temp.fCustomData := fCustomData;
5186 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5187 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5189 SourceFD, DestFD: TFormatDescriptor;
5190 SourcePD, DestPD: TglBitmapPixelData;
5191 ShiftData: TShiftData;
5193 function CanCopyDirect: Boolean;
5196 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5197 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5198 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5199 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5202 function CanShift: Boolean;
5205 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5206 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5207 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5208 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5211 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5214 while (aSource > aDest) and (aSource > 0) do begin
5216 aSource := aSource shr 1;
5221 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5222 SourceFD := TFormatDescriptor.Get(Format);
5223 DestFD := TFormatDescriptor.Get(aFormat);
5225 SourceFD.PreparePixel(SourcePD);
5226 DestFD.PreparePixel (DestPD);
5228 if CanCopyDirect then
5229 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5230 else if CanShift then begin
5231 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5232 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5233 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5234 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5235 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5237 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5242 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5243 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5245 if aUseRGB or aUseAlpha then
5246 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5247 ((PtrInt(aUseAlpha) and 1) shl 1) or
5248 (PtrInt(aUseRGB) and 1) ));
5251 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5252 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5254 fBorderColor[0] := aRed;
5255 fBorderColor[1] := aGreen;
5256 fBorderColor[2] := aBlue;
5257 fBorderColor[3] := aAlpha;
5258 if (ID > 0) then begin
5260 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5264 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5265 procedure TglBitmap.FreeData;
5267 SetDataPointer(nil, tfEmpty);
5270 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5271 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5272 const aAlpha: Byte);
5274 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5277 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5278 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5280 PixelData: TglBitmapPixelData;
5282 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5284 aRed / PixelData.Range.r,
5285 aGreen / PixelData.Range.g,
5286 aBlue / PixelData.Range.b,
5287 aAlpha / PixelData.Range.a);
5290 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5291 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5293 PixelData: TglBitmapPixelData;
5295 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5296 with PixelData do begin
5297 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5298 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5299 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5300 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5302 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5305 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5306 procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal);
5311 fFilterMin := GL_NEAREST;
5313 fFilterMin := GL_LINEAR;
5314 GL_NEAREST_MIPMAP_NEAREST:
5315 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5316 GL_LINEAR_MIPMAP_NEAREST:
5317 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5318 GL_NEAREST_MIPMAP_LINEAR:
5319 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5320 GL_LINEAR_MIPMAP_LINEAR:
5321 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5323 raise EglBitmapException.Create('SetFilter - Unknow MIN filter.');
5329 fFilterMag := GL_NEAREST;
5331 fFilterMag := GL_LINEAR;
5333 raise EglBitmapException.Create('SetFilter - Unknow MAG filter.');
5337 if (ID > 0) then begin
5339 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5341 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5343 GL_NEAREST, GL_LINEAR:
5344 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5345 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5346 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5347 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5348 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5351 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5355 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5356 procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; const R: Cardinal);
5358 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5362 aTarget := GL_CLAMP;
5365 aTarget := GL_REPEAT;
5367 GL_CLAMP_TO_EDGE: begin
5368 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5369 aTarget := GL_CLAMP_TO_EDGE
5371 aTarget := GL_CLAMP;
5374 GL_CLAMP_TO_BORDER: begin
5375 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5376 aTarget := GL_CLAMP_TO_BORDER
5378 aTarget := GL_CLAMP;
5381 GL_MIRRORED_REPEAT: begin
5382 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5383 aTarget := GL_MIRRORED_REPEAT
5385 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5388 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).');
5393 CheckAndSetWrap(S, fWrapS);
5394 CheckAndSetWrap(T, fWrapT);
5395 CheckAndSetWrap(R, fWrapR);
5397 if (ID > 0) then begin
5399 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5400 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5401 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5405 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5406 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5408 if aEnableTextureUnit then
5411 glBindTexture(Target, ID);
5414 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5415 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5417 if aDisableTextureUnit then
5419 glBindTexture(Target, 0);
5422 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5423 constructor TglBitmap.Create;
5425 {$IFDEF GLB_NATIVE_OGL}
5426 glbReadOpenGLExtensions;
5428 if (ClassType = TglBitmap) then
5429 raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5433 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5434 constructor TglBitmap.Create(const aFileName: String);
5437 LoadFromFile(FileName);
5440 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5441 constructor TglBitmap.Create(const aStream: TStream);
5444 LoadFromStream(aStream);
5447 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5448 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
5454 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5455 GetMem(Image, ImageSize);
5457 FillChar(Image^, ImageSize, #$FF);
5458 SetDataPointer(Image, aFormat, aSize.X, aSize.Y);
5465 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5466 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
5467 const aFunc: TglBitmapFunction; const aArgs: Pointer);
5470 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5474 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5475 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5478 LoadFromResource(aInstance, aResource, aResType);
5481 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5482 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5485 LoadFromResourceID(aInstance, aResourceID, aResType);
5489 {$IFDEF GLB_SUPPORT_PNG_READ}
5490 {$IF DEFINED(GLB_SDL_IMAGE)}
5491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5492 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5493 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5494 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5496 Surface: PSDL_Surface;
5500 RWops := glBitmapCreateRWops(aStream);
5502 if IMG_isPNG(RWops) > 0 then begin
5503 Surface := IMG_LoadPNG_RW(RWops);
5505 AssignFromSurface(Surface);
5508 SDL_FreeSurface(Surface);
5516 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5517 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5518 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5520 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5523 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5524 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5527 signature: array [0..7] of byte;
5529 png_info: png_infop;
5531 TempHeight, TempWidth: Integer;
5532 Format: TglBitmapFormat;
5535 png_rows: array of pByte;
5536 Row, LineSize: Integer;
5540 if not init_libPNG then
5541 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5545 StreamPos := aStream.Position;
5546 aStream.Read(signature, 8);
5547 aStream.Position := StreamPos;
5549 if png_check_sig(@signature, 8) <> 0 then begin
5551 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5553 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5556 png_info := png_create_info_struct(png);
5557 if png_info = nil then begin
5558 png_destroy_read_struct(@png, nil, nil);
5559 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5562 // set read callback
5563 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5565 // read informations
5566 png_read_info(png, png_info);
5569 TempHeight := png_get_image_height(png, png_info);
5570 TempWidth := png_get_image_width(png, png_info);
5573 case png_get_color_type(png, png_info) of
5574 PNG_COLOR_TYPE_GRAY:
5575 Format := tfLuminance8;
5576 PNG_COLOR_TYPE_GRAY_ALPHA:
5577 Format := tfLuminance8Alpha8;
5580 PNG_COLOR_TYPE_RGB_ALPHA:
5583 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5586 // cut upper 8 bit from 16 bit formats
5587 if png_get_bit_depth(png, png_info) > 8 then
5588 png_set_strip_16(png);
5590 // expand bitdepth smaller than 8
5591 if png_get_bit_depth(png, png_info) < 8 then
5592 png_set_expand(png);
5594 // allocating mem for scanlines
5595 LineSize := png_get_rowbytes(png, png_info);
5596 GetMem(png_data, TempHeight * LineSize);
5598 SetLength(png_rows, TempHeight);
5599 for Row := Low(png_rows) to High(png_rows) do begin
5600 png_rows[Row] := png_data;
5601 Inc(png_rows[Row], Row * LineSize);
5604 // read complete image into scanlines
5605 png_read_image(png, @png_rows[0]);
5608 png_read_end(png, png_info);
5610 // destroy read struct
5611 png_destroy_read_struct(@png, @png_info, nil);
5613 SetLength(png_rows, 0);
5616 SetDataPointer(png_data, Format, TempWidth, TempHeight);
5629 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5630 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5631 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5635 Header: Array[0..7] of Byte;
5636 Row, Col, PixSize, LineSize: Integer;
5637 NewImage, pSource, pDest, pAlpha: pByte;
5638 Format: TglBitmapInternalFormat;
5641 PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10);
5646 StreamPos := Stream.Position;
5647 Stream.Read(Header[0], SizeOf(Header));
5648 Stream.Position := StreamPos;
5650 {Test if the header matches}
5651 if Header = PngHeader then begin
5652 Png := TPNGObject.Create;
5654 Png.LoadFromStream(Stream);
5656 case Png.Header.ColorType of
5658 Format := ifLuminance;
5659 COLOR_GRAYSCALEALPHA:
5660 Format := ifLuminanceAlpha;
5666 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5669 PixSize := Trunc(FormatGetSize(Format));
5670 LineSize := Integer(Png.Header.Width) * PixSize;
5672 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5676 case Png.Header.ColorType of
5677 COLOR_RGB, COLOR_GRAYSCALE:
5679 for Row := 0 to Png.Height -1 do begin
5680 Move (Png.Scanline[Row]^, pDest^, LineSize);
5681 Inc(pDest, LineSize);
5684 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5686 PixSize := PixSize -1;
5688 for Row := 0 to Png.Height -1 do begin
5689 pSource := Png.Scanline[Row];
5690 pAlpha := pByte(Png.AlphaScanline[Row]);
5692 for Col := 0 to Png.Width -1 do begin
5693 Move (pSource^, pDest^, PixSize);
5694 Inc(pSource, PixSize);
5695 Inc(pDest, PixSize);
5704 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5707 SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height);
5722 {$IFDEF GLB_SUPPORT_PNG_WRITE}
5723 {$IFDEF GLB_LIB_PNG}
5724 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5725 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5727 TStream(png_get_io_ptr(png)).Write(buffer^, size);
5731 {$IF DEFINED(GLB_LIB_PNG)}
5732 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5733 procedure TglBitmap.SavePNG(const aStream: TStream);
5736 png_info: png_infop;
5737 png_rows: array of pByte;
5741 FormatDesc: TFormatDescriptor;
5743 if not (ftPNG in FormatGetSupportedFiles(Format)) then
5744 raise EglBitmapUnsupportedFormat.Create(Format);
5746 if not init_libPNG then
5747 raise Exception.Create('unable to initialize libPNG.');
5751 tfAlpha8, tfLuminance8:
5752 ColorType := PNG_COLOR_TYPE_GRAY;
5754 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
5756 ColorType := PNG_COLOR_TYPE_RGB;
5758 ColorType := PNG_COLOR_TYPE_RGBA;
5760 raise EglBitmapUnsupportedFormat.Create(Format);
5763 FormatDesc := TFormatDescriptor.Get(Format);
5764 LineSize := FormatDesc.GetSize(Width, 1);
5766 // creating array for scanline
5767 SetLength(png_rows, Height);
5769 for Row := 0 to Height - 1 do begin
5770 png_rows[Row] := Data;
5771 Inc(png_rows[Row], Row * LineSize)
5775 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5777 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
5780 png_info := png_create_info_struct(png);
5781 if png_info = nil then begin
5782 png_destroy_write_struct(@png, nil);
5783 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
5786 // set read callback
5787 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
5790 png_set_compression_level(png, 6);
5792 if Format in [tfBGR8, tfBGRA8] then
5795 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
5796 png_write_info(png, png_info);
5797 png_write_image(png, @png_rows[0]);
5798 png_write_end(png, png_info);
5799 png_destroy_write_struct(@png, @png_info);
5801 SetLength(png_rows, 0);
5808 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5809 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5810 procedure TglBitmap.SavePNG(const aStream: TStream);
5814 pSource, pDest: pByte;
5815 X, Y, PixSize: Integer;
5816 ColorType: Cardinal;
5822 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
5823 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5825 case FInternalFormat of
5826 ifAlpha, ifLuminance, ifDepth8: begin
5827 ColorType := COLOR_GRAYSCALE;
5831 ifLuminanceAlpha: begin
5832 ColorType := COLOR_GRAYSCALEALPHA;
5836 ifBGR8, ifRGB8: begin
5837 ColorType := COLOR_RGB;
5841 ifBGRA8, ifRGBA8: begin
5842 ColorType := COLOR_RGBALPHA;
5847 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5850 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
5854 for Y := 0 to Height -1 do begin
5855 pDest := png.ScanLine[Y];
5856 for X := 0 to Width -1 do begin
5857 Move(pSource^, pDest^, PixSize);
5858 Inc(pDest, PixSize);
5859 Inc(pSource, PixSize);
5861 png.AlphaScanline[Y]^[X] := pSource^;
5866 // convert RGB line to BGR
5867 if InternalFormat in [ifRGB8, ifRGBA8] then begin
5868 pTemp := png.ScanLine[Y];
5869 for X := 0 to Width -1 do begin
5870 Temp := pByteArray(pTemp)^[0];
5871 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
5872 pByteArray(pTemp)^[2] := Temp;
5879 Png.CompressionLevel := 6;
5880 Png.SaveToStream(Stream);
5888 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5889 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5890 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5891 {$IFDEF GLB_LIB_JPEG}
5893 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
5894 glBitmap_libJPEG_source_mgr = record
5895 pub: jpeg_source_mgr;
5898 SrcBuffer: array [1..4096] of byte;
5901 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
5902 glBitmap_libJPEG_dest_mgr = record
5903 pub: jpeg_destination_mgr;
5905 DestStream: TStream;
5906 DestBuffer: array [1..4096] of byte;
5909 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5910 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
5912 src: glBitmap_libJPEG_source_mgr_ptr;
5915 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5917 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
5918 if (bytes <= 0) then begin
5919 src^.SrcBuffer[1] := $FF;
5920 src^.SrcBuffer[2] := JPEG_EOI;
5924 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
5925 src^.pub.bytes_in_buffer := bytes;
5930 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5931 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
5933 src: glBitmap_libJPEG_source_mgr_ptr;
5935 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5937 if num_bytes > 0 then begin
5938 // wanted byte isn't in buffer so set stream position and read buffer
5939 if num_bytes > src^.pub.bytes_in_buffer then begin
5940 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
5941 src^.pub.fill_input_buffer(cinfo);
5943 // wanted byte is in buffer so only skip
5944 inc(src^.pub.next_input_byte, num_bytes);
5945 dec(src^.pub.bytes_in_buffer, num_bytes);
5950 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5951 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
5953 dest: glBitmap_libJPEG_dest_mgr_ptr;
5955 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5957 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
5958 // write complete buffer
5959 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
5962 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
5963 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
5969 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5970 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
5973 dest: glBitmap_libJPEG_dest_mgr_ptr;
5975 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5977 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
5978 // check for endblock
5979 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
5981 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
5986 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
5991 {$IFDEF GLB_SUPPORT_JPEG_READ}
5992 {$IF DEFINED(GLB_SDL_IMAGE)}
5993 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5994 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
5996 Surface: PSDL_Surface;
6001 RWops := glBitmapCreateRWops(aStream);
6003 if IMG_isJPG(RWops) > 0 then begin
6004 Surface := IMG_LoadJPG_RW(RWops);
6006 AssignFromSurface(Surface);
6009 SDL_FreeSurface(Surface);
6017 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6018 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6019 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6022 Temp: array[0..1]of Byte;
6024 jpeg: jpeg_decompress_struct;
6025 jpeg_err: jpeg_error_mgr;
6027 IntFormat: TglBitmapInternalFormat;
6029 TempHeight, TempWidth: Integer;
6036 if not init_libJPEG then
6037 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6040 // reading first two bytes to test file and set cursor back to begin
6041 StreamPos := Stream.Position;
6042 Stream.Read(Temp[0], 2);
6043 Stream.Position := StreamPos;
6045 // if Bitmap then read file.
6046 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6047 FillChar(jpeg, SizeOf(jpeg_decompress_struct), $00);
6048 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
6051 jpeg.err := jpeg_std_error(@jpeg_err);
6052 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6053 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6055 // decompression struct
6056 jpeg_create_decompress(@jpeg);
6058 // allocation space for streaming methods
6059 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6061 // seeting up custom functions
6062 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6063 pub.init_source := glBitmap_libJPEG_init_source;
6064 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6065 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6066 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6067 pub.term_source := glBitmap_libJPEG_term_source;
6069 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6070 pub.next_input_byte := nil; // until buffer loaded
6072 SrcStream := Stream;
6075 // set global decoding state
6076 jpeg.global_state := DSTATE_START;
6078 // read header of jpeg
6079 jpeg_read_header(@jpeg, false);
6081 // setting output parameter
6082 case jpeg.jpeg_color_space of
6085 jpeg.out_color_space := JCS_GRAYSCALE;
6086 IntFormat := ifLuminance;
6089 jpeg.out_color_space := JCS_RGB;
6090 IntFormat := ifRGB8;
6094 jpeg_start_decompress(@jpeg);
6096 TempHeight := jpeg.output_height;
6097 TempWidth := jpeg.output_width;
6099 // creating new image
6100 GetMem(pImage, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
6104 for Row := 0 to TempHeight -1 do begin
6105 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6106 Inc(pTemp, Trunc(FormatGetSize(IntFormat) * TempWidth));
6109 // finish decompression
6110 jpeg_finish_decompress(@jpeg);
6112 // destroy decompression
6113 jpeg_destroy_decompress(@jpeg);
6115 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight);
6128 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6129 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6130 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6135 Temp: array[0..1]of Byte;
6139 // reading first two bytes to test file and set cursor back to begin
6140 StreamPos := Stream.Position;
6141 Stream.Read(Temp[0], 2);
6142 Stream.Position := StreamPos;
6144 // if Bitmap then read file.
6145 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6146 bmp := TBitmap.Create;
6148 jpg := TJPEGImage.Create;
6150 jpg.LoadFromStream(Stream);
6152 result := AssignFromBitmap(bmp);
6164 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6165 {$IF DEFEFINED(GLB_LIB_JPEG)}
6166 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6167 procedure TglBitmap.SaveJPEG(Stream: TStream);
6169 jpeg: jpeg_compress_struct;
6170 jpeg_err: jpeg_error_mgr;
6172 pTemp, pTemp2: pByte;
6174 procedure CopyRow(pDest, pSource: pByte);
6178 for X := 0 to Width - 1 do begin
6179 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6180 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6181 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6188 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6189 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
6191 if not init_libJPEG then
6192 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6195 FillChar(jpeg, SizeOf(jpeg_compress_struct), $00);
6196 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
6199 jpeg.err := jpeg_std_error(@jpeg_err);
6200 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6201 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6203 // compression struct
6204 jpeg_create_compress(@jpeg);
6206 // allocation space for streaming methods
6207 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6209 // seeting up custom functions
6210 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6211 pub.init_destination := glBitmap_libJPEG_init_destination;
6212 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6213 pub.term_destination := glBitmap_libJPEG_term_destination;
6215 pub.next_output_byte := @DestBuffer[1];
6216 pub.free_in_buffer := Length(DestBuffer);
6218 DestStream := Stream;
6221 // very important state
6222 jpeg.global_state := CSTATE_START;
6223 jpeg.image_width := Width;
6224 jpeg.image_height := Height;
6225 case InternalFormat of
6226 ifAlpha, ifLuminance, ifDepth8: begin
6227 jpeg.input_components := 1;
6228 jpeg.in_color_space := JCS_GRAYSCALE;
6230 ifRGB8, ifBGR8: begin
6231 jpeg.input_components := 3;
6232 jpeg.in_color_space := JCS_RGB;
6236 jpeg_set_defaults(@jpeg);
6237 jpeg_set_quality(@jpeg, 95, true);
6238 jpeg_start_compress(@jpeg, true);
6241 if InternalFormat = ifBGR8 then
6242 GetMem(pTemp2, fRowSize)
6247 for Row := 0 to jpeg.image_height -1 do begin
6249 if InternalFormat = ifBGR8 then
6250 CopyRow(pTemp2, pTemp)
6255 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6256 inc(pTemp, fRowSize);
6260 if InternalFormat = ifBGR8 then
6263 jpeg_finish_compress(@jpeg);
6264 jpeg_destroy_compress(@jpeg);
6270 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6271 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6272 procedure TglBitmap.SaveJPEG(Stream: TStream);
6277 if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then
6278 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
6280 Bmp := TBitmap.Create;
6282 Jpg := TJPEGImage.Create;
6284 AssignToBitmap(Bmp);
6285 if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
6286 Jpg.Grayscale := true;
6287 Jpg.PixelFormat := jf8Bit;
6290 Jpg.SaveToStream(Stream);
6301 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6302 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6303 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6310 BMP_COMP_BITFIELDS = 3;
6313 TBMPHeader = packed record
6318 bfOffBits: Cardinal;
6321 TBMPInfo = packed record
6327 biCompression: Cardinal;
6328 biSizeImage: Cardinal;
6329 biXPelsPerMeter: Longint;
6330 biYPelsPerMeter: Longint;
6331 biClrUsed: Cardinal;
6332 biClrImportant: Cardinal;
6335 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6336 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6338 //////////////////////////////////////////////////////////////////////////////////////////////////
6339 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6342 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6343 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6346 case aInfo.biCompression of
6348 BMP_COMP_RLE8: begin
6349 raise EglBitmapException.Create('RLE compression is not supported');
6351 BMP_COMP_BITFIELDS: begin
6352 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6353 aStream.Read(aMask.r, SizeOf(aMask.r));
6354 aStream.Read(aMask.g, SizeOf(aMask.g));
6355 aStream.Read(aMask.b, SizeOf(aMask.b));
6356 aStream.Read(aMask.a, SizeOf(aMask.a));
6358 raise EglBitmapException.Create('Bitfields are only supported for 16bit and 32bit formats');
6362 //get suitable format
6363 case aInfo.biBitCount of
6364 8: result := tfLuminance8;
6365 16: result := tfBGR5;
6366 24: result := tfBGR8;
6367 32: result := tfBGRA8;
6371 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6374 ColorTable: TbmpColorTable;
6377 if (aInfo.biBitCount >= 16) then
6379 aFormat := tfLuminance8;
6380 c := aInfo.biClrUsed;
6382 c := 1 shl aInfo.biBitCount;
6383 SetLength(ColorTable, c);
6384 for i := 0 to c-1 do begin
6385 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6386 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6390 result := TbmpColorTableFormat.Create;
6391 result.PixelSize := aInfo.biBitCount / 8;
6392 result.ColorTable := ColorTable;
6393 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6396 //////////////////////////////////////////////////////////////////////////////////////////////////
6397 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6398 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6400 TmpFormat: TglBitmapFormat;
6401 FormatDesc: TFormatDescriptor;
6404 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6405 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6406 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6407 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6408 aFormat := FormatDesc.Format;
6413 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6414 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6415 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6416 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6418 result := TbmpBitfieldFormat.Create;
6419 result.PixelSize := aInfo.biBitCount / 8;
6420 result.RedMask := aMask.r;
6421 result.GreenMask := aMask.g;
6422 result.BlueMask := aMask.b;
6423 result.AlphaMask := aMask.a;
6430 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6431 PaddingBuff: Cardinal;
6432 LineBuf, ImageData, TmpData: PByte;
6433 SourceMD, DestMD: Pointer;
6434 BmpFormat: TglBitmapFormat;
6437 Mask: TglBitmapColorRec;
6442 SpecialFormat: TFormatDescriptor;
6443 FormatDesc: TFormatDescriptor;
6445 //////////////////////////////////////////////////////////////////////////////////////////////////
6446 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6449 Pixel: TglBitmapPixelData;
6451 aStream.Read(aLineBuf^, rbLineSize);
6452 SpecialFormat.PreparePixel(Pixel);
6453 for i := 0 to Info.biWidth-1 do begin
6454 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6455 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6456 FormatDesc.Map(Pixel, aData, DestMD);
6462 BmpFormat := tfEmpty;
6463 SpecialFormat := nil;
6469 StartPos := aStream.Position;
6470 aStream.Read(Header{%H-}, SizeOf(Header));
6472 if Header.bfType = BMP_MAGIC then begin
6474 BmpFormat := ReadInfo(Info, Mask);
6475 SpecialFormat := ReadColorTable(BmpFormat, Info);
6476 if not Assigned(SpecialFormat) then
6477 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6478 aStream.Position := StartPos + Header.bfOffBits;
6480 if (BmpFormat <> tfEmpty) then begin
6481 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6482 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6483 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6484 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6487 DestMD := FormatDesc.CreateMappingData;
6488 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6489 GetMem(ImageData, ImageSize);
6490 if Assigned(SpecialFormat) then begin
6491 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6492 SourceMD := SpecialFormat.CreateMappingData;
6497 FillChar(ImageData^, ImageSize, $FF);
6498 TmpData := ImageData;
6499 if (Info.biHeight > 0) then
6500 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6501 for i := 0 to Abs(Info.biHeight)-1 do begin
6502 if Assigned(SpecialFormat) then
6503 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6505 aStream.Read(TmpData^, wbLineSize); //else only read data
6506 if (Info.biHeight > 0) then
6507 dec(TmpData, wbLineSize)
6509 inc(TmpData, wbLineSize);
6510 aStream.Read(PaddingBuff{%H-}, Padding);
6512 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight));
6515 if Assigned(LineBuf) then
6517 if Assigned(SourceMD) then
6518 SpecialFormat.FreeMappingData(SourceMD);
6519 FormatDesc.FreeMappingData(DestMD);
6526 raise EglBitmapException.Create('LoadBMP - No suitable format found');
6528 aStream.Position := StartPos;
6532 FreeAndNil(SpecialFormat);
6535 else aStream.Position := StartPos;
6538 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6539 procedure TglBitmap.SaveBMP(const aStream: TStream);
6543 Converter: TbmpColorTableFormat;
6544 FormatDesc: TFormatDescriptor;
6545 SourceFD, DestFD: Pointer;
6546 pData, srcData, dstData, ConvertBuffer: pByte;
6548 Pixel: TglBitmapPixelData;
6549 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6550 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6552 PaddingBuff: Cardinal;
6554 function GetLineWidth : Integer;
6556 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6560 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6561 raise EglBitmapUnsupportedFormat.Create(Format);
6564 FormatDesc := TFormatDescriptor.Get(Format);
6565 ImageSize := FormatDesc.GetSize(Dimension);
6567 FillChar(Header{%H-}, SizeOf(Header), 0);
6568 Header.bfType := BMP_MAGIC;
6569 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6570 Header.bfReserved1 := 0;
6571 Header.bfReserved2 := 0;
6572 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6574 FillChar(Info{%H-}, SizeOf(Info), 0);
6575 Info.biSize := SizeOf(Info);
6576 Info.biWidth := Width;
6577 Info.biHeight := Height;
6579 Info.biCompression := BMP_COMP_RGB;
6580 Info.biSizeImage := ImageSize;
6585 Info.biBitCount := 4;
6586 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6587 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6588 Converter := TbmpColorTableFormat.Create;
6589 Converter.PixelSize := 0.5;
6590 Converter.Format := Format;
6591 Converter.Range := glBitmapColorRec($F, $F, $F, $0);
6592 Converter.CreateColorTable;
6595 tfR3G3B2, tfLuminance8: begin
6596 Info.biBitCount := 8;
6597 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6598 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6599 Converter := TbmpColorTableFormat.Create;
6600 Converter.PixelSize := 1;
6601 Converter.Format := Format;
6602 if (Format = tfR3G3B2) then begin
6603 Converter.Range := glBitmapColorRec($7, $7, $3, $0);
6604 Converter.Shift := glBitmapShiftRec(0, 3, 6, 0);
6606 Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0);
6607 Converter.CreateColorTable;
6610 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6611 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6612 Info.biBitCount := 16;
6613 Info.biCompression := BMP_COMP_BITFIELDS;
6616 tfBGR8, tfRGB8: begin
6617 Info.biBitCount := 24;
6620 tfRGB10, tfRGB10A2, tfRGBA8,
6621 tfBGR10, tfBGR10A2, tfBGRA8: begin
6622 Info.biBitCount := 32;
6623 Info.biCompression := BMP_COMP_BITFIELDS;
6626 raise EglBitmapUnsupportedFormat.Create(Format);
6628 Info.biXPelsPerMeter := 2835;
6629 Info.biYPelsPerMeter := 2835;
6632 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6633 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
6634 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
6636 RedMask := FormatDesc.RedMask;
6637 GreenMask := FormatDesc.GreenMask;
6638 BlueMask := FormatDesc.BlueMask;
6639 AlphaMask := FormatDesc.AlphaMask;
6643 aStream.Write(Header, SizeOf(Header));
6644 aStream.Write(Info, SizeOf(Info));
6647 if Assigned(Converter) then
6648 aStream.Write(Converter.ColorTable[0].b,
6649 SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable));
6652 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6653 aStream.Write(RedMask, SizeOf(Cardinal));
6654 aStream.Write(GreenMask, SizeOf(Cardinal));
6655 aStream.Write(BlueMask, SizeOf(Cardinal));
6656 aStream.Write(AlphaMask, SizeOf(Cardinal));
6660 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
6661 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
6662 Padding := GetLineWidth - wbLineSize;
6666 inc(pData, (Height-1) * rbLineSize);
6668 // prepare row buffer. But only for RGB because RGBA supports color masks
6669 // so it's possible to change color within the image.
6670 if Assigned(Converter) then begin
6671 FormatDesc.PreparePixel(Pixel);
6672 GetMem(ConvertBuffer, wbLineSize);
6673 SourceFD := FormatDesc.CreateMappingData;
6674 DestFD := Converter.CreateMappingData;
6676 ConvertBuffer := nil;
6679 for LineIdx := 0 to Height - 1 do begin
6681 if Assigned(Converter) then begin
6683 dstData := ConvertBuffer;
6684 for PixelIdx := 0 to Info.biWidth-1 do begin
6685 FormatDesc.Unmap(srcData, Pixel, SourceFD);
6686 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
6687 Converter.Map(Pixel, dstData, DestFD);
6689 aStream.Write(ConvertBuffer^, wbLineSize);
6691 aStream.Write(pData^, rbLineSize);
6693 dec(pData, rbLineSize);
6694 if (Padding > 0) then
6695 aStream.Write(PaddingBuff, Padding);
6698 // destroy row buffer
6699 if Assigned(ConvertBuffer) then begin
6700 FormatDesc.FreeMappingData(SourceFD);
6701 Converter.FreeMappingData(DestFD);
6702 FreeMem(ConvertBuffer);
6706 if Assigned(Converter) then
6711 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6712 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6713 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6715 TTGAHeader = packed record
6719 //ColorMapSpec: Array[0..4] of Byte;
6720 ColorMapStart: Word;
6721 ColorMapLength: Word;
6722 ColorMapEntrySize: Byte;
6732 TGA_UNCOMPRESSED_RGB = 2;
6733 TGA_UNCOMPRESSED_GRAY = 3;
6734 TGA_COMPRESSED_RGB = 10;
6735 TGA_COMPRESSED_GRAY = 11;
6737 TGA_NONE_COLOR_TABLE = 0;
6739 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6740 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
6743 ImageData: System.PByte;
6744 StartPosition: Int64;
6745 PixelSize, LineSize: Integer;
6746 tgaFormat: TglBitmapFormat;
6747 FormatDesc: TFormatDescriptor;
6748 Counter: packed record
6750 low, high, dir: Integer;
6757 ////////////////////////////////////////////////////////////////////////////////////////
6758 procedure ReadUncompressed;
6761 buf, tmp1, tmp2: System.PByte;
6764 if (Counter.X.dir < 0) then
6765 buf := GetMem(LineSize);
6767 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
6768 tmp1 := ImageData + (Counter.Y.low * LineSize); //pointer to LineStart
6769 if (Counter.X.dir < 0) then begin //flip X
6770 aStream.Read(buf^, LineSize);
6771 tmp2 := buf + LineSize - PixelSize; //pointer to last pixel in line
6772 for i := 0 to Header.Width-1 do begin //for all pixels in line
6773 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
6778 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
6781 aStream.Read(tmp1^, LineSize);
6782 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
6785 if Assigned(buf) then
6790 ////////////////////////////////////////////////////////////////////////////////////////
6791 procedure ReadCompressed;
6793 /////////////////////////////////////////////////////////////////
6795 TmpData: System.PByte;
6796 LinePixelsRead: Integer;
6797 procedure CheckLine;
6799 if (LinePixelsRead >= Header.Width) then begin
6800 LinePixelsRead := 0;
6801 inc(Counter.Y.low, Counter.Y.dir); //next line index
6802 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6803 if (Counter.X.dir < 0) then //if x flipped then
6804 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6808 /////////////////////////////////////////////////////////////////
6811 CacheSize, CachePos: Integer;
6812 procedure CachedRead(out Buffer; Count: Integer);
6816 if (CachePos + Count > CacheSize) then begin
6817 //if buffer overflow save non read bytes
6819 if (CacheSize - CachePos > 0) then begin
6820 BytesRead := CacheSize - CachePos;
6821 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
6822 inc(CachePos, BytesRead);
6825 //load cache from file
6826 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
6827 aStream.Read(Cache^, CacheSize);
6830 //read rest of requested bytes
6831 if (Count - BytesRead > 0) then begin
6832 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
6833 inc(CachePos, Count - BytesRead);
6836 //if no buffer overflow just read the data
6837 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
6838 inc(CachePos, Count);
6842 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
6847 inc(aBuffer, Counter.X.dir);
6850 PWord(aBuffer)^ := PWord(aData)^;
6851 inc(aBuffer, 2 * Counter.X.dir);
6854 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
6855 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
6856 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
6857 inc(aBuffer, 3 * Counter.X.dir);
6860 PCardinal(aBuffer)^ := PCardinal(aData)^;
6861 inc(aBuffer, 4 * Counter.X.dir);
6867 TotalPixelsToRead, TotalPixelsRead: Integer;
6869 buf: array [0..3] of Byte; //1 pixel is max 32bit long
6870 PixelRepeat: Boolean;
6871 PixelsToRead, PixelCount: Integer;
6876 TotalPixelsToRead := Header.Width * Header.Height;
6877 TotalPixelsRead := 0;
6878 LinePixelsRead := 0;
6880 GetMem(Cache, CACHE_SIZE);
6882 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6883 if (Counter.X.dir < 0) then //if x flipped then
6884 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6888 CachedRead(Temp, 1);
6889 PixelRepeat := (Temp and $80) > 0;
6890 PixelsToRead := (Temp and $7F) + 1;
6891 inc(TotalPixelsRead, PixelsToRead);
6894 CachedRead(buf[0], PixelSize);
6895 while (PixelsToRead > 0) do begin
6897 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
6898 while (PixelCount > 0) do begin
6899 if not PixelRepeat then
6900 CachedRead(buf[0], PixelSize);
6901 PixelToBuffer(@buf[0], TmpData);
6902 inc(LinePixelsRead);
6907 until (TotalPixelsRead >= TotalPixelsToRead);
6913 function IsGrayFormat: Boolean;
6915 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
6921 // reading header to test file and set cursor back to begin
6922 StartPosition := aStream.Position;
6923 aStream.Read(Header{%H-}, SizeOf(Header));
6925 // no colormapped files
6926 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
6927 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
6930 if Header.ImageID <> 0 then // skip image ID
6931 aStream.Position := aStream.Position + Header.ImageID;
6934 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
6935 0: tgaFormat := tfLuminance8;
6936 8: tgaFormat := tfAlpha8;
6939 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
6940 0: tgaFormat := tfLuminance16;
6941 8: tgaFormat := tfLuminance8Alpha8;
6942 end else case (Header.ImageDesc and $F) of
6943 0: tgaFormat := tfBGR5;
6944 1: tgaFormat := tfBGR5A1;
6945 4: tgaFormat := tfBGRA4;
6948 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6949 0: tgaFormat := tfBGR8;
6952 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6953 2: tgaFormat := tfBGR10A2;
6954 8: tgaFormat := tfBGRA8;
6958 if (tgaFormat = tfEmpty) then
6959 raise EglBitmapException.Create('LoadTga - unsupported format');
6961 FormatDesc := TFormatDescriptor.Get(tgaFormat);
6962 PixelSize := FormatDesc.GetSize(1, 1);
6963 LineSize := FormatDesc.GetSize(Header.Width, 1);
6965 GetMem(ImageData, LineSize * Header.Height);
6968 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
6969 Counter.X.low := Header.Height-1;;
6970 Counter.X.high := 0;
6971 Counter.X.dir := -1;
6974 Counter.X.high := Header.Height-1;
6979 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
6981 Counter.Y.high := Header.Height-1;
6984 Counter.Y.low := Header.Height-1;;
6985 Counter.Y.high := 0;
6986 Counter.Y.dir := -1;
6990 case Header.ImageType of
6991 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
6993 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
6997 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height);
7004 aStream.Position := StartPosition;
7007 else aStream.Position := StartPosition;
7010 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7011 procedure TglBitmap.SaveTGA(const aStream: TStream);
7014 LineSize, Size, x, y: Integer;
7015 Pixel: TglBitmapPixelData;
7016 LineBuf, SourceData, DestData: PByte;
7017 SourceMD, DestMD: Pointer;
7018 FormatDesc: TFormatDescriptor;
7019 Converter: TFormatDescriptor;
7021 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7022 raise EglBitmapUnsupportedFormat.Create(Format);
7025 FillChar(Header{%H-}, SizeOf(Header), 0);
7028 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7029 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7030 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7032 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7035 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7037 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7038 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7040 else if (Format in [tfBGR8, tfRGB8]) then
7048 Header.ImageDesc := 1 and $F;
7049 tfRGB10A2, tfBGR10A2:
7050 Header.ImageDesc := 2 and $F;
7052 Header.ImageDesc := 4 and $F;
7053 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7054 Header.ImageDesc := 8 and $F;
7057 Header.Width := Width;
7058 Header.Height := Height;
7059 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7060 aStream.Write(Header, SizeOf(Header));
7062 // convert RGB(A) to BGR(A)
7064 FormatDesc := TFormatDescriptor.Get(Format);
7065 Size := FormatDesc.GetSize(Dimension);
7066 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7067 if (FormatDesc.RGBInverted = tfEmpty) then
7068 raise EglBitmapException.Create('inverted RGB format is empty');
7069 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7070 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7071 (Converter.PixelSize <> FormatDesc.PixelSize) then
7072 raise EglBitmapException.Create('invalid inverted RGB format');
7075 if Assigned(Converter) then begin
7076 LineSize := FormatDesc.GetSize(Width, 1);
7077 LineBuf := GetMem(LineSize);
7078 SourceMD := FormatDesc.CreateMappingData;
7079 DestMD := Converter.CreateMappingData;
7082 for y := 0 to Height-1 do begin
7083 DestData := LineBuf;
7084 for x := 0 to Width-1 do begin
7085 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7086 Converter.Map(Pixel, DestData, DestMD);
7088 aStream.Write(LineBuf^, LineSize);
7092 FormatDesc.FreeMappingData(SourceMD);
7093 FormatDesc.FreeMappingData(DestMD);
7096 aStream.Write(Data^, Size);
7099 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7100 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7101 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7103 DDS_MAGIC: Cardinal = $20534444;
7105 // DDS_header.dwFlags
7106 DDSD_CAPS = $00000001;
7107 DDSD_HEIGHT = $00000002;
7108 DDSD_WIDTH = $00000004;
7109 DDSD_PIXELFORMAT = $00001000;
7111 // DDS_header.sPixelFormat.dwFlags
7112 DDPF_ALPHAPIXELS = $00000001;
7113 DDPF_ALPHA = $00000002;
7114 DDPF_FOURCC = $00000004;
7115 DDPF_RGB = $00000040;
7116 DDPF_LUMINANCE = $00020000;
7118 // DDS_header.sCaps.dwCaps1
7119 DDSCAPS_TEXTURE = $00001000;
7121 // DDS_header.sCaps.dwCaps2
7122 DDSCAPS2_CUBEMAP = $00000200;
7124 D3DFMT_DXT1 = $31545844;
7125 D3DFMT_DXT3 = $33545844;
7126 D3DFMT_DXT5 = $35545844;
7129 TDDSPixelFormat = packed record
7133 dwRGBBitCount: Cardinal;
7134 dwRBitMask: Cardinal;
7135 dwGBitMask: Cardinal;
7136 dwBBitMask: Cardinal;
7137 dwABitMask: Cardinal;
7140 TDDSCaps = packed record
7144 dwReserved: Cardinal;
7147 TDDSHeader = packed record
7152 dwPitchOrLinearSize: Cardinal;
7154 dwMipMapCount: Cardinal;
7155 dwReserved: array[0..10] of Cardinal;
7156 PixelFormat: TDDSPixelFormat;
7158 dwReserved2: Cardinal;
7161 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7162 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7165 Converter: TbmpBitfieldFormat;
7167 function GetDDSFormat: TglBitmapFormat;
7169 fd: TFormatDescriptor;
7171 Range: TglBitmapColorRec;
7175 with Header.PixelFormat do begin
7177 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7178 case Header.PixelFormat.dwFourCC of
7179 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7180 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7181 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7183 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7185 //find matching format
7186 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7187 fd := TFormatDescriptor.Get(result);
7188 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7189 (8 * fd.PixelSize = dwRGBBitCount) then
7193 //find format with same Range
7194 Range.r := dwRBitMask;
7195 Range.g := dwGBitMask;
7196 Range.b := dwBBitMask;
7197 Range.a := dwABitMask;
7198 for i := 0 to 3 do begin
7199 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7200 Range.arr[i] := Range.arr[i] shr 1;
7202 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7203 fd := TFormatDescriptor.Get(result);
7206 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7214 //no format with same range found -> use default
7215 if (result = tfEmpty) then begin
7216 if (dwABitMask > 0) then
7222 Converter := TbmpBitfieldFormat.Create;
7223 Converter.RedMask := dwRBitMask;
7224 Converter.GreenMask := dwGBitMask;
7225 Converter.BlueMask := dwBBitMask;
7226 Converter.AlphaMask := dwABitMask;
7227 Converter.PixelSize := dwRGBBitCount / 8;
7234 x, y, LineSize, RowSize, Magic: Cardinal;
7235 NewImage, TmpData, RowData, SrcData: System.PByte;
7236 SourceMD, DestMD: Pointer;
7237 Pixel: TglBitmapPixelData;
7238 ddsFormat: TglBitmapFormat;
7239 FormatDesc: TFormatDescriptor;
7244 StreamPos := aStream.Position;
7247 aStream.Read(Magic{%H-}, sizeof(Magic));
7248 if (Magic <> DDS_MAGIC) then begin
7249 aStream.Position := StreamPos;
7254 aStream.Read(Header{%H-}, sizeof(Header));
7255 if (Header.dwSize <> SizeOf(Header)) or
7256 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7257 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7259 aStream.Position := StreamPos;
7263 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7264 raise EglBitmapException.Create('LoadDDS - CubeMaps are not supported');
7266 ddsFormat := GetDDSFormat;
7268 if (ddsFormat = tfEmpty) then
7269 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7271 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7272 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7273 GetMem(NewImage, Header.dwHeight * LineSize);
7275 TmpData := NewImage;
7278 if Assigned(Converter) then begin
7279 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7280 GetMem(RowData, RowSize);
7281 SourceMD := Converter.CreateMappingData;
7282 DestMD := FormatDesc.CreateMappingData;
7284 for y := 0 to Header.dwHeight-1 do begin
7285 TmpData := NewImage + y * LineSize;
7287 aStream.Read(SrcData^, RowSize);
7288 for x := 0 to Header.dwWidth-1 do begin
7289 Converter.Unmap(SrcData, Pixel, SourceMD);
7290 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7291 FormatDesc.Map(Pixel, TmpData, DestMD);
7295 Converter.FreeMappingData(SourceMD);
7296 FormatDesc.FreeMappingData(DestMD);
7302 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7303 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7304 for Y := 0 to Header.dwHeight-1 do begin
7305 aStream.Read(TmpData^, RowSize);
7306 Inc(TmpData, LineSize);
7311 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7312 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7313 for Y := 0 to Header.dwHeight-1 do begin
7314 aStream.Read(TmpData^, RowSize);
7315 Inc(TmpData, LineSize);
7318 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7320 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
7327 FreeAndNil(Converter);
7331 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7332 procedure TglBitmap.SaveDDS(const aStream: TStream);
7335 FormatDesc: TFormatDescriptor;
7337 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7338 raise EglBitmapUnsupportedFormat.Create(Format);
7340 FormatDesc := TFormatDescriptor.Get(Format);
7343 FillChar(Header{%H-}, SizeOf(Header), 0);
7344 Header.dwSize := SizeOf(Header);
7345 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7347 Header.dwWidth := Max(1, Width);
7348 Header.dwHeight := Max(1, Height);
7351 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7354 Header.PixelFormat.dwSize := sizeof(Header);
7355 if (FormatDesc.IsCompressed) then begin
7356 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7358 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7359 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7360 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7362 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7363 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7364 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7365 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7366 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7367 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7368 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7369 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7370 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7372 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7373 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7374 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7375 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7376 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7377 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7380 if (FormatDesc.HasAlpha) then
7381 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7383 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7384 aStream.Write(Header, SizeOf(Header));
7385 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7388 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7389 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7390 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7391 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7393 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7394 result := fLines[aIndex]
7399 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7400 procedure TglBitmap2D.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
7401 const aWidth: Integer; const aHeight: Integer);
7403 Idx, LineWidth: Integer;
7405 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7407 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7409 fGetPixelFunc := GetPixel2DUnmap;
7410 fSetPixelFunc := SetPixel2DUnmap;
7413 if Assigned(Data) then begin
7414 SetLength(fLines, GetHeight);
7415 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7417 for Idx := 0 to GetHeight -1 do begin
7418 fLines[Idx] := Data;
7419 Inc(fLines[Idx], Idx * LineWidth);
7422 else SetLength(fLines, 0);
7424 SetLength(fLines, 0);
7426 fSetPixelFunc := nil;
7430 fGetPixelFunc := GetPixel2DDXT1;
7432 fGetPixelFunc := GetPixel2DDXT3;
7434 fGetPixelFunc := GetPixel2DDXT5;
7436 fGetPixelFunc := nil;
7442 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7443 procedure TglBitmap2D.UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
7445 FormatDesc: TFormatDescriptor;
7447 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7449 FormatDesc := TFormatDescriptor.Get(Format);
7450 if FormatDesc.IsCompressed then begin
7451 glCompressedTexImage2D(Target, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7452 end else if aBuildWithGlu then begin
7453 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7454 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7456 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7457 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7461 if (FreeDataAfterGenTexture) then
7465 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7466 procedure TglBitmap2D.AfterConstruction;
7469 Target := GL_TEXTURE_2D;
7472 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7473 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7476 Size, w, h: Integer;
7477 FormatDesc: TFormatDescriptor;
7479 FormatDesc := TFormatDescriptor.Get(Format);
7480 if FormatDesc.IsCompressed then
7481 raise EglBitmapUnsupportedFormat.Create(Format);
7483 w := aRight - aLeft;
7484 h := aBottom - aTop;
7485 Size := FormatDesc.GetSize(w, h);
7488 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7489 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7490 SetDataPointer(Temp, Format, w, h);
7498 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7499 procedure TglBitmap2D.GetDataFromTexture;
7502 TempWidth, TempHeight: Integer;
7503 TempIntFormat: Cardinal;
7504 IntFormat, f: TglBitmapFormat;
7505 FormatDesc: TFormatDescriptor;
7510 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7511 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7512 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7514 IntFormat := tfEmpty;
7515 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
7516 FormatDesc := TFormatDescriptor.Get(f);
7517 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
7518 IntFormat := FormatDesc.Format;
7523 // Getting data from OpenGL
7524 FormatDesc := TFormatDescriptor.Get(IntFormat);
7525 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
7527 if FormatDesc.IsCompressed then
7528 glGetCompressedTexImage(Target, 0, Temp)
7530 glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
7531 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
7538 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7539 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
7541 BuildWithGlu, PotTex, TexRec: Boolean;
7544 if Assigned(Data) then begin
7545 // Check Texture Size
7546 if (aTestTextureSize) then begin
7547 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7549 if ((Height > TexSize) or (Width > TexSize)) then
7550 raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7552 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
7553 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
7555 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7556 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7560 SetupParameters(BuildWithGlu);
7561 UploadData(Target, BuildWithGlu);
7562 glAreTexturesResident(1, @fID, @fIsResident);
7566 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7567 function TglBitmap2D.FlipHorz: Boolean;
7570 TempDestData, DestData, SourceData: PByte;
7573 result := inherited FlipHorz;
7574 if Assigned(Data) then begin
7576 ImgSize := Height * fRowSize;
7577 GetMem(DestData, ImgSize);
7579 TempDestData := DestData;
7580 Dec(TempDestData, fRowSize + fPixelSize);
7581 for Row := 0 to Height -1 do begin
7582 Inc(TempDestData, fRowSize * 2);
7583 for Col := 0 to Width -1 do begin
7584 Move(SourceData^, TempDestData^, fPixelSize);
7585 Inc(SourceData, fPixelSize);
7586 Dec(TempDestData, fPixelSize);
7589 SetDataPointer(DestData, Format);
7598 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7599 function TglBitmap2D.FlipVert: Boolean;
7602 TempDestData, DestData, SourceData: PByte;
7604 result := inherited FlipVert;
7605 if Assigned(Data) then begin
7607 GetMem(DestData, Height * fRowSize);
7609 TempDestData := DestData;
7610 Inc(TempDestData, Width * (Height -1) * fPixelSize);
7611 for Row := 0 to Height -1 do begin
7612 Move(SourceData^, TempDestData^, fRowSize);
7613 Dec(TempDestData, fRowSize);
7614 Inc(SourceData, fRowSize);
7616 SetDataPointer(DestData, Format);
7625 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7626 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7627 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7629 TMatrixItem = record
7634 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
7635 TglBitmapToNormalMapRec = Record
7637 Heights: array of Single;
7638 MatrixU : array of TMatrixItem;
7639 MatrixV : array of TMatrixItem;
7643 ONE_OVER_255 = 1 / 255;
7645 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7646 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
7650 with FuncRec do begin
7652 Source.Data.r * LUMINANCE_WEIGHT_R +
7653 Source.Data.g * LUMINANCE_WEIGHT_G +
7654 Source.Data.b * LUMINANCE_WEIGHT_B;
7655 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
7659 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7660 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
7663 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
7666 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7667 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
7669 TVec = Array[0..2] of Single;
7676 function GetHeight(X, Y: Integer): Single;
7678 with FuncRec do begin
7679 X := Max(0, Min(Size.X -1, X));
7680 Y := Max(0, Min(Size.Y -1, Y));
7681 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
7686 with FuncRec do begin
7687 with PglBitmapToNormalMapRec(Args)^ do begin
7689 for Idx := Low(MatrixU) to High(MatrixU) do
7690 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
7693 for Idx := Low(MatrixU) to High(MatrixU) do
7694 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
7696 Vec[0] := -du * Scale;
7697 Vec[1] := -dv * Scale;
7702 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
7703 if Len <> 0 then begin
7704 Vec[0] := Vec[0] * Len;
7705 Vec[1] := Vec[1] * Len;
7706 Vec[2] := Vec[2] * Len;
7710 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
7711 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
7712 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
7716 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7717 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
7719 Rec: TglBitmapToNormalMapRec;
7721 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
7723 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
7724 Matrix[Index].X := X;
7725 Matrix[Index].Y := Y;
7726 Matrix[Index].W := W;
7731 if TFormatDescriptor.Get(Format).IsCompressed then
7732 raise EglBitmapUnsupportedFormat.Create(Format);
7734 if aScale > 100 then
7736 else if aScale < -100 then
7739 Rec.Scale := aScale;
7741 SetLength(Rec.Heights, Width * Height);
7745 SetLength(Rec.MatrixU, 2);
7746 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
7747 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
7749 SetLength(Rec.MatrixV, 2);
7750 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
7751 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
7755 SetLength(Rec.MatrixU, 6);
7756 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
7757 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
7758 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
7759 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
7760 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
7761 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
7763 SetLength(Rec.MatrixV, 6);
7764 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
7765 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
7766 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
7767 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
7768 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
7769 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
7773 SetLength(Rec.MatrixU, 6);
7774 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
7775 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
7776 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
7777 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
7778 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
7779 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
7781 SetLength(Rec.MatrixV, 6);
7782 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
7783 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
7784 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
7785 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
7786 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
7787 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
7791 SetLength(Rec.MatrixU, 20);
7792 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
7793 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
7794 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
7795 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
7796 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
7797 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
7798 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
7799 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
7800 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
7801 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
7802 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
7803 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
7804 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
7805 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
7806 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
7807 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
7808 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
7809 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
7810 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
7811 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
7813 SetLength(Rec.MatrixV, 20);
7814 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
7815 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
7816 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
7817 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
7818 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
7819 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
7820 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
7821 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
7822 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
7823 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
7824 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
7825 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
7826 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
7827 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
7828 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
7829 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
7830 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
7831 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
7832 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
7833 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
7838 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
7839 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
7841 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
7842 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
7844 SetLength(Rec.Heights, 0);
7857 procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
7862 if Height > 1 then begin
7863 // extract first line of the data
7864 Size := FormatGetImageSize(glBitmapPosition(Width), Format);
7865 GetMem(pTemp, Size);
7867 Move(Data^, pTemp^, Size);
7874 inherited SetDataPointer(pTemp, Format, Width);
7876 if FormatIsUncompressed(Format) then begin
7877 fUnmapFunc := FormatGetUnMapFunc(Format);
7878 fGetPixelFunc := GetPixel1DUnmap;
7883 procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
7888 Inc(pTemp, Pos.X * fPixelSize);
7890 fUnmapFunc(pTemp, Pixel);
7894 function TglBitmap1D.FlipHorz: Boolean;
7897 pTempDest, pDest, pSource: pByte;
7899 result := inherited FlipHorz;
7901 if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin
7904 GetMem(pDest, fRowSize);
7908 Inc(pTempDest, fRowSize);
7909 for Col := 0 to Width -1 do begin
7910 Move(pSource^, pTempDest^, fPixelSize);
7912 Inc(pSource, fPixelSize);
7913 Dec(pTempDest, fPixelSize);
7916 SetDataPointer(pDest, InternalFormat);
7926 procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
7929 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
7930 glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data)
7934 if BuildWithGlu then
7935 gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data)
7937 glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data);
7940 if (FreeDataAfterGenTexture) then
7945 procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean);
7947 BuildWithGlu, TexRec: Boolean;
7948 glFormat, glInternalFormat, glType: Cardinal;
7951 if Assigned(Data) then begin
7952 // Check Texture Size
7953 if (TestTextureSize) then begin
7954 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7956 if (Width > TexSize) then
7957 raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7959 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7960 (Target = GL_TEXTURE_RECTANGLE_ARB);
7962 if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7963 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7968 SetupParameters(BuildWithGlu);
7969 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
7971 UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
7974 glAreTexturesResident(1, @fID, @fIsResident);
7979 procedure TglBitmap1D.AfterConstruction;
7983 Target := GL_TEXTURE_1D;
7987 { TglBitmapCubeMap }
7989 procedure TglBitmapCubeMap.AfterConstruction;
7993 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
7994 raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
7996 SetWrap; // set all to GL_CLAMP_TO_EDGE
7997 Target := GL_TEXTURE_CUBE_MAP;
7998 fGenMode := GL_REFLECTION_MAP;
8002 procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean);
8004 inherited Bind (EnableTextureUnit);
8006 if EnableTexCoordsGen then begin
8007 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8008 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8009 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8010 glEnable(GL_TEXTURE_GEN_S);
8011 glEnable(GL_TEXTURE_GEN_T);
8012 glEnable(GL_TEXTURE_GEN_R);
8017 procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean);
8019 glFormat, glInternalFormat, glType: Cardinal;
8020 BuildWithGlu: Boolean;
8023 // Check Texture Size
8024 if (TestTextureSize) then begin
8025 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8027 if ((Height > TexSize) or (Width > TexSize)) then
8028 raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8030 if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8031 raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8035 if ID = 0 then begin
8037 SetupParameters(BuildWithGlu);
8040 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
8042 UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu);
8046 procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean);
8048 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8052 procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen,
8053 DisableTextureUnit: Boolean);
8055 inherited Unbind (DisableTextureUnit);
8057 if DisableTexCoordsGen then begin
8058 glDisable(GL_TEXTURE_GEN_S);
8059 glDisable(GL_TEXTURE_GEN_T);
8060 glDisable(GL_TEXTURE_GEN_R);
8065 { TglBitmapNormalMap }
8068 TVec = Array[0..2] of Single;
8069 TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8071 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8072 TglBitmapNormalMapRec = record
8074 Func: TglBitmapNormalMapGetVectorFunc;
8078 procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8081 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8082 Vec[2] := - (Position.X + 0.5 - HalfSize);
8086 procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8088 Vec[0] := - HalfSize;
8089 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8090 Vec[2] := Position.X + 0.5 - HalfSize;
8094 procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8096 Vec[0] := Position.X + 0.5 - HalfSize;
8098 Vec[2] := Position.Y + 0.5 - HalfSize;
8102 procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8104 Vec[0] := Position.X + 0.5 - HalfSize;
8105 Vec[1] := - HalfSize;
8106 Vec[2] := - (Position.Y + 0.5 - HalfSize);
8110 procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8112 Vec[0] := Position.X + 0.5 - HalfSize;
8113 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8118 procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8120 Vec[0] := - (Position.X + 0.5 - HalfSize);
8121 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8122 Vec[2] := - HalfSize;
8126 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8131 with FuncRec do begin
8132 with PglBitmapNormalMapRec (CustomData)^ do begin
8133 Func(Vec, Position, HalfSize);
8136 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8137 if Len <> 0 then begin
8138 Vec[0] := Vec[0] * Len;
8139 Vec[1] := Vec[1] * Len;
8140 Vec[2] := Vec[2] * Len;
8143 // Scale Vector and AddVectro
8144 Vec[0] := Vec[0] * 0.5 + 0.5;
8145 Vec[1] := Vec[1] * 0.5 + 0.5;
8146 Vec[2] := Vec[2] * 0.5 + 0.5;
8150 Dest.Red := Round(Vec[0] * 255);
8151 Dest.Green := Round(Vec[1] * 255);
8152 Dest.Blue := Round(Vec[2] * 255);
8157 procedure TglBitmapNormalMap.AfterConstruction;
8161 fGenMode := GL_NORMAL_MAP;
8165 procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer;
8166 TestTextureSize: Boolean);
8168 Rec: TglBitmapNormalMapRec;
8169 SizeRec: TglBitmapPixelPosition;
8171 Rec.HalfSize := Size div 2;
8173 FreeDataAfterGenTexture := false;
8175 SizeRec.Fields := [ffX, ffY];
8180 Rec.Func := glBitmapNormalMapPosX;
8181 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8182 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize);
8185 Rec.Func := glBitmapNormalMapNegX;
8186 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8187 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize);
8190 Rec.Func := glBitmapNormalMapPosY;
8191 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8192 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize);
8195 Rec.Func := glBitmapNormalMapNegY;
8196 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8197 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize);
8200 Rec.Func := glBitmapNormalMapPosZ;
8201 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8202 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize);
8205 Rec.Func := glBitmapNormalMapNegZ;
8206 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8207 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize);
8212 glBitmapSetDefaultFormat(tfEmpty);
8213 glBitmapSetDefaultMipmap(mmMipmap);
8214 glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8215 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8217 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8218 glBitmapSetDefaultDeleteTextureOnFree (true);
8220 TFormatDescriptor.Init;
8222 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8223 OpenGLInitialized := false;
8224 InitOpenGLCS := TCriticalSection.Create;
8228 TFormatDescriptor.Finalize;
8230 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8231 FreeAndNil(InitOpenGLCS);