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 // PNG /////////////////////////////////////////////////////////////////////////////////////////////
249 // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/
250 // if you enable pngimage the libPNG will be ignored
251 {.$DEFINE GLB_PNGIMAGE}
253 // activate to use the libPNG -> http://www.libpng.org/
254 // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libpng
255 {.$DEFINE GLB_LIB_PNG}
257 // JPEG ////////////////////////////////////////////////////////////////////////////////////////////
258 // if you enable delphi jpegs the libJPEG will be ignored
259 {.$DEFINE GLB_DELPHI_JPEG}
261 // activate to use the libJPEG -> http://www.ijg.org/
262 // You will need an aditional header -> 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];
1780 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1781 if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then
1782 result := result + [ftJPEG];
1786 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1787 function IsPowerOfTwo(aNumber: Integer): Boolean;
1789 while (aNumber and 1) = 0 do
1790 aNumber := aNumber shr 1;
1791 result := aNumber = 1;
1794 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1795 function GetTopMostBit(aBitSet: QWord): Integer;
1798 while aBitSet > 0 do begin
1800 aBitSet := aBitSet shr 1;
1804 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1805 function CountSetBits(aBitSet: QWord): Integer;
1808 while aBitSet > 0 do begin
1809 if (aBitSet and 1) = 1 then
1811 aBitSet := aBitSet shr 1;
1815 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1816 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1819 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1820 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1821 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1824 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1825 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1828 DEPTH_WEIGHT_R * aPixel.Data.r +
1829 DEPTH_WEIGHT_G * aPixel.Data.g +
1830 DEPTH_WEIGHT_B * aPixel.Data.b);
1833 {$IFDEF GLB_NATIVE_OGL}
1834 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1835 //OpenGLInitialization///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1836 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1838 GL_LibHandle: Pointer = nil;
1840 function glbGetProcAddress(aProcName: PChar; aLibHandle: Pointer = nil): Pointer;
1844 if not Assigned(aLibHandle) then
1845 aLibHandle := GL_LibHandle;
1847 {$IF DEFINED(GLB_WIN)}
1848 result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName);
1849 if Assigned(result) then
1852 if Assigned(wglGetProcAddress) then
1853 result := wglGetProcAddress(aProcName);
1854 {$ELSEIF DEFINED(GLB_LINUX)}
1855 if Assigned(glXGetProcAddress) then begin
1856 result := glXGetProcAddress(aProcName);
1857 if Assigned(result) then
1861 if Assigned(glXGetProcAddressARB) then begin
1862 result := glXGetProcAddressARB(aProcName);
1863 if Assigned(result) then
1867 result := dlsym(aLibHandle, aProcName);
1869 if not Assigned(result) then
1870 raise EglBitmapException.Create('unable to load procedure form library: ' + aProcName);
1873 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
1875 GLU_LibHandle: Pointer = nil;
1876 OpenGLInitialized: Boolean;
1877 InitOpenGLCS: TCriticalSection;
1879 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1880 procedure glbInitOpenGL;
1882 ////////////////////////////////////////////////////////////////////////////////
1883 function glbLoadLibrary(const aName: PChar): Pointer;
1885 {$IF DEFINED(GLB_WIN)}
1886 result := {%H-}Pointer(LoadLibrary(aName));
1887 {$ELSEIF DEFINED(GLB_LINUX)}
1888 result := dlopen(Name, RTLD_LAZY);
1894 ////////////////////////////////////////////////////////////////////////////////
1895 function glbFreeLibrary(const aLibHandle: Pointer): Boolean;
1898 if not Assigned(aLibHandle) then
1901 {$IF DEFINED(GLB_WIN)}
1902 Result := FreeLibrary({%H-}HINST(aLibHandle));
1903 {$ELSEIF DEFINED(GLB_LINUX)}
1904 Result := dlclose(aLibHandle) = 0;
1909 if Assigned(GL_LibHandle) then
1910 glbFreeLibrary(GL_LibHandle);
1912 if Assigned(GLU_LibHandle) then
1913 glbFreeLibrary(GLU_LibHandle);
1915 GL_LibHandle := glbLoadLibrary(libopengl);
1916 if not Assigned(GL_LibHandle) then
1917 raise EglBitmapException.Create('unable to load library: ' + libopengl);
1919 GLU_LibHandle := glbLoadLibrary(libglu);
1920 if not Assigned(GLU_LibHandle) then
1921 raise EglBitmapException.Create('unable to load library: ' + libglu);
1924 {$IF DEFINED(GLB_WIN)}
1925 wglGetProcAddress := glbGetProcAddress('wglGetProcAddress');
1926 {$ELSEIF DEFINED(GLB_LINUX)}
1927 glXGetProcAddress := glbGetProcAddress('glXGetProcAddress');
1928 glXGetProcAddressARB := dglGetProcAddress('glXGetProcAddressARB');
1931 glEnable := glbGetProcAddress('glEnable');
1932 glDisable := glbGetProcAddress('glDisable');
1933 glGetString := glbGetProcAddress('glGetString');
1934 glGetIntegerv := glbGetProcAddress('glGetIntegerv');
1935 glTexParameteri := glbGetProcAddress('glTexParameteri');
1936 glTexParameterfv := glbGetProcAddress('glTexParameterfv');
1937 glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
1938 glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
1939 glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
1940 glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
1941 glGenTextures := glbGetProcAddress('glGenTextures');
1942 glBindTexture := glbGetProcAddress('glBindTexture');
1943 glDeleteTextures := glbGetProcAddress('glDeleteTextures');
1944 glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
1945 glReadPixels := glbGetProcAddress('glReadPixels');
1946 glPixelStorei := glbGetProcAddress('glPixelStorei');
1947 glTexImage1D := glbGetProcAddress('glTexImage1D');
1948 glTexImage2D := glbGetProcAddress('glTexImage2D');
1949 glGetTexImage := glbGetProcAddress('glGetTexImage');
1951 gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
1952 gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
1954 glbFreeLibrary(GL_LibHandle);
1955 glbFreeLibrary(GLU_LibHandle);
1960 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1961 procedure glbReadOpenGLExtensions;
1967 MajorVersion, MinorVersion: Integer;
1969 ///////////////////////////////////////////////////////////////////////////////////////////
1970 procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer);
1977 Separator := Pos(AnsiString('.'), aBuffer);
1978 if (Separator > 1) and (Separator < Length(aBuffer)) and
1979 (aBuffer[Separator - 1] in ['0'..'9']) and
1980 (aBuffer[Separator + 1] in ['0'..'9']) then begin
1983 while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do
1986 Delete(aBuffer, 1, Separator);
1987 Separator := Pos(AnsiString('.'), aBuffer) + 1;
1989 while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do
1992 Delete(aBuffer, Separator, 255);
1993 Separator := Pos(AnsiString('.'), aBuffer);
1995 aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1));
1996 aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1));
2000 ///////////////////////////////////////////////////////////////////////////////////////////
2001 function CheckExtension(const Extension: AnsiString): Boolean;
2005 ExtPos := Pos(Extension, Buffer);
2006 result := ExtPos > 0;
2008 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
2012 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
2015 if not OpenGLInitialized then begin
2017 OpenGLInitialized := true;
2025 Context := wglGetCurrentContext;
2026 if (Context <> gLastContext) then begin
2027 gLastContext := Context;
2031 Buffer := glGetString(GL_VERSION);
2032 TrimVersionString(Buffer, MajorVersion, MinorVersion);
2034 GL_VERSION_1_2 := false;
2035 GL_VERSION_1_3 := false;
2036 GL_VERSION_1_4 := false;
2037 GL_VERSION_2_0 := false;
2038 if MajorVersion = 1 then begin
2039 if MinorVersion >= 2 then
2040 GL_VERSION_1_2 := true;
2042 if MinorVersion >= 3 then
2043 GL_VERSION_1_3 := true;
2045 if MinorVersion >= 4 then
2046 GL_VERSION_1_4 := true;
2047 end else if MajorVersion >= 2 then begin
2048 GL_VERSION_1_2 := true;
2049 GL_VERSION_1_3 := true;
2050 GL_VERSION_1_4 := true;
2051 GL_VERSION_2_0 := true;
2055 Buffer := glGetString(GL_EXTENSIONS);
2056 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
2057 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
2058 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
2059 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
2060 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
2061 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
2062 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
2063 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
2064 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
2065 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
2067 if GL_VERSION_1_3 then begin
2068 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D');
2069 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D');
2070 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
2072 glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB');
2073 glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB');
2074 glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB');
2084 function CreateGrayPalette: HPALETTE;
2089 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
2091 Pal.palVersion := $300;
2092 Pal.palNumEntries := 256;
2095 {$DEFINE GLB_TEMPRANGECHECK}
2099 for Idx := 0 to 256 - 1 do begin
2100 Pal.palPalEntry[Idx].peRed := Idx;
2101 Pal.palPalEntry[Idx].peGreen := Idx;
2102 Pal.palPalEntry[Idx].peBlue := Idx;
2103 Pal.palPalEntry[Idx].peFlags := 0;
2106 {$IFDEF GLB_TEMPRANGECHECK}
2107 {$UNDEF GLB_TEMPRANGECHECK}
2111 result := CreatePalette(Pal^);
2118 {$IFDEF GLB_SDL_IMAGE}
2119 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2120 // SDL Image Helper /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2121 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2122 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2124 result := TStream(context^.unknown.data1).Seek(offset, whence);
2127 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2129 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2132 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2134 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2137 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2142 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2144 result := SDL_AllocRW;
2146 if result = nil then
2147 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2149 result^.seek := glBitmapRWseek;
2150 result^.read := glBitmapRWread;
2151 result^.write := glBitmapRWwrite;
2152 result^.close := glBitmapRWclose;
2153 result^.unknown.data1 := Stream;
2158 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
2160 glBitmap: TglBitmap2D;
2166 if Instance = 0 then
2167 Instance := HInstance;
2169 if (LoadFromRes) then
2170 glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName)
2173 glBitmap := TglBitmap2D.Create(FileName);
2176 glBitmap.DeleteTextureOnFree := false;
2177 glBitmap.FreeDataAfterGenTexture := false;
2178 glBitmap.GenTexture(true);
2179 if (glBitmap.ID > 0) then begin
2180 Texture := glBitmap.ID;
2188 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
2190 CM: TglBitmapCubeMap;
2195 if Instance = 0 then
2196 Instance := HInstance;
2199 CM := TglBitmapCubeMap.Create;
2201 CM.DeleteTextureOnFree := false;
2205 if (LoadFromRes) then
2206 CM.LoadFromResource(Instance, PositiveX)
2209 CM.LoadFromFile(PositiveX);
2210 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
2213 if (LoadFromRes) then
2214 CM.LoadFromResource(Instance, NegativeX)
2217 CM.LoadFromFile(NegativeX);
2218 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
2221 if (LoadFromRes) then
2222 CM.LoadFromResource(Instance, PositiveY)
2225 CM.LoadFromFile(PositiveY);
2226 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
2229 if (LoadFromRes) then
2230 CM.LoadFromResource(Instance, NegativeY)
2233 CM.LoadFromFile(NegativeY);
2234 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
2237 if (LoadFromRes) then
2238 CM.LoadFromResource(Instance, PositiveZ)
2241 CM.LoadFromFile(PositiveZ);
2242 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
2245 if (LoadFromRes) then
2246 CM.LoadFromResource(Instance, NegativeZ)
2249 CM.LoadFromFile(NegativeZ);
2250 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
2259 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
2261 NM: TglBitmapNormalMap;
2265 NM := TglBitmapNormalMap.Create;
2267 NM.DeleteTextureOnFree := false;
2268 NM.GenerateNormalMap(Size);
2278 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2279 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2281 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2284 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2285 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2287 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2290 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2291 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2293 glBitmapDefaultMipmap := aValue;
2296 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2297 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2299 glBitmapDefaultFormat := aFormat;
2302 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2303 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2305 glBitmapDefaultFilterMin := aMin;
2306 glBitmapDefaultFilterMag := aMag;
2309 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2310 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2312 glBitmapDefaultWrapS := S;
2313 glBitmapDefaultWrapT := T;
2314 glBitmapDefaultWrapR := R;
2317 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2318 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2320 result := glBitmapDefaultDeleteTextureOnFree;
2323 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2324 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2326 result := glBitmapDefaultFreeDataAfterGenTextures;
2329 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2330 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2332 result := glBitmapDefaultMipmap;
2335 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2336 function glBitmapGetDefaultFormat: TglBitmapFormat;
2338 result := glBitmapDefaultFormat;
2341 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2342 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
2344 aMin := glBitmapDefaultFilterMin;
2345 aMag := glBitmapDefaultFilterMag;
2348 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2349 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
2351 S := glBitmapDefaultWrapS;
2352 T := glBitmapDefaultWrapT;
2353 R := glBitmapDefaultWrapR;
2356 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2357 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2358 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2359 function TFormatDescriptor.GetRedMask: QWord;
2361 result := fRange.r shl fShift.r;
2364 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2365 function TFormatDescriptor.GetGreenMask: QWord;
2367 result := fRange.g shl fShift.g;
2370 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2371 function TFormatDescriptor.GetBlueMask: QWord;
2373 result := fRange.b shl fShift.b;
2376 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2377 function TFormatDescriptor.GetAlphaMask: QWord;
2379 result := fRange.a shl fShift.a;
2382 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2383 function TFormatDescriptor.GetComponents: Integer;
2389 if (fRange.arr[i] > 0) then
2393 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2394 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2398 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2399 w := Max(1, aSize.X);
2400 h := Max(1, aSize.Y);
2401 result := GetSize(w, h);
2406 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2407 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2410 if (aWidth <= 0) or (aHeight <= 0) then
2412 result := Ceil(aWidth * aHeight * fPixelSize);
2415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2416 function TFormatDescriptor.CreateMappingData: Pointer;
2421 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2422 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2428 function TFormatDescriptor.IsEmpty: Boolean;
2430 result := (fFormat = tfEmpty);
2433 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2434 function TFormatDescriptor.HasAlpha: Boolean;
2436 result := (fRange.a > 0);
2439 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2440 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean;
2444 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2445 raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
2447 if (aRedMask <> RedMask) then
2449 if (aGreenMask <> GreenMask) then
2451 if (aBlueMask <> BlueMask) then
2453 if (aAlphaMask <> AlphaMask) then
2458 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2459 procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData);
2461 FillChar(aPixel{%H-}, SizeOf(aPixel), 0);
2462 aPixel.Data := fRange;
2463 aPixel.Range := fRange;
2464 aPixel.Format := fFormat;
2467 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2468 constructor TFormatDescriptor.Create;
2473 fWithAlpha := tfEmpty;
2474 fWithoutAlpha := tfEmpty;
2475 fRGBInverted := tfEmpty;
2476 fUncompressed := tfEmpty;
2478 fIsCompressed := false;
2481 fglInternalFormat := 0;
2484 FillChar(fRange, 0, SizeOf(fRange));
2485 FillChar(fShift, 0, SizeOf(fShift));
2488 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2489 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2490 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2491 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2493 aData^ := aPixel.Data.a;
2497 procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2502 aPixel.Data.a := aData^;
2506 constructor TfdAlpha_UB1.Create;
2511 fglFormat := GL_ALPHA;
2512 fglDataFormat := GL_UNSIGNED_BYTE;
2515 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2516 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2517 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2518 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2520 aData^ := LuminanceWeight(aPixel);
2524 procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2526 aPixel.Data.r := aData^;
2527 aPixel.Data.g := aData^;
2528 aPixel.Data.b := aData^;
2533 constructor TfdLuminance_UB1.Create;
2540 fglFormat := GL_LUMINANCE;
2541 fglDataFormat := GL_UNSIGNED_BYTE;
2544 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2545 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2546 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2547 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2553 if (fRange.arr[i] > 0) then
2554 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2558 procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2563 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2567 constructor TfdUniversal_UB1.Create;
2573 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2574 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2575 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2576 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2578 inherited Map(aPixel, aData, aMapData);
2579 aData^ := aPixel.Data.a;
2583 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2585 inherited Unmap(aData, aPixel, aMapData);
2586 aPixel.Data.a := aData^;
2590 constructor TfdLuminanceAlpha_UB2.Create;
2596 fglFormat := GL_LUMINANCE_ALPHA;
2597 fglDataFormat := GL_UNSIGNED_BYTE;
2600 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2601 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2602 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2603 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2605 aData^ := aPixel.Data.r;
2607 aData^ := aPixel.Data.g;
2609 aData^ := aPixel.Data.b;
2613 procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2615 aPixel.Data.r := aData^;
2617 aPixel.Data.g := aData^;
2619 aPixel.Data.b := aData^;
2624 constructor TfdRGB_UB3.Create;
2634 fglFormat := GL_RGB;
2635 fglDataFormat := GL_UNSIGNED_BYTE;
2638 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2639 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2640 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2641 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2643 aData^ := aPixel.Data.b;
2645 aData^ := aPixel.Data.g;
2647 aData^ := aPixel.Data.r;
2651 procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2653 aPixel.Data.b := aData^;
2655 aPixel.Data.g := aData^;
2657 aPixel.Data.r := aData^;
2662 constructor TfdBGR_UB3.Create;
2671 fglFormat := GL_BGR;
2672 fglDataFormat := GL_UNSIGNED_BYTE;
2675 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2676 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2677 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2678 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2680 inherited Map(aPixel, aData, aMapData);
2681 aData^ := aPixel.Data.a;
2685 procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2687 inherited Unmap(aData, aPixel, aMapData);
2688 aPixel.Data.a := aData^;
2692 constructor TfdRGBA_UB4.Create;
2698 fglFormat := GL_RGBA;
2699 fglDataFormat := GL_UNSIGNED_BYTE;
2702 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2703 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2704 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2705 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2707 inherited Map(aPixel, aData, aMapData);
2708 aData^ := aPixel.Data.a;
2712 procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2714 inherited Unmap(aData, aPixel, aMapData);
2715 aPixel.Data.a := aData^;
2719 constructor TfdBGRA_UB4.Create;
2725 fglFormat := GL_BGRA;
2726 fglDataFormat := GL_UNSIGNED_BYTE;
2729 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2730 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2731 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2732 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2734 PWord(aData)^ := aPixel.Data.a;
2738 procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2743 aPixel.Data.a := PWord(aData)^;
2747 constructor TfdAlpha_US1.Create;
2752 fglFormat := GL_ALPHA;
2753 fglDataFormat := GL_UNSIGNED_SHORT;
2756 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2757 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2758 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2759 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2761 PWord(aData)^ := LuminanceWeight(aPixel);
2765 procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2767 aPixel.Data.r := PWord(aData)^;
2768 aPixel.Data.g := PWord(aData)^;
2769 aPixel.Data.b := PWord(aData)^;
2774 constructor TfdLuminance_US1.Create;
2781 fglFormat := GL_LUMINANCE;
2782 fglDataFormat := GL_UNSIGNED_SHORT;
2785 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2786 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2787 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2788 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2794 if (fRange.arr[i] > 0) then
2795 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2799 procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2804 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2808 constructor TfdUniversal_US1.Create;
2814 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2815 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2816 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2817 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2819 PWord(aData)^ := DepthWeight(aPixel);
2823 procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2825 aPixel.Data.r := PWord(aData)^;
2826 aPixel.Data.g := PWord(aData)^;
2827 aPixel.Data.b := PWord(aData)^;
2832 constructor TfdDepth_US1.Create;
2839 fglFormat := GL_DEPTH_COMPONENT;
2840 fglDataFormat := GL_UNSIGNED_SHORT;
2843 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2844 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2845 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2846 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2848 inherited Map(aPixel, aData, aMapData);
2849 PWord(aData)^ := aPixel.Data.a;
2853 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2855 inherited Unmap(aData, aPixel, aMapData);
2856 aPixel.Data.a := PWord(aData)^;
2860 constructor TfdLuminanceAlpha_US2.Create;
2866 fglFormat := GL_LUMINANCE_ALPHA;
2867 fglDataFormat := GL_UNSIGNED_SHORT;
2870 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2871 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2872 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2873 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2875 PWord(aData)^ := aPixel.Data.r;
2877 PWord(aData)^ := aPixel.Data.g;
2879 PWord(aData)^ := aPixel.Data.b;
2883 procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2885 aPixel.Data.r := PWord(aData)^;
2887 aPixel.Data.g := PWord(aData)^;
2889 aPixel.Data.b := PWord(aData)^;
2894 constructor TfdRGB_US3.Create;
2904 fglFormat := GL_RGB;
2905 fglDataFormat := GL_UNSIGNED_SHORT;
2908 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2909 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2910 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2911 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2913 PWord(aData)^ := aPixel.Data.b;
2915 PWord(aData)^ := aPixel.Data.g;
2917 PWord(aData)^ := aPixel.Data.r;
2921 procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2923 aPixel.Data.b := PWord(aData)^;
2925 aPixel.Data.g := PWord(aData)^;
2927 aPixel.Data.r := PWord(aData)^;
2932 constructor TfdBGR_US3.Create;
2942 fglFormat := GL_BGR;
2943 fglDataFormat := GL_UNSIGNED_SHORT;
2946 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2947 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2948 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2949 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2951 inherited Map(aPixel, aData, aMapData);
2952 PWord(aData)^ := aPixel.Data.a;
2956 procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2958 inherited Unmap(aData, aPixel, aMapData);
2959 aPixel.Data.a := PWord(aData)^;
2963 constructor TfdRGBA_US4.Create;
2969 fglFormat := GL_RGBA;
2970 fglDataFormat := GL_UNSIGNED_SHORT;
2973 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2974 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2975 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2976 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2978 inherited Map(aPixel, aData, aMapData);
2979 PWord(aData)^ := aPixel.Data.a;
2983 procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
2985 inherited Unmap(aData, aPixel, aMapData);
2986 aPixel.Data.a := PWord(aData)^;
2990 constructor TfdBGRA_US4.Create;
2996 fglFormat := GL_BGRA;
2997 fglDataFormat := GL_UNSIGNED_SHORT;
3000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3001 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3002 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3003 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3007 PCardinal(aData)^ := 0;
3009 if (fRange.arr[i] > 0) then
3010 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
3014 procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3019 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
3023 constructor TfdUniversal_UI1.Create;
3029 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3030 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3031 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3032 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3034 PCardinal(aData)^ := DepthWeight(aPixel);
3038 procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3040 aPixel.Data.r := PCardinal(aData)^;
3041 aPixel.Data.g := PCardinal(aData)^;
3042 aPixel.Data.b := PCardinal(aData)^;
3047 constructor TfdDepth_UI1.Create;
3051 fRange.r := $FFFFFFFF;
3052 fRange.g := $FFFFFFFF;
3053 fRange.b := $FFFFFFFF;
3054 fglFormat := GL_DEPTH_COMPONENT;
3055 fglDataFormat := GL_UNSIGNED_INT;
3058 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3059 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3060 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3061 constructor TfdAlpha4.Create;
3064 fFormat := tfAlpha4;
3065 fWithAlpha := tfAlpha4;
3066 fglInternalFormat := GL_ALPHA4;
3069 constructor TfdAlpha8.Create;
3072 fFormat := tfAlpha8;
3073 fWithAlpha := tfAlpha8;
3074 fglInternalFormat := GL_ALPHA8;
3077 constructor TfdAlpha12.Create;
3080 fFormat := tfAlpha12;
3081 fWithAlpha := tfAlpha12;
3082 fglInternalFormat := GL_ALPHA12;
3085 constructor TfdAlpha16.Create;
3088 fFormat := tfAlpha16;
3089 fWithAlpha := tfAlpha16;
3090 fglInternalFormat := GL_ALPHA16;
3093 constructor TfdLuminance4.Create;
3096 fFormat := tfLuminance4;
3097 fWithAlpha := tfLuminance4Alpha4;
3098 fWithoutAlpha := tfLuminance4;
3099 fglInternalFormat := GL_LUMINANCE4;
3102 constructor TfdLuminance8.Create;
3105 fFormat := tfLuminance8;
3106 fWithAlpha := tfLuminance8Alpha8;
3107 fWithoutAlpha := tfLuminance8;
3108 fglInternalFormat := GL_LUMINANCE8;
3111 constructor TfdLuminance12.Create;
3114 fFormat := tfLuminance12;
3115 fWithAlpha := tfLuminance12Alpha12;
3116 fWithoutAlpha := tfLuminance12;
3117 fglInternalFormat := GL_LUMINANCE12;
3120 constructor TfdLuminance16.Create;
3123 fFormat := tfLuminance16;
3124 fWithAlpha := tfLuminance16Alpha16;
3125 fWithoutAlpha := tfLuminance16;
3126 fglInternalFormat := GL_LUMINANCE16;
3129 constructor TfdLuminance4Alpha4.Create;
3132 fFormat := tfLuminance4Alpha4;
3133 fWithAlpha := tfLuminance4Alpha4;
3134 fWithoutAlpha := tfLuminance4;
3135 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
3138 constructor TfdLuminance6Alpha2.Create;
3141 fFormat := tfLuminance6Alpha2;
3142 fWithAlpha := tfLuminance6Alpha2;
3143 fWithoutAlpha := tfLuminance8;
3144 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
3147 constructor TfdLuminance8Alpha8.Create;
3150 fFormat := tfLuminance8Alpha8;
3151 fWithAlpha := tfLuminance8Alpha8;
3152 fWithoutAlpha := tfLuminance8;
3153 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
3156 constructor TfdLuminance12Alpha4.Create;
3159 fFormat := tfLuminance12Alpha4;
3160 fWithAlpha := tfLuminance12Alpha4;
3161 fWithoutAlpha := tfLuminance12;
3162 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
3165 constructor TfdLuminance12Alpha12.Create;
3168 fFormat := tfLuminance12Alpha12;
3169 fWithAlpha := tfLuminance12Alpha12;
3170 fWithoutAlpha := tfLuminance12;
3171 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
3174 constructor TfdLuminance16Alpha16.Create;
3177 fFormat := tfLuminance16Alpha16;
3178 fWithAlpha := tfLuminance16Alpha16;
3179 fWithoutAlpha := tfLuminance16;
3180 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
3183 constructor TfdR3G3B2.Create;
3186 fFormat := tfR3G3B2;
3187 fWithAlpha := tfRGBA2;
3188 fWithoutAlpha := tfR3G3B2;
3195 fglFormat := GL_RGB;
3196 fglInternalFormat := GL_R3_G3_B2;
3197 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
3200 constructor TfdRGB4.Create;
3204 fWithAlpha := tfRGBA4;
3205 fWithoutAlpha := tfRGB4;
3206 fRGBInverted := tfBGR4;
3213 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3214 fglInternalFormat := GL_RGB4;
3215 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3218 constructor TfdR5G6B5.Create;
3221 fFormat := tfR5G6B5;
3222 fWithAlpha := tfRGBA4;
3223 fWithoutAlpha := tfR5G6B5;
3224 fRGBInverted := tfB5G6R5;
3231 fglFormat := GL_RGB;
3232 fglInternalFormat := GL_RGB565;
3233 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3236 constructor TfdRGB5.Create;
3240 fWithAlpha := tfRGB5A1;
3241 fWithoutAlpha := tfRGB5;
3242 fRGBInverted := tfBGR5;
3249 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3250 fglInternalFormat := GL_RGB5;
3251 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3254 constructor TfdRGB8.Create;
3258 fWithAlpha := tfRGBA8;
3259 fWithoutAlpha := tfRGB8;
3260 fRGBInverted := tfBGR8;
3261 fglInternalFormat := GL_RGB8;
3264 constructor TfdRGB10.Create;
3268 fWithAlpha := tfRGB10A2;
3269 fWithoutAlpha := tfRGB10;
3270 fRGBInverted := tfBGR10;
3277 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3278 fglInternalFormat := GL_RGB10;
3279 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3282 constructor TfdRGB12.Create;
3286 fWithAlpha := tfRGBA12;
3287 fWithoutAlpha := tfRGB12;
3288 fRGBInverted := tfBGR12;
3289 fglInternalFormat := GL_RGB12;
3292 constructor TfdRGB16.Create;
3296 fWithAlpha := tfRGBA16;
3297 fWithoutAlpha := tfRGB16;
3298 fRGBInverted := tfBGR16;
3299 fglInternalFormat := GL_RGB16;
3302 constructor TfdRGBA2.Create;
3306 fWithAlpha := tfRGBA2;
3307 fWithoutAlpha := tfR3G3B2;
3308 fRGBInverted := tfBGRA2;
3309 fglInternalFormat := GL_RGBA2;
3312 constructor TfdRGBA4.Create;
3316 fWithAlpha := tfRGBA4;
3317 fWithoutAlpha := tfRGB4;
3318 fRGBInverted := tfBGRA4;
3327 fglFormat := GL_RGBA;
3328 fglInternalFormat := GL_RGBA4;
3329 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3332 constructor TfdRGB5A1.Create;
3335 fFormat := tfRGB5A1;
3336 fWithAlpha := tfRGB5A1;
3337 fWithoutAlpha := tfRGB5;
3338 fRGBInverted := tfBGR5A1;
3347 fglFormat := GL_RGBA;
3348 fglInternalFormat := GL_RGB5_A1;
3349 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3352 constructor TfdRGBA8.Create;
3356 fWithAlpha := tfRGBA8;
3357 fWithoutAlpha := tfRGB8;
3358 fRGBInverted := tfBGRA8;
3359 fglInternalFormat := GL_RGBA8;
3362 constructor TfdRGB10A2.Create;
3365 fFormat := tfRGB10A2;
3366 fWithAlpha := tfRGB10A2;
3367 fWithoutAlpha := tfRGB10;
3368 fRGBInverted := tfBGR10A2;
3377 fglFormat := GL_RGBA;
3378 fglInternalFormat := GL_RGB10_A2;
3379 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3382 constructor TfdRGBA12.Create;
3385 fFormat := tfRGBA12;
3386 fWithAlpha := tfRGBA12;
3387 fWithoutAlpha := tfRGB12;
3388 fRGBInverted := tfBGRA12;
3389 fglInternalFormat := GL_RGBA12;
3392 constructor TfdRGBA16.Create;
3395 fFormat := tfRGBA16;
3396 fWithAlpha := tfRGBA16;
3397 fWithoutAlpha := tfRGB16;
3398 fRGBInverted := tfBGRA16;
3399 fglInternalFormat := GL_RGBA16;
3402 constructor TfdBGR4.Create;
3407 fWithAlpha := tfBGRA4;
3408 fWithoutAlpha := tfBGR4;
3409 fRGBInverted := tfRGB4;
3418 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3419 fglInternalFormat := GL_RGB4;
3420 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3423 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3424 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3426 constructor TfdB5G6R5.Create;
3429 fFormat := tfB5G6R5;
3430 fWithAlpha := tfBGRA4;
3431 fWithoutAlpha := tfB5G6R5;
3432 fRGBInverted := tfR5G6B5;
3439 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3440 fglInternalFormat := GL_RGB8;
3441 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3444 constructor TfdBGR5.Create;
3449 fWithAlpha := tfBGR5A1;
3450 fWithoutAlpha := tfBGR5;
3451 fRGBInverted := tfRGB5;
3460 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3461 fglInternalFormat := GL_RGB5;
3462 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3465 constructor TfdBGR8.Create;
3469 fWithAlpha := tfBGRA8;
3470 fWithoutAlpha := tfBGR8;
3471 fRGBInverted := tfRGB8;
3472 fglInternalFormat := GL_RGB8;
3475 constructor TfdBGR10.Create;
3479 fWithAlpha := tfBGR10A2;
3480 fWithoutAlpha := tfBGR10;
3481 fRGBInverted := tfRGB10;
3490 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3491 fglInternalFormat := GL_RGB10;
3492 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3495 constructor TfdBGR12.Create;
3499 fWithAlpha := tfBGRA12;
3500 fWithoutAlpha := tfBGR12;
3501 fRGBInverted := tfRGB12;
3502 fglInternalFormat := GL_RGB12;
3505 constructor TfdBGR16.Create;
3509 fWithAlpha := tfBGRA16;
3510 fWithoutAlpha := tfBGR16;
3511 fRGBInverted := tfRGB16;
3512 fglInternalFormat := GL_RGB16;
3515 constructor TfdBGRA2.Create;
3519 fWithAlpha := tfBGRA4;
3520 fWithoutAlpha := tfBGR4;
3521 fRGBInverted := tfRGBA2;
3522 fglInternalFormat := GL_RGBA2;
3525 constructor TfdBGRA4.Create;
3529 fWithAlpha := tfBGRA4;
3530 fWithoutAlpha := tfBGR4;
3531 fRGBInverted := tfRGBA4;
3540 fglFormat := GL_BGRA;
3541 fglInternalFormat := GL_RGBA4;
3542 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3545 constructor TfdBGR5A1.Create;
3548 fFormat := tfBGR5A1;
3549 fWithAlpha := tfBGR5A1;
3550 fWithoutAlpha := tfBGR5;
3551 fRGBInverted := tfRGB5A1;
3560 fglFormat := GL_BGRA;
3561 fglInternalFormat := GL_RGB5_A1;
3562 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3565 constructor TfdBGRA8.Create;
3569 fWithAlpha := tfBGRA8;
3570 fWithoutAlpha := tfBGR8;
3571 fRGBInverted := tfRGBA8;
3572 fglInternalFormat := GL_RGBA8;
3575 constructor TfdBGR10A2.Create;
3578 fFormat := tfBGR10A2;
3579 fWithAlpha := tfBGR10A2;
3580 fWithoutAlpha := tfBGR10;
3581 fRGBInverted := tfRGB10A2;
3590 fglFormat := GL_BGRA;
3591 fglInternalFormat := GL_RGB10_A2;
3592 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3595 constructor TfdBGRA12.Create;
3598 fFormat := tfBGRA12;
3599 fWithAlpha := tfBGRA12;
3600 fWithoutAlpha := tfBGR12;
3601 fRGBInverted := tfRGBA12;
3602 fglInternalFormat := GL_RGBA12;
3605 constructor TfdBGRA16.Create;
3608 fFormat := tfBGRA16;
3609 fWithAlpha := tfBGRA16;
3610 fWithoutAlpha := tfBGR16;
3611 fRGBInverted := tfRGBA16;
3612 fglInternalFormat := GL_RGBA16;
3615 constructor TfdDepth16.Create;
3618 fFormat := tfDepth16;
3619 fWithAlpha := tfEmpty;
3620 fWithoutAlpha := tfDepth16;
3621 fglInternalFormat := GL_DEPTH_COMPONENT16;
3624 constructor TfdDepth24.Create;
3627 fFormat := tfDepth24;
3628 fWithAlpha := tfEmpty;
3629 fWithoutAlpha := tfDepth24;
3630 fglInternalFormat := GL_DEPTH_COMPONENT24;
3633 constructor TfdDepth32.Create;
3636 fFormat := tfDepth32;
3637 fWithAlpha := tfEmpty;
3638 fWithoutAlpha := tfDepth32;
3639 fglInternalFormat := GL_DEPTH_COMPONENT32;
3642 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3643 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3644 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3645 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3647 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3650 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3652 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3655 constructor TfdS3tcDtx1RGBA.Create;
3658 fFormat := tfS3tcDtx1RGBA;
3659 fWithAlpha := tfS3tcDtx1RGBA;
3660 fUncompressed := tfRGB5A1;
3662 fIsCompressed := true;
3663 fglFormat := GL_COMPRESSED_RGBA;
3664 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3665 fglDataFormat := GL_UNSIGNED_BYTE;
3668 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3669 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3670 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3671 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3673 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3676 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3678 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3681 constructor TfdS3tcDtx3RGBA.Create;
3684 fFormat := tfS3tcDtx3RGBA;
3685 fWithAlpha := tfS3tcDtx3RGBA;
3686 fUncompressed := tfRGBA8;
3688 fIsCompressed := true;
3689 fglFormat := GL_COMPRESSED_RGBA;
3690 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3691 fglDataFormat := GL_UNSIGNED_BYTE;
3694 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3695 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3696 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3697 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3699 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3702 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3704 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3707 constructor TfdS3tcDtx5RGBA.Create;
3710 fFormat := tfS3tcDtx3RGBA;
3711 fWithAlpha := tfS3tcDtx3RGBA;
3712 fUncompressed := tfRGBA8;
3714 fIsCompressed := true;
3715 fglFormat := GL_COMPRESSED_RGBA;
3716 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3717 fglDataFormat := GL_UNSIGNED_BYTE;
3720 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3721 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3722 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3723 class procedure TFormatDescriptor.Init;
3725 if not Assigned(FormatDescriptorCS) then
3726 FormatDescriptorCS := TCriticalSection.Create;
3729 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3730 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3732 FormatDescriptorCS.Enter;
3734 result := FormatDescriptors[aFormat];
3735 if not Assigned(result) then begin
3736 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3737 FormatDescriptors[aFormat] := result;
3740 FormatDescriptorCS.Leave;
3744 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3745 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3747 result := Get(Get(aFormat).WithAlpha);
3750 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3751 class procedure TFormatDescriptor.Clear;
3755 FormatDescriptorCS.Enter;
3757 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3758 FreeAndNil(FormatDescriptors[f]);
3760 FormatDescriptorCS.Leave;
3764 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3765 class procedure TFormatDescriptor.Finalize;
3768 FreeAndNil(FormatDescriptorCS);
3771 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3772 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3773 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3774 procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord);
3776 Update(aValue, fRange.r, fShift.r);
3779 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3780 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord);
3782 Update(aValue, fRange.g, fShift.g);
3785 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3786 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord);
3788 Update(aValue, fRange.b, fShift.b);
3791 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3792 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord);
3794 Update(aValue, fRange.a, fShift.a);
3797 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3798 procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out
3805 while (aMask > 0) and ((aMask and 1) = 0) do begin
3807 aMask := aMask shr 1;
3810 while (aMask > 0) do begin
3811 aRange := aRange shl 1;
3812 aMask := aMask shr 1;
3816 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3819 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3820 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3826 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3827 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3828 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3829 ((aPixel.Data.a and fRange.a) shl fShift.a);
3830 s := Round(fPixelSize);
3833 2: PWord(aData)^ := data;
3834 4: PCardinal(aData)^ := data;
3835 8: PQWord(aData)^ := data;
3837 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3842 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3843 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3848 s := Round(fPixelSize);
3851 2: data := PWord(aData)^;
3852 4: data := PCardinal(aData)^;
3853 8: data := PQWord(aData)^;
3855 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3858 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3862 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3863 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3864 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3865 procedure TbmpColorTableFormat.CreateColorTable;
3869 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3870 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3872 if (Format = tfLuminance4) then
3873 SetLength(fColorTable, 16)
3875 SetLength(fColorTable, 256);
3879 for i := 0 to High(fColorTable) do begin
3880 fColorTable[i].r := 16 * i;
3881 fColorTable[i].g := 16 * i;
3882 fColorTable[i].b := 16 * i;
3883 fColorTable[i].a := 0;
3888 for i := 0 to High(fColorTable) do begin
3889 fColorTable[i].r := i;
3890 fColorTable[i].g := i;
3891 fColorTable[i].b := i;
3892 fColorTable[i].a := 0;
3897 for i := 0 to High(fColorTable) do begin
3898 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3899 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3900 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3901 fColorTable[i].a := 0;
3907 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3908 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3912 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3913 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3917 if (aMapData = nil) then
3919 d := LuminanceWeight(aPixel) and Range.r;
3920 aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData)));
3922 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3929 aData^ := LuminanceWeight(aPixel) and Range.r;
3935 ((aPixel.Data.r and Range.r) shl Shift.r) or
3936 ((aPixel.Data.g and Range.g) shl Shift.g) or
3937 ((aPixel.Data.b and Range.b) shl Shift.b));
3943 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3944 procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer);
3951 s := Trunc(fPixelSize);
3952 f := fPixelSize - s;
3953 bits := Round(8 * f);
3955 0: idx := (aData^ shr (8 - bits - {%H-}PtrUInt(aMapData))) and ((1 shl bits) - 1);
3957 2: idx := PWord(aData)^;
3958 4: idx := PCardinal(aData)^;
3959 8: idx := PQWord(aData)^;
3961 raise EglBitmapException.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3963 if (idx >= Length(fColorTable)) then
3964 raise EglBitmapException.CreateFmt('invalid color index: %d', [idx]);
3965 with fColorTable[idx] do begin
3971 inc(aMapData, bits);
3972 if ({%H-}PtrUInt(aMapData) >= 8) then begin
3979 destructor TbmpColorTableFormat.Destroy;
3981 SetLength(fColorTable, 0);
3985 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3986 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3987 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3988 procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor);
3992 for i := 0 to 3 do begin
3993 if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin
3994 if (aSourceFD.Range.arr[i] > 0) then
3995 aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i])
3997 aPixel.Data.arr[i] := aDestFD.Range.arr[i];
4002 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4003 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
4005 with aFuncRec do begin
4006 if (Source.Range.r > 0) then
4007 Dest.Data.r := Source.Data.r;
4008 if (Source.Range.g > 0) then
4009 Dest.Data.g := Source.Data.g;
4010 if (Source.Range.b > 0) then
4011 Dest.Data.b := Source.Data.b;
4012 if (Source.Range.a > 0) then
4013 Dest.Data.a := Source.Data.a;
4017 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4018 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4022 with aFuncRec do begin
4024 if (Source.Range.arr[i] > 0) then
4025 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
4030 TShiftData = packed record
4032 0: (r, g, b, a: SmallInt);
4033 1: (arr: array[0..3] of SmallInt);
4035 PShiftData = ^TShiftData;
4037 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4038 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
4044 if (Source.Range.arr[i] > 0) then
4045 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
4048 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4049 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
4051 with aFuncRec do begin
4052 Dest.Data := Source.Data;
4053 if ({%H-}PtrUInt(Args) and $1 > 0) then begin
4054 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
4055 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
4056 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
4058 if ({%H-}PtrUInt(Args) and $2 > 0) then begin
4059 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
4064 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4065 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
4069 with aFuncRec do begin
4071 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
4075 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4076 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4080 with FuncRec do begin
4081 if (FuncRec.Args = nil) then begin //source has no alpha
4083 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
4084 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
4085 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
4086 Dest.Data.a := Round(Dest.Range.a * Temp);
4088 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
4092 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4093 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4095 PglBitmapPixelData = ^TglBitmapPixelData;
4097 with FuncRec do begin
4098 Dest.Data.r := Source.Data.r;
4099 Dest.Data.g := Source.Data.g;
4100 Dest.Data.b := Source.Data.b;
4102 with PglBitmapPixelData(Args)^ do
4103 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
4104 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
4105 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
4108 Dest.Data.a := Dest.Range.a;
4112 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4113 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
4115 with FuncRec do begin
4116 Dest.Data.r := Source.Data.r;
4117 Dest.Data.g := Source.Data.g;
4118 Dest.Data.b := Source.Data.b;
4119 Dest.Data.a := PCardinal(Args)^;
4123 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4124 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
4127 TRGBPix = array [0..2] of byte;
4131 while aWidth > 0 do begin
4132 Temp := PRGBPix(aData)^[0];
4133 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
4134 PRGBPix(aData)^[2] := Temp;
4144 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4145 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4146 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4147 function TglBitmap.GetWidth: Integer;
4149 if (ffX in fDimension.Fields) then
4150 result := fDimension.X
4155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4156 function TglBitmap.GetHeight: Integer;
4158 if (ffY in fDimension.Fields) then
4159 result := fDimension.Y
4164 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4165 function TglBitmap.GetFileWidth: Integer;
4167 result := Max(1, Width);
4170 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4171 function TglBitmap.GetFileHeight: Integer;
4173 result := Max(1, Height);
4176 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4177 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4179 if fCustomData = aValue then
4181 fCustomData := aValue;
4184 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4185 procedure TglBitmap.SetCustomName(const aValue: String);
4187 if fCustomName = aValue then
4189 fCustomName := aValue;
4192 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4193 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4195 if fCustomNameW = aValue then
4197 fCustomNameW := aValue;
4200 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4201 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4203 if fDeleteTextureOnFree = aValue then
4205 fDeleteTextureOnFree := aValue;
4208 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4209 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4211 if fFormat = aValue then
4213 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4214 raise EglBitmapUnsupportedFormat.Create(Format);
4215 SetDataPointer(Data, aValue, Width, Height);
4218 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4219 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4221 if fFreeDataAfterGenTexture = aValue then
4223 fFreeDataAfterGenTexture := aValue;
4226 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4227 procedure TglBitmap.SetID(const aValue: Cardinal);
4229 if fID = aValue then
4234 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4235 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4237 if fMipMap = aValue then
4242 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4243 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4245 if fTarget = aValue then
4250 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4251 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4253 MaxAnisotropic: Integer;
4255 fAnisotropic := aValue;
4256 if (ID > 0) then begin
4257 if GL_EXT_texture_filter_anisotropic then begin
4258 if fAnisotropic > 0 then begin
4260 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4261 if aValue > MaxAnisotropic then
4262 fAnisotropic := MaxAnisotropic;
4263 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4271 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4272 procedure TglBitmap.CreateID;
4275 glDeleteTextures(1, @fID);
4276 glGenTextures(1, @fID);
4280 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4281 procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean);
4283 // Set Up Parameters
4284 SetWrap(fWrapS, fWrapT, fWrapR);
4285 SetFilter(fFilterMin, fFilterMag);
4286 SetAnisotropic(fAnisotropic);
4287 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4289 // Mip Maps Generation Mode
4290 aBuildWithGlu := false;
4291 if (MipMap = mmMipmap) then begin
4292 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4293 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4295 aBuildWithGlu := true;
4296 end else if (MipMap = mmMipmapGlu) then
4297 aBuildWithGlu := true;
4300 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4301 procedure TglBitmap.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
4302 const aWidth: Integer; const aHeight: Integer);
4306 if (Data <> aData) then begin
4307 if (Assigned(Data)) then
4312 FillChar(fDimension, SizeOf(fDimension), 0);
4313 if not Assigned(fData) then begin
4318 if aWidth <> -1 then begin
4319 fDimension.Fields := fDimension.Fields + [ffX];
4320 fDimension.X := aWidth;
4323 if aHeight <> -1 then begin
4324 fDimension.Fields := fDimension.Fields + [ffY];
4325 fDimension.Y := aHeight;
4328 s := TFormatDescriptor.Get(aFormat).PixelSize;
4330 fPixelSize := Ceil(s);
4331 fRowSize := Ceil(s * aWidth);
4335 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4336 function TglBitmap.FlipHorz: Boolean;
4341 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4342 function TglBitmap.FlipVert: Boolean;
4347 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4348 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4349 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4350 procedure TglBitmap.AfterConstruction;
4352 inherited AfterConstruction;
4356 fIsResident := false;
4358 fFormat := glBitmapGetDefaultFormat;
4359 fMipMap := glBitmapDefaultMipmap;
4360 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4361 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4363 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4364 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4367 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4368 procedure TglBitmap.BeforeDestruction;
4370 SetDataPointer(nil, tfEmpty);
4371 if (fID > 0) and fDeleteTextureOnFree then
4372 glDeleteTextures(1, @fID);
4373 inherited BeforeDestruction;
4376 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4377 procedure TglBitmap.LoadFromFile(const aFilename: String);
4381 if not FileExists(aFilename) then
4382 raise EglBitmapException.Create('file does not exist: ' + aFilename);
4383 fFilename := aFilename;
4384 fs := TFileStream.Create(fFilename, fmOpenRead);
4393 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4394 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4396 {$IFDEF GLB_SUPPORT_PNG_READ}
4397 if not LoadPNG(aStream) then
4399 {$IFDEF GLB_SUPPORT_JPEG_READ}
4400 if not LoadJPEG(aStream) then
4402 if not LoadDDS(aStream) then
4403 if not LoadTGA(aStream) then
4404 if not LoadBMP(aStream) then
4405 raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4408 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4409 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4410 const aFormat: TglBitmapFormat; const aArgs: Pointer);
4415 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4416 GetMem(tmpData, size);
4418 FillChar(tmpData^, size, #$FF);
4419 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y);
4424 AddFunc(Self, aFunc, false, Format, aArgs);
4428 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4429 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
4431 rs: TResourceStream;
4436 if not Assigned(ResType) then begin
4437 TempPos := Pos('.', Resource);
4438 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
4439 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
4440 TempResType := PChar(ResTypeStr);
4442 TempResType := ResType
4444 rs := TResourceStream.Create(Instance, Resource, TempResType);
4452 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4453 procedure TglBitmap.LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4455 rs: TResourceStream;
4457 rs := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
4466 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4467 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4471 fs := TFileStream.Create(aFileName, fmCreate);
4474 SaveToStream(fs, aFileType);
4480 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4481 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4484 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4485 ftPNG: SavePNG(aStream);
4487 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4488 ftJPEG: SaveJPEG(aStream);
4490 ftDDS: SaveDDS(aStream);
4491 ftTGA: SaveTGA(aStream);
4492 ftBMP: SaveBMP(aStream);
4496 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4497 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean;
4499 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4502 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4503 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4504 const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean;
4506 DestData, TmpData, SourceData: pByte;
4507 TempHeight, TempWidth: Integer;
4508 SourceFD, DestFD: TFormatDescriptor;
4509 SourceMD, DestMD: Pointer;
4511 FuncRec: TglBitmapFunctionRec;
4513 Assert(Assigned(Data));
4514 Assert(Assigned(aSource));
4515 Assert(Assigned(aSource.Data));
4518 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4519 SourceFD := TFormatDescriptor.Get(aSource.Format);
4520 DestFD := TFormatDescriptor.Get(aFormat);
4522 // inkompatible Formats so CreateTemp
4523 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4524 aCreateTemp := true;
4527 TempHeight := Max(1, aSource.Height);
4528 TempWidth := Max(1, aSource.Width);
4530 FuncRec.Sender := Self;
4531 FuncRec.Args := aArgs;
4534 if aCreateTemp then begin
4535 GetMem(TmpData, TFormatDescriptor.Get(aFormat).GetSize(TempWidth, TempHeight));
4536 DestData := TmpData;
4541 SourceFD.PreparePixel(FuncRec.Source);
4542 DestFD.PreparePixel (FuncRec.Dest);
4544 SourceMD := SourceFD.CreateMappingData;
4545 DestMD := DestFD.CreateMappingData;
4547 FuncRec.Size := aSource.Dimension;
4548 FuncRec.Position.Fields := FuncRec.Size.Fields;
4551 SourceData := aSource.Data;
4552 FuncRec.Position.Y := 0;
4553 while FuncRec.Position.Y < TempHeight do begin
4554 FuncRec.Position.X := 0;
4555 while FuncRec.Position.X < TempWidth do begin
4556 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4558 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4559 inc(FuncRec.Position.X);
4561 inc(FuncRec.Position.Y);
4564 // Updating Image or InternalFormat
4566 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height)
4567 else if (aFormat <> fFormat) then
4572 SourceFD.FreeMappingData(SourceMD);
4573 DestFD.FreeMappingData(DestMD);
4584 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4585 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4587 Row, RowSize: Integer;
4588 SourceData, TmpData: PByte;
4590 FormatDesc: TFormatDescriptor;
4592 function GetRowPointer(Row: Integer): pByte;
4594 result := aSurface.pixels;
4595 Inc(result, Row * RowSize);
4601 FormatDesc := TFormatDescriptor.Get(Format);
4602 if FormatDesc.IsCompressed then
4603 raise EglBitmapUnsupportedFormat.Create(Format);
4605 if Assigned(Data) then begin
4606 case Trunc(FormatDesc.PixelSize) of
4612 raise EglBitmapUnsupportedFormat.Create(Format);
4615 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4616 FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask);
4618 RowSize := FormatDesc.GetSize(FileWidth, 1);
4620 for Row := 0 to FileHeight-1 do begin
4621 TmpData := GetRowPointer(Row);
4622 if Assigned(TmpData) then begin
4623 Move(SourceData^, TmpData^, RowSize);
4624 inc(SourceData, RowSize);
4631 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4632 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4634 pSource, pData, pTempData: PByte;
4635 Row, RowSize, TempWidth, TempHeight: Integer;
4636 IntFormat: TglBitmapFormat;
4637 FormatDesc: TFormatDescriptor;
4639 function GetRowPointer(Row: Integer): pByte;
4641 result := aSurface^.pixels;
4642 Inc(result, Row * RowSize);
4647 if (Assigned(aSurface)) then begin
4648 with aSurface^.format^ do begin
4649 for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin
4650 FormatDesc := TFormatDescriptor.Get(IntFormat);
4651 if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then
4654 if (IntFormat = tfEmpty) then
4655 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4658 TempWidth := aSurface^.w;
4659 TempHeight := aSurface^.h;
4660 RowSize := FormatDesc.GetSize(TempWidth, 1);
4661 GetMem(pData, TempHeight * RowSize);
4664 for Row := 0 to TempHeight -1 do begin
4665 pSource := GetRowPointer(Row);
4666 if (Assigned(pSource)) then begin
4667 Move(pSource^, pTempData^, RowSize);
4668 Inc(pTempData, RowSize);
4671 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
4680 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4681 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4683 Row, Col, AlphaInterleave: Integer;
4684 pSource, pDest: PByte;
4686 function GetRowPointer(Row: Integer): pByte;
4688 result := aSurface.pixels;
4689 Inc(result, Row * Width);
4694 if Assigned(Data) then begin
4695 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4696 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4698 AlphaInterleave := 0;
4701 AlphaInterleave := 1;
4703 AlphaInterleave := 3;
4707 for Row := 0 to Height -1 do begin
4708 pDest := GetRowPointer(Row);
4709 if Assigned(pDest) then begin
4710 for Col := 0 to Width -1 do begin
4711 Inc(pSource, AlphaInterleave);
4723 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4724 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean;
4728 bmp := TglBitmap2D.Create;
4730 bmp.AssignFromSurface(aSurface);
4731 result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs);
4739 //TODO rework & test
4740 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4741 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4744 pSource, pData: PByte;
4747 if Assigned(Data) then begin
4748 if Assigned(aBitmap) then begin
4749 aBitmap.Width := Width;
4750 aBitmap.Height := Height;
4753 tfAlpha8, ifLuminance, ifDepth8:
4755 Bitmap.PixelFormat := pf8bit;
4756 Bitmap.Palette := CreateGrayPalette;
4759 Bitmap.PixelFormat := pf15bit;
4761 Bitmap.PixelFormat := pf16bit;
4763 Bitmap.PixelFormat := pf24bit;
4765 Bitmap.PixelFormat := pf32bit;
4767 raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
4771 for Row := 0 to FileHeight -1 do begin
4772 pData := Bitmap.Scanline[Row];
4774 Move(pSource^, pData^, fRowSize);
4775 Inc(pSource, fRowSize);
4777 // swap RGB(A) to BGR(A)
4778 if InternalFormat in [ifRGB8, ifRGBA8] then
4779 SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8);
4787 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4788 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4790 pSource, pData, pTempData: PByte;
4791 Row, RowSize, TempWidth, TempHeight: Integer;
4792 IntFormat: TglBitmapInternalFormat;
4796 if (Assigned(Bitmap)) then begin
4797 case Bitmap.PixelFormat of
4799 IntFormat := ifLuminance;
4801 IntFormat := ifRGB5A1;
4803 IntFormat := ifR5G6B5;
4805 IntFormat := ifBGR8;
4807 IntFormat := ifBGRA8;
4809 raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
4812 TempWidth := Bitmap.Width;
4813 TempHeight := Bitmap.Height;
4815 RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
4817 GetMem(pData, TempHeight * RowSize);
4821 for Row := 0 to TempHeight -1 do begin
4822 pSource := Bitmap.Scanline[Row];
4824 if (Assigned(pSource)) then begin
4825 Move(pSource^, pTempData^, RowSize);
4826 Inc(pTempData, RowSize);
4830 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
4840 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4841 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4843 Row, Col, AlphaInterleave: Integer;
4844 pSource, pDest: PByte;
4848 if Assigned(Data) then begin
4849 if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin
4850 if Assigned(Bitmap) then begin
4851 Bitmap.PixelFormat := pf8bit;
4852 Bitmap.Palette := CreateGrayPalette;
4853 Bitmap.Width := Width;
4854 Bitmap.Height := Height;
4856 case InternalFormat of
4858 AlphaInterleave := 1;
4860 AlphaInterleave := 3;
4862 AlphaInterleave := 0;
4868 for Row := 0 to Height -1 do begin
4869 pDest := Bitmap.Scanline[Row];
4871 if Assigned(pDest) then begin
4872 for Col := 0 to Width -1 do begin
4873 Inc(pSource, AlphaInterleave);
4887 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4888 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4892 tex := TglBitmap2D.Create;
4894 tex.AssignFromBitmap(Bitmap);
4895 result := AddAlphaFromglBitmap(tex, Func, CustomData);
4901 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4902 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar;
4903 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4905 RS: TResourceStream;
4910 if Assigned(ResType) then
4911 TempResType := ResType
4914 TempPos := Pos('.', Resource);
4915 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
4916 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
4917 TempResType := PChar(ResTypeStr);
4920 RS := TResourceStream.Create(Instance, Resource, TempResType);
4922 result := AddAlphaFromStream(RS, Func, CustomData);
4928 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4929 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
4930 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4932 RS: TResourceStream;
4934 RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
4936 result := AddAlphaFromStream(RS, Func, CustomData);
4943 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4944 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4946 if TFormatDescriptor.Get(Format).IsCompressed then
4947 raise EglBitmapUnsupportedFormat.Create(Format);
4948 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
4951 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4952 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4956 FS := TFileStream.Create(FileName, fmOpenRead);
4958 result := AddAlphaFromStream(FS, aFunc, aArgs);
4964 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4965 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4969 tex := TglBitmap2D.Create(aStream);
4971 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4977 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4978 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean;
4980 DestData, DestData2, SourceData: pByte;
4981 TempHeight, TempWidth: Integer;
4982 SourceFD, DestFD: TFormatDescriptor;
4983 SourceMD, DestMD, DestMD2: Pointer;
4985 FuncRec: TglBitmapFunctionRec;
4989 Assert(Assigned(Data));
4990 Assert(Assigned(aBitmap));
4991 Assert(Assigned(aBitmap.Data));
4993 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
4994 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
4996 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
4997 DestFD := TFormatDescriptor.Get(Format);
4999 if not Assigned(aFunc) then begin
5000 aFunc := glBitmapAlphaFunc;
5001 FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha);
5003 FuncRec.Args := aArgs;
5006 TempHeight := aBitmap.FileHeight;
5007 TempWidth := aBitmap.FileWidth;
5009 FuncRec.Sender := Self;
5010 FuncRec.Size := Dimension;
5011 FuncRec.Position.Fields := FuncRec.Size.Fields;
5015 SourceData := aBitmap.Data;
5018 SourceFD.PreparePixel(FuncRec.Source);
5019 DestFD.PreparePixel (FuncRec.Dest);
5021 SourceMD := SourceFD.CreateMappingData;
5022 DestMD := DestFD.CreateMappingData;
5023 DestMD2 := DestFD.CreateMappingData;
5025 FuncRec.Position.Y := 0;
5026 while FuncRec.Position.Y < TempHeight do begin
5027 FuncRec.Position.X := 0;
5028 while FuncRec.Position.X < TempWidth do begin
5029 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
5030 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
5032 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
5033 inc(FuncRec.Position.X);
5035 inc(FuncRec.Position.Y);
5038 SourceFD.FreeMappingData(SourceMD);
5039 DestFD.FreeMappingData(DestMD);
5040 DestFD.FreeMappingData(DestMD2);
5045 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5046 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
5048 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
5051 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5052 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
5054 PixelData: TglBitmapPixelData;
5056 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5057 result := AddAlphaFromColorKeyFloat(
5058 aRed / PixelData.Range.r,
5059 aGreen / PixelData.Range.g,
5060 aBlue / PixelData.Range.b,
5061 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
5064 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5065 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
5067 values: array[0..2] of Single;
5070 PixelData: TglBitmapPixelData;
5072 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5073 with PixelData do begin
5075 values[1] := aGreen;
5078 for i := 0 to 2 do begin
5079 tmp := Trunc(Range.arr[i] * aDeviation);
5080 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
5081 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
5086 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
5089 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5090 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
5092 result := AddAlphaFromValueFloat(aAlpha / $FF);
5095 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5096 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
5098 PixelData: TglBitmapPixelData;
5100 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5101 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
5104 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5105 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
5107 PixelData: TglBitmapPixelData;
5109 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5111 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
5112 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a);
5115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5116 function TglBitmap.RemoveAlpha: Boolean;
5118 FormatDesc: TFormatDescriptor;
5121 FormatDesc := TFormatDescriptor.Get(Format);
5122 if Assigned(Data) then begin
5123 if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then
5124 raise EglBitmapUnsupportedFormat.Create(Format);
5125 result := ConvertTo(FormatDesc.WithoutAlpha);
5129 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5130 function TglBitmap.Clone: TglBitmap;
5137 Temp := (ClassType.Create as TglBitmap);
5139 // copy texture data if assigned
5140 if Assigned(Data) then begin
5141 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
5142 GetMem(TempPtr, Size);
5144 Move(Data^, TempPtr^, Size);
5145 Temp.SetDataPointer(TempPtr, Format, Width, Height);
5151 Temp.SetDataPointer(nil, Format, Width, Height);
5155 Temp.fTarget := Target;
5156 Temp.fFormat := Format;
5157 Temp.fMipMap := MipMap;
5158 Temp.fAnisotropic := Anisotropic;
5159 Temp.fBorderColor := fBorderColor;
5160 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
5161 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
5162 Temp.fFilterMin := fFilterMin;
5163 Temp.fFilterMag := fFilterMag;
5164 Temp.fWrapS := fWrapS;
5165 Temp.fWrapT := fWrapT;
5166 Temp.fWrapR := fWrapR;
5167 Temp.fFilename := fFilename;
5168 Temp.fCustomName := fCustomName;
5169 Temp.fCustomNameW := fCustomNameW;
5170 Temp.fCustomData := fCustomData;
5179 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5180 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
5182 SourceFD, DestFD: TFormatDescriptor;
5183 SourcePD, DestPD: TglBitmapPixelData;
5184 ShiftData: TShiftData;
5186 function CanCopyDirect: Boolean;
5189 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5190 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5191 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5192 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5195 function CanShift: Boolean;
5198 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
5199 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
5200 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
5201 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5204 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5207 while (aSource > aDest) and (aSource > 0) do begin
5209 aSource := aSource shr 1;
5214 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5215 SourceFD := TFormatDescriptor.Get(Format);
5216 DestFD := TFormatDescriptor.Get(aFormat);
5218 SourceFD.PreparePixel(SourcePD);
5219 DestFD.PreparePixel (DestPD);
5221 if CanCopyDirect then
5222 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5223 else if CanShift then begin
5224 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5225 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5226 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5227 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5228 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData);
5230 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5235 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5236 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5238 if aUseRGB or aUseAlpha then
5239 AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
5240 ((PtrInt(aUseAlpha) and 1) shl 1) or
5241 (PtrInt(aUseRGB) and 1) ));
5244 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5245 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5247 fBorderColor[0] := aRed;
5248 fBorderColor[1] := aGreen;
5249 fBorderColor[2] := aBlue;
5250 fBorderColor[3] := aAlpha;
5251 if (ID > 0) then begin
5253 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5257 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5258 procedure TglBitmap.FreeData;
5260 SetDataPointer(nil, tfEmpty);
5263 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5264 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5265 const aAlpha: Byte);
5267 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5270 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5271 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5273 PixelData: TglBitmapPixelData;
5275 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5277 aRed / PixelData.Range.r,
5278 aGreen / PixelData.Range.g,
5279 aBlue / PixelData.Range.b,
5280 aAlpha / PixelData.Range.a);
5283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5284 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5286 PixelData: TglBitmapPixelData;
5288 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5289 with PixelData do begin
5290 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5291 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5292 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5293 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5295 AddFunc(glBitmapFillWithColorFunc, false, @PixelData);
5298 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5299 procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal);
5304 fFilterMin := GL_NEAREST;
5306 fFilterMin := GL_LINEAR;
5307 GL_NEAREST_MIPMAP_NEAREST:
5308 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5309 GL_LINEAR_MIPMAP_NEAREST:
5310 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5311 GL_NEAREST_MIPMAP_LINEAR:
5312 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5313 GL_LINEAR_MIPMAP_LINEAR:
5314 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5316 raise EglBitmapException.Create('SetFilter - Unknow MIN filter.');
5322 fFilterMag := GL_NEAREST;
5324 fFilterMag := GL_LINEAR;
5326 raise EglBitmapException.Create('SetFilter - Unknow MAG filter.');
5330 if (ID > 0) then begin
5332 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5334 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5336 GL_NEAREST, GL_LINEAR:
5337 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5338 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5339 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5340 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5341 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5344 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5348 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5349 procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; const R: Cardinal);
5351 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5355 aTarget := GL_CLAMP;
5358 aTarget := GL_REPEAT;
5360 GL_CLAMP_TO_EDGE: begin
5361 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5362 aTarget := GL_CLAMP_TO_EDGE
5364 aTarget := GL_CLAMP;
5367 GL_CLAMP_TO_BORDER: begin
5368 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5369 aTarget := GL_CLAMP_TO_BORDER
5371 aTarget := GL_CLAMP;
5374 GL_MIRRORED_REPEAT: begin
5375 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5376 aTarget := GL_MIRRORED_REPEAT
5378 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5381 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).');
5386 CheckAndSetWrap(S, fWrapS);
5387 CheckAndSetWrap(T, fWrapT);
5388 CheckAndSetWrap(R, fWrapR);
5390 if (ID > 0) then begin
5392 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5393 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5394 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5398 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5399 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5401 if aEnableTextureUnit then
5404 glBindTexture(Target, ID);
5407 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5408 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5410 if aDisableTextureUnit then
5412 glBindTexture(Target, 0);
5415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5416 constructor TglBitmap.Create;
5418 {$IFDEF GLB_NATIVE_OGL}
5419 glbReadOpenGLExtensions;
5421 if (ClassType = TglBitmap) then
5422 raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5426 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5427 constructor TglBitmap.Create(const aFileName: String);
5430 LoadFromFile(FileName);
5433 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5434 constructor TglBitmap.Create(const aStream: TStream);
5437 LoadFromStream(aStream);
5440 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5441 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
5447 ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
5448 GetMem(Image, ImageSize);
5450 FillChar(Image^, ImageSize, #$FF);
5451 SetDataPointer(Image, aFormat, aSize.X, aSize.Y);
5458 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5459 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
5460 const aFunc: TglBitmapFunction; const aArgs: Pointer);
5463 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5467 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5468 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5471 LoadFromResource(aInstance, aResource, aResType);
5474 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5475 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5478 LoadFromResourceID(aInstance, aResourceID, aResType);
5482 {$IFDEF GLB_SUPPORT_PNG_READ}
5483 {$IF DEFINED(GLB_SDL_IMAGE)}
5484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5485 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5486 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5487 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5489 Surface: PSDL_Surface;
5493 RWops := glBitmapCreateRWops(aStream);
5495 if IMG_isPNG(RWops) > 0 then begin
5496 Surface := IMG_LoadPNG_RW(RWops);
5498 AssignFromSurface(Surface);
5501 SDL_FreeSurface(Surface);
5509 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5510 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5511 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5513 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5516 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5517 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5520 signature: array [0..7] of byte;
5522 png_info: png_infop;
5524 TempHeight, TempWidth: Integer;
5525 Format: TglBitmapFormat;
5528 png_rows: array of pByte;
5529 Row, LineSize: Integer;
5533 if not init_libPNG then
5534 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5538 StreamPos := aStream.Position;
5539 aStream.Read(signature{%H-}, 8);
5540 aStream.Position := StreamPos;
5542 if png_check_sig(@signature, 8) <> 0 then begin
5544 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5546 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5549 png_info := png_create_info_struct(png);
5550 if png_info = nil then begin
5551 png_destroy_read_struct(@png, nil, nil);
5552 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5555 // set read callback
5556 png_set_read_fn(png, aStream, glBitmap_libPNG_read_func);
5558 // read informations
5559 png_read_info(png, png_info);
5562 TempHeight := png_get_image_height(png, png_info);
5563 TempWidth := png_get_image_width(png, png_info);
5566 case png_get_color_type(png, png_info) of
5567 PNG_COLOR_TYPE_GRAY:
5568 Format := tfLuminance8;
5569 PNG_COLOR_TYPE_GRAY_ALPHA:
5570 Format := tfLuminance8Alpha8;
5573 PNG_COLOR_TYPE_RGB_ALPHA:
5576 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5579 // cut upper 8 bit from 16 bit formats
5580 if png_get_bit_depth(png, png_info) > 8 then
5581 png_set_strip_16(png);
5583 // expand bitdepth smaller than 8
5584 if png_get_bit_depth(png, png_info) < 8 then
5585 png_set_expand(png);
5587 // allocating mem for scanlines
5588 LineSize := png_get_rowbytes(png, png_info);
5589 GetMem(png_data, TempHeight * LineSize);
5591 SetLength(png_rows, TempHeight);
5592 for Row := Low(png_rows) to High(png_rows) do begin
5593 png_rows[Row] := png_data;
5594 Inc(png_rows[Row], Row * LineSize);
5597 // read complete image into scanlines
5598 png_read_image(png, @png_rows[0]);
5601 png_read_end(png, png_info);
5603 // destroy read struct
5604 png_destroy_read_struct(@png, @png_info, nil);
5606 SetLength(png_rows, 0);
5609 SetDataPointer(png_data, Format, TempWidth, TempHeight);
5622 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5623 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5624 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5628 Header: Array[0..7] of Byte;
5629 Row, Col, PixSize, LineSize: Integer;
5630 NewImage, pSource, pDest, pAlpha: pByte;
5631 Format: TglBitmapInternalFormat;
5634 PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10);
5639 StreamPos := Stream.Position;
5640 Stream.Read(Header[0], SizeOf(Header));
5641 Stream.Position := StreamPos;
5643 {Test if the header matches}
5644 if Header = PngHeader then begin
5645 Png := TPNGObject.Create;
5647 Png.LoadFromStream(Stream);
5649 case Png.Header.ColorType of
5651 Format := ifLuminance;
5652 COLOR_GRAYSCALEALPHA:
5653 Format := ifLuminanceAlpha;
5659 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5662 PixSize := Trunc(FormatGetSize(Format));
5663 LineSize := Integer(Png.Header.Width) * PixSize;
5665 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5669 case Png.Header.ColorType of
5670 COLOR_RGB, COLOR_GRAYSCALE:
5672 for Row := 0 to Png.Height -1 do begin
5673 Move (Png.Scanline[Row]^, pDest^, LineSize);
5674 Inc(pDest, LineSize);
5677 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5679 PixSize := PixSize -1;
5681 for Row := 0 to Png.Height -1 do begin
5682 pSource := Png.Scanline[Row];
5683 pAlpha := pByte(Png.AlphaScanline[Row]);
5685 for Col := 0 to Png.Width -1 do begin
5686 Move (pSource^, pDest^, PixSize);
5687 Inc(pSource, PixSize);
5688 Inc(pDest, PixSize);
5697 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5700 SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height);
5715 {$IFDEF GLB_SUPPORT_PNG_WRITE}
5716 {$IFDEF GLB_LIB_PNG}
5717 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5718 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5720 TStream(png_get_io_ptr(png)).Write(buffer^, size);
5724 {$IF DEFINED(GLB_LIB_PNG)}
5725 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5726 procedure TglBitmap.SavePNG(const aStream: TStream);
5729 png_info: png_infop;
5730 png_rows: array of pByte;
5734 FormatDesc: TFormatDescriptor;
5736 if not (ftPNG in FormatGetSupportedFiles(Format)) then
5737 raise EglBitmapUnsupportedFormat.Create(Format);
5739 if not init_libPNG then
5740 raise Exception.Create('unable to initialize libPNG.');
5744 tfAlpha8, tfLuminance8:
5745 ColorType := PNG_COLOR_TYPE_GRAY;
5747 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
5749 ColorType := PNG_COLOR_TYPE_RGB;
5751 ColorType := PNG_COLOR_TYPE_RGBA;
5753 raise EglBitmapUnsupportedFormat.Create(Format);
5756 FormatDesc := TFormatDescriptor.Get(Format);
5757 LineSize := FormatDesc.GetSize(Width, 1);
5759 // creating array for scanline
5760 SetLength(png_rows, Height);
5762 for Row := 0 to Height - 1 do begin
5763 png_rows[Row] := Data;
5764 Inc(png_rows[Row], Row * LineSize)
5768 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5770 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
5773 png_info := png_create_info_struct(png);
5774 if png_info = nil then begin
5775 png_destroy_write_struct(@png, nil);
5776 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
5779 // set read callback
5780 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
5783 png_set_compression_level(png, 6);
5785 if Format in [tfBGR8, tfBGRA8] then
5788 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
5789 png_write_info(png, png_info);
5790 png_write_image(png, @png_rows[0]);
5791 png_write_end(png, png_info);
5792 png_destroy_write_struct(@png, @png_info);
5794 SetLength(png_rows, 0);
5801 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5802 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5803 procedure TglBitmap.SavePNG(const aStream: TStream);
5807 pSource, pDest: pByte;
5808 X, Y, PixSize: Integer;
5809 ColorType: Cardinal;
5815 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
5816 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5818 case FInternalFormat of
5819 ifAlpha, ifLuminance, ifDepth8: begin
5820 ColorType := COLOR_GRAYSCALE;
5824 ifLuminanceAlpha: begin
5825 ColorType := COLOR_GRAYSCALEALPHA;
5829 ifBGR8, ifRGB8: begin
5830 ColorType := COLOR_RGB;
5834 ifBGRA8, ifRGBA8: begin
5835 ColorType := COLOR_RGBALPHA;
5840 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5843 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
5847 for Y := 0 to Height -1 do begin
5848 pDest := png.ScanLine[Y];
5849 for X := 0 to Width -1 do begin
5850 Move(pSource^, pDest^, PixSize);
5851 Inc(pDest, PixSize);
5852 Inc(pSource, PixSize);
5854 png.AlphaScanline[Y]^[X] := pSource^;
5859 // convert RGB line to BGR
5860 if InternalFormat in [ifRGB8, ifRGBA8] then begin
5861 pTemp := png.ScanLine[Y];
5862 for X := 0 to Width -1 do begin
5863 Temp := pByteArray(pTemp)^[0];
5864 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
5865 pByteArray(pTemp)^[2] := Temp;
5872 Png.CompressionLevel := 6;
5873 Png.SaveToStream(Stream);
5881 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5882 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5883 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5884 {$IFDEF GLB_LIB_JPEG}
5886 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
5887 glBitmap_libJPEG_source_mgr = record
5888 pub: jpeg_source_mgr;
5891 SrcBuffer: array [1..4096] of byte;
5894 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
5895 glBitmap_libJPEG_dest_mgr = record
5896 pub: jpeg_destination_mgr;
5898 DestStream: TStream;
5899 DestBuffer: array [1..4096] of byte;
5902 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
5908 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
5914 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
5919 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
5925 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
5931 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5932 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
5934 src: glBitmap_libJPEG_source_mgr_ptr;
5937 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5939 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
5940 if (bytes <= 0) then begin
5941 src^.SrcBuffer[1] := $FF;
5942 src^.SrcBuffer[2] := JPEG_EOI;
5946 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
5947 src^.pub.bytes_in_buffer := bytes;
5952 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5953 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
5955 src: glBitmap_libJPEG_source_mgr_ptr;
5957 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5959 if num_bytes > 0 then begin
5960 // wanted byte isn't in buffer so set stream position and read buffer
5961 if num_bytes > src^.pub.bytes_in_buffer then begin
5962 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
5963 src^.pub.fill_input_buffer(cinfo);
5965 // wanted byte is in buffer so only skip
5966 inc(src^.pub.next_input_byte, num_bytes);
5967 dec(src^.pub.bytes_in_buffer, num_bytes);
5972 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5973 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
5975 dest: glBitmap_libJPEG_dest_mgr_ptr;
5977 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5979 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
5980 // write complete buffer
5981 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
5984 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
5985 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
5991 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5992 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
5995 dest: glBitmap_libJPEG_dest_mgr_ptr;
5997 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5999 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6000 // check for endblock
6001 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6003 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6008 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6013 {$IFDEF GLB_SUPPORT_JPEG_READ}
6014 {$IF DEFINED(GLB_SDL_IMAGE)}
6015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6016 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6018 Surface: PSDL_Surface;
6023 RWops := glBitmapCreateRWops(aStream);
6025 if IMG_isJPG(RWops) > 0 then begin
6026 Surface := IMG_LoadJPG_RW(RWops);
6028 AssignFromSurface(Surface);
6031 SDL_FreeSurface(Surface);
6039 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6040 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6041 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6044 Temp: array[0..1]of Byte;
6046 jpeg: jpeg_decompress_struct;
6047 jpeg_err: jpeg_error_mgr;
6049 IntFormat: TglBitmapFormat;
6051 TempHeight, TempWidth: Integer;
6056 FormatDesc: TFormatDescriptor;
6060 if not init_libJPEG then
6061 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6064 // reading first two bytes to test file and set cursor back to begin
6065 StreamPos := aStream.Position;
6066 aStream.Read({%H-}Temp[0], 2);
6067 aStream.Position := StreamPos;
6069 // if Bitmap then read file.
6070 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6071 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6072 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6075 jpeg.err := jpeg_std_error(@jpeg_err);
6076 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6077 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6079 // decompression struct
6080 jpeg_create_decompress(@jpeg);
6082 // allocation space for streaming methods
6083 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6085 // seeting up custom functions
6086 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6087 pub.init_source := glBitmap_libJPEG_init_source;
6088 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6089 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6090 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6091 pub.term_source := glBitmap_libJPEG_term_source;
6093 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6094 pub.next_input_byte := nil; // until buffer loaded
6096 SrcStream := aStream;
6099 // set global decoding state
6100 jpeg.global_state := DSTATE_START;
6102 // read header of jpeg
6103 jpeg_read_header(@jpeg, false);
6105 // setting output parameter
6106 case jpeg.jpeg_color_space of
6109 jpeg.out_color_space := JCS_GRAYSCALE;
6110 IntFormat := tfLuminance8;
6113 jpeg.out_color_space := JCS_RGB;
6114 IntFormat := tfRGB8;
6118 jpeg_start_decompress(@jpeg);
6120 TempHeight := jpeg.output_height;
6121 TempWidth := jpeg.output_width;
6123 FormatDesc := TFormatDescriptor.Get(IntFormat);
6125 // creating new image
6126 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6130 for Row := 0 to TempHeight -1 do begin
6131 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6132 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6135 // finish decompression
6136 jpeg_finish_decompress(@jpeg);
6138 // destroy decompression
6139 jpeg_destroy_decompress(@jpeg);
6141 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight);
6154 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6156 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6161 Temp: array[0..1]of Byte;
6165 // reading first two bytes to test file and set cursor back to begin
6166 StreamPos := Stream.Position;
6167 Stream.Read(Temp[0], 2);
6168 Stream.Position := StreamPos;
6170 // if Bitmap then read file.
6171 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6172 bmp := TBitmap.Create;
6174 jpg := TJPEGImage.Create;
6176 jpg.LoadFromStream(Stream);
6178 result := AssignFromBitmap(bmp);
6190 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6191 {$IF DEFINED(GLB_LIB_JPEG)}
6192 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6193 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6195 jpeg: jpeg_compress_struct;
6196 jpeg_err: jpeg_error_mgr;
6198 pTemp, pTemp2: pByte;
6200 procedure CopyRow(pDest, pSource: pByte);
6204 for X := 0 to Width - 1 do begin
6205 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6206 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6207 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6214 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6215 raise EglBitmapUnsupportedFormat.Create(Format);
6217 if not init_libJPEG then
6218 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6221 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6222 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6225 jpeg.err := jpeg_std_error(@jpeg_err);
6226 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6227 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6229 // compression struct
6230 jpeg_create_compress(@jpeg);
6232 // allocation space for streaming methods
6233 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6235 // seeting up custom functions
6236 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6237 pub.init_destination := glBitmap_libJPEG_init_destination;
6238 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6239 pub.term_destination := glBitmap_libJPEG_term_destination;
6241 pub.next_output_byte := @DestBuffer[1];
6242 pub.free_in_buffer := Length(DestBuffer);
6244 DestStream := aStream;
6247 // very important state
6248 jpeg.global_state := CSTATE_START;
6249 jpeg.image_width := Width;
6250 jpeg.image_height := Height;
6252 tfAlpha8, tfLuminance8: begin
6253 jpeg.input_components := 1;
6254 jpeg.in_color_space := JCS_GRAYSCALE;
6256 tfRGB8, tfBGR8: begin
6257 jpeg.input_components := 3;
6258 jpeg.in_color_space := JCS_RGB;
6262 jpeg_set_defaults(@jpeg);
6263 jpeg_set_quality(@jpeg, 95, true);
6264 jpeg_start_compress(@jpeg, true);
6267 if Format = tfBGR8 then
6268 GetMem(pTemp2, fRowSize)
6273 for Row := 0 to jpeg.image_height -1 do begin
6275 if Format = tfBGR8 then
6276 CopyRow(pTemp2, pTemp)
6281 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6282 inc(pTemp, fRowSize);
6286 if Format = tfBGR8 then
6289 jpeg_finish_compress(@jpeg);
6290 jpeg_destroy_compress(@jpeg);
6296 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6297 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6298 procedure TglBitmap.SaveJPEG(Stream: TStream);
6303 if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then
6304 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
6306 Bmp := TBitmap.Create;
6308 Jpg := TJPEGImage.Create;
6310 AssignToBitmap(Bmp);
6311 if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
6312 Jpg.Grayscale := true;
6313 Jpg.PixelFormat := jf8Bit;
6316 Jpg.SaveToStream(Stream);
6327 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6328 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6329 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6336 BMP_COMP_BITFIELDS = 3;
6339 TBMPHeader = packed record
6344 bfOffBits: Cardinal;
6347 TBMPInfo = packed record
6353 biCompression: Cardinal;
6354 biSizeImage: Cardinal;
6355 biXPelsPerMeter: Longint;
6356 biYPelsPerMeter: Longint;
6357 biClrUsed: Cardinal;
6358 biClrImportant: Cardinal;
6361 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6362 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6364 //////////////////////////////////////////////////////////////////////////////////////////////////
6365 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6368 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6369 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6372 case aInfo.biCompression of
6374 BMP_COMP_RLE8: begin
6375 raise EglBitmapException.Create('RLE compression is not supported');
6377 BMP_COMP_BITFIELDS: begin
6378 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6379 aStream.Read(aMask.r, SizeOf(aMask.r));
6380 aStream.Read(aMask.g, SizeOf(aMask.g));
6381 aStream.Read(aMask.b, SizeOf(aMask.b));
6382 aStream.Read(aMask.a, SizeOf(aMask.a));
6384 raise EglBitmapException.Create('Bitfields are only supported for 16bit and 32bit formats');
6388 //get suitable format
6389 case aInfo.biBitCount of
6390 8: result := tfLuminance8;
6391 16: result := tfBGR5;
6392 24: result := tfBGR8;
6393 32: result := tfBGRA8;
6397 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6400 ColorTable: TbmpColorTable;
6403 if (aInfo.biBitCount >= 16) then
6405 aFormat := tfLuminance8;
6406 c := aInfo.biClrUsed;
6408 c := 1 shl aInfo.biBitCount;
6409 SetLength(ColorTable, c);
6410 for i := 0 to c-1 do begin
6411 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6412 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6416 result := TbmpColorTableFormat.Create;
6417 result.PixelSize := aInfo.biBitCount / 8;
6418 result.ColorTable := ColorTable;
6419 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6422 //////////////////////////////////////////////////////////////////////////////////////////////////
6423 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6424 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6426 TmpFormat: TglBitmapFormat;
6427 FormatDesc: TFormatDescriptor;
6430 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6431 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6432 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6433 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6434 aFormat := FormatDesc.Format;
6439 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6440 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6441 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6442 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6444 result := TbmpBitfieldFormat.Create;
6445 result.PixelSize := aInfo.biBitCount / 8;
6446 result.RedMask := aMask.r;
6447 result.GreenMask := aMask.g;
6448 result.BlueMask := aMask.b;
6449 result.AlphaMask := aMask.a;
6456 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6457 PaddingBuff: Cardinal;
6458 LineBuf, ImageData, TmpData: PByte;
6459 SourceMD, DestMD: Pointer;
6460 BmpFormat: TglBitmapFormat;
6463 Mask: TglBitmapColorRec;
6468 SpecialFormat: TFormatDescriptor;
6469 FormatDesc: TFormatDescriptor;
6471 //////////////////////////////////////////////////////////////////////////////////////////////////
6472 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6475 Pixel: TglBitmapPixelData;
6477 aStream.Read(aLineBuf^, rbLineSize);
6478 SpecialFormat.PreparePixel(Pixel);
6479 for i := 0 to Info.biWidth-1 do begin
6480 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6481 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6482 FormatDesc.Map(Pixel, aData, DestMD);
6488 BmpFormat := tfEmpty;
6489 SpecialFormat := nil;
6495 StartPos := aStream.Position;
6496 aStream.Read(Header{%H-}, SizeOf(Header));
6498 if Header.bfType = BMP_MAGIC then begin
6500 BmpFormat := ReadInfo(Info, Mask);
6501 SpecialFormat := ReadColorTable(BmpFormat, Info);
6502 if not Assigned(SpecialFormat) then
6503 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6504 aStream.Position := StartPos + Header.bfOffBits;
6506 if (BmpFormat <> tfEmpty) then begin
6507 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6508 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6509 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6510 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6513 DestMD := FormatDesc.CreateMappingData;
6514 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6515 GetMem(ImageData, ImageSize);
6516 if Assigned(SpecialFormat) then begin
6517 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6518 SourceMD := SpecialFormat.CreateMappingData;
6523 FillChar(ImageData^, ImageSize, $FF);
6524 TmpData := ImageData;
6525 if (Info.biHeight > 0) then
6526 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6527 for i := 0 to Abs(Info.biHeight)-1 do begin
6528 if Assigned(SpecialFormat) then
6529 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6531 aStream.Read(TmpData^, wbLineSize); //else only read data
6532 if (Info.biHeight > 0) then
6533 dec(TmpData, wbLineSize)
6535 inc(TmpData, wbLineSize);
6536 aStream.Read(PaddingBuff{%H-}, Padding);
6538 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight));
6541 if Assigned(LineBuf) then
6543 if Assigned(SourceMD) then
6544 SpecialFormat.FreeMappingData(SourceMD);
6545 FormatDesc.FreeMappingData(DestMD);
6552 raise EglBitmapException.Create('LoadBMP - No suitable format found');
6554 aStream.Position := StartPos;
6558 FreeAndNil(SpecialFormat);
6561 else aStream.Position := StartPos;
6564 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6565 procedure TglBitmap.SaveBMP(const aStream: TStream);
6569 Converter: TbmpColorTableFormat;
6570 FormatDesc: TFormatDescriptor;
6571 SourceFD, DestFD: Pointer;
6572 pData, srcData, dstData, ConvertBuffer: pByte;
6574 Pixel: TglBitmapPixelData;
6575 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6576 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6578 PaddingBuff: Cardinal;
6580 function GetLineWidth : Integer;
6582 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6586 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6587 raise EglBitmapUnsupportedFormat.Create(Format);
6590 FormatDesc := TFormatDescriptor.Get(Format);
6591 ImageSize := FormatDesc.GetSize(Dimension);
6593 FillChar(Header{%H-}, SizeOf(Header), 0);
6594 Header.bfType := BMP_MAGIC;
6595 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6596 Header.bfReserved1 := 0;
6597 Header.bfReserved2 := 0;
6598 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6600 FillChar(Info{%H-}, SizeOf(Info), 0);
6601 Info.biSize := SizeOf(Info);
6602 Info.biWidth := Width;
6603 Info.biHeight := Height;
6605 Info.biCompression := BMP_COMP_RGB;
6606 Info.biSizeImage := ImageSize;
6611 Info.biBitCount := 4;
6612 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6613 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6614 Converter := TbmpColorTableFormat.Create;
6615 Converter.PixelSize := 0.5;
6616 Converter.Format := Format;
6617 Converter.Range := glBitmapColorRec($F, $F, $F, $0);
6618 Converter.CreateColorTable;
6621 tfR3G3B2, tfLuminance8: begin
6622 Info.biBitCount := 8;
6623 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6624 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6625 Converter := TbmpColorTableFormat.Create;
6626 Converter.PixelSize := 1;
6627 Converter.Format := Format;
6628 if (Format = tfR3G3B2) then begin
6629 Converter.Range := glBitmapColorRec($7, $7, $3, $0);
6630 Converter.Shift := glBitmapShiftRec(0, 3, 6, 0);
6632 Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0);
6633 Converter.CreateColorTable;
6636 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6637 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6638 Info.biBitCount := 16;
6639 Info.biCompression := BMP_COMP_BITFIELDS;
6642 tfBGR8, tfRGB8: begin
6643 Info.biBitCount := 24;
6646 tfRGB10, tfRGB10A2, tfRGBA8,
6647 tfBGR10, tfBGR10A2, tfBGRA8: begin
6648 Info.biBitCount := 32;
6649 Info.biCompression := BMP_COMP_BITFIELDS;
6652 raise EglBitmapUnsupportedFormat.Create(Format);
6654 Info.biXPelsPerMeter := 2835;
6655 Info.biYPelsPerMeter := 2835;
6658 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6659 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
6660 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
6662 RedMask := FormatDesc.RedMask;
6663 GreenMask := FormatDesc.GreenMask;
6664 BlueMask := FormatDesc.BlueMask;
6665 AlphaMask := FormatDesc.AlphaMask;
6669 aStream.Write(Header, SizeOf(Header));
6670 aStream.Write(Info, SizeOf(Info));
6673 if Assigned(Converter) then
6674 aStream.Write(Converter.ColorTable[0].b,
6675 SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable));
6678 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6679 aStream.Write(RedMask, SizeOf(Cardinal));
6680 aStream.Write(GreenMask, SizeOf(Cardinal));
6681 aStream.Write(BlueMask, SizeOf(Cardinal));
6682 aStream.Write(AlphaMask, SizeOf(Cardinal));
6686 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
6687 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
6688 Padding := GetLineWidth - wbLineSize;
6692 inc(pData, (Height-1) * rbLineSize);
6694 // prepare row buffer. But only for RGB because RGBA supports color masks
6695 // so it's possible to change color within the image.
6696 if Assigned(Converter) then begin
6697 FormatDesc.PreparePixel(Pixel);
6698 GetMem(ConvertBuffer, wbLineSize);
6699 SourceFD := FormatDesc.CreateMappingData;
6700 DestFD := Converter.CreateMappingData;
6702 ConvertBuffer := nil;
6705 for LineIdx := 0 to Height - 1 do begin
6707 if Assigned(Converter) then begin
6709 dstData := ConvertBuffer;
6710 for PixelIdx := 0 to Info.biWidth-1 do begin
6711 FormatDesc.Unmap(srcData, Pixel, SourceFD);
6712 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
6713 Converter.Map(Pixel, dstData, DestFD);
6715 aStream.Write(ConvertBuffer^, wbLineSize);
6717 aStream.Write(pData^, rbLineSize);
6719 dec(pData, rbLineSize);
6720 if (Padding > 0) then
6721 aStream.Write(PaddingBuff, Padding);
6724 // destroy row buffer
6725 if Assigned(ConvertBuffer) then begin
6726 FormatDesc.FreeMappingData(SourceFD);
6727 Converter.FreeMappingData(DestFD);
6728 FreeMem(ConvertBuffer);
6732 if Assigned(Converter) then
6737 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6738 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6739 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6741 TTGAHeader = packed record
6745 //ColorMapSpec: Array[0..4] of Byte;
6746 ColorMapStart: Word;
6747 ColorMapLength: Word;
6748 ColorMapEntrySize: Byte;
6758 TGA_UNCOMPRESSED_RGB = 2;
6759 TGA_UNCOMPRESSED_GRAY = 3;
6760 TGA_COMPRESSED_RGB = 10;
6761 TGA_COMPRESSED_GRAY = 11;
6763 TGA_NONE_COLOR_TABLE = 0;
6765 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6766 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
6769 ImageData: System.PByte;
6770 StartPosition: Int64;
6771 PixelSize, LineSize: Integer;
6772 tgaFormat: TglBitmapFormat;
6773 FormatDesc: TFormatDescriptor;
6774 Counter: packed record
6776 low, high, dir: Integer;
6783 ////////////////////////////////////////////////////////////////////////////////////////
6784 procedure ReadUncompressed;
6787 buf, tmp1, tmp2: System.PByte;
6790 if (Counter.X.dir < 0) then
6791 buf := GetMem(LineSize);
6793 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
6794 tmp1 := ImageData + (Counter.Y.low * LineSize); //pointer to LineStart
6795 if (Counter.X.dir < 0) then begin //flip X
6796 aStream.Read(buf^, LineSize);
6797 tmp2 := buf + LineSize - PixelSize; //pointer to last pixel in line
6798 for i := 0 to Header.Width-1 do begin //for all pixels in line
6799 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
6804 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
6807 aStream.Read(tmp1^, LineSize);
6808 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
6811 if Assigned(buf) then
6816 ////////////////////////////////////////////////////////////////////////////////////////
6817 procedure ReadCompressed;
6819 /////////////////////////////////////////////////////////////////
6821 TmpData: System.PByte;
6822 LinePixelsRead: Integer;
6823 procedure CheckLine;
6825 if (LinePixelsRead >= Header.Width) then begin
6826 LinePixelsRead := 0;
6827 inc(Counter.Y.low, Counter.Y.dir); //next line index
6828 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6829 if (Counter.X.dir < 0) then //if x flipped then
6830 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6834 /////////////////////////////////////////////////////////////////
6837 CacheSize, CachePos: Integer;
6838 procedure CachedRead(out Buffer; Count: Integer);
6842 if (CachePos + Count > CacheSize) then begin
6843 //if buffer overflow save non read bytes
6845 if (CacheSize - CachePos > 0) then begin
6846 BytesRead := CacheSize - CachePos;
6847 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
6848 inc(CachePos, BytesRead);
6851 //load cache from file
6852 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
6853 aStream.Read(Cache^, CacheSize);
6856 //read rest of requested bytes
6857 if (Count - BytesRead > 0) then begin
6858 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
6859 inc(CachePos, Count - BytesRead);
6862 //if no buffer overflow just read the data
6863 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
6864 inc(CachePos, Count);
6868 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
6873 inc(aBuffer, Counter.X.dir);
6876 PWord(aBuffer)^ := PWord(aData)^;
6877 inc(aBuffer, 2 * Counter.X.dir);
6880 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
6881 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
6882 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
6883 inc(aBuffer, 3 * Counter.X.dir);
6886 PCardinal(aBuffer)^ := PCardinal(aData)^;
6887 inc(aBuffer, 4 * Counter.X.dir);
6893 TotalPixelsToRead, TotalPixelsRead: Integer;
6895 buf: array [0..3] of Byte; //1 pixel is max 32bit long
6896 PixelRepeat: Boolean;
6897 PixelsToRead, PixelCount: Integer;
6902 TotalPixelsToRead := Header.Width * Header.Height;
6903 TotalPixelsRead := 0;
6904 LinePixelsRead := 0;
6906 GetMem(Cache, CACHE_SIZE);
6908 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6909 if (Counter.X.dir < 0) then //if x flipped then
6910 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6914 CachedRead(Temp, 1);
6915 PixelRepeat := (Temp and $80) > 0;
6916 PixelsToRead := (Temp and $7F) + 1;
6917 inc(TotalPixelsRead, PixelsToRead);
6920 CachedRead(buf[0], PixelSize);
6921 while (PixelsToRead > 0) do begin
6923 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
6924 while (PixelCount > 0) do begin
6925 if not PixelRepeat then
6926 CachedRead(buf[0], PixelSize);
6927 PixelToBuffer(@buf[0], TmpData);
6928 inc(LinePixelsRead);
6933 until (TotalPixelsRead >= TotalPixelsToRead);
6939 function IsGrayFormat: Boolean;
6941 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
6947 // reading header to test file and set cursor back to begin
6948 StartPosition := aStream.Position;
6949 aStream.Read(Header{%H-}, SizeOf(Header));
6951 // no colormapped files
6952 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
6953 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
6956 if Header.ImageID <> 0 then // skip image ID
6957 aStream.Position := aStream.Position + Header.ImageID;
6960 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
6961 0: tgaFormat := tfLuminance8;
6962 8: tgaFormat := tfAlpha8;
6965 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
6966 0: tgaFormat := tfLuminance16;
6967 8: tgaFormat := tfLuminance8Alpha8;
6968 end else case (Header.ImageDesc and $F) of
6969 0: tgaFormat := tfBGR5;
6970 1: tgaFormat := tfBGR5A1;
6971 4: tgaFormat := tfBGRA4;
6974 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6975 0: tgaFormat := tfBGR8;
6978 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6979 2: tgaFormat := tfBGR10A2;
6980 8: tgaFormat := tfBGRA8;
6984 if (tgaFormat = tfEmpty) then
6985 raise EglBitmapException.Create('LoadTga - unsupported format');
6987 FormatDesc := TFormatDescriptor.Get(tgaFormat);
6988 PixelSize := FormatDesc.GetSize(1, 1);
6989 LineSize := FormatDesc.GetSize(Header.Width, 1);
6991 GetMem(ImageData, LineSize * Header.Height);
6994 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
6995 Counter.X.low := Header.Height-1;;
6996 Counter.X.high := 0;
6997 Counter.X.dir := -1;
7000 Counter.X.high := Header.Height-1;
7005 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7007 Counter.Y.high := Header.Height-1;
7010 Counter.Y.low := Header.Height-1;;
7011 Counter.Y.high := 0;
7012 Counter.Y.dir := -1;
7016 case Header.ImageType of
7017 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7019 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7023 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height);
7030 aStream.Position := StartPosition;
7033 else aStream.Position := StartPosition;
7036 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7037 procedure TglBitmap.SaveTGA(const aStream: TStream);
7040 LineSize, Size, x, y: Integer;
7041 Pixel: TglBitmapPixelData;
7042 LineBuf, SourceData, DestData: PByte;
7043 SourceMD, DestMD: Pointer;
7044 FormatDesc: TFormatDescriptor;
7045 Converter: TFormatDescriptor;
7047 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7048 raise EglBitmapUnsupportedFormat.Create(Format);
7051 FillChar(Header{%H-}, SizeOf(Header), 0);
7054 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7055 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7056 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7058 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7061 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7063 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7064 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7066 else if (Format in [tfBGR8, tfRGB8]) then
7074 Header.ImageDesc := 1 and $F;
7075 tfRGB10A2, tfBGR10A2:
7076 Header.ImageDesc := 2 and $F;
7078 Header.ImageDesc := 4 and $F;
7079 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7080 Header.ImageDesc := 8 and $F;
7083 Header.Width := Width;
7084 Header.Height := Height;
7085 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7086 aStream.Write(Header, SizeOf(Header));
7088 // convert RGB(A) to BGR(A)
7090 FormatDesc := TFormatDescriptor.Get(Format);
7091 Size := FormatDesc.GetSize(Dimension);
7092 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7093 if (FormatDesc.RGBInverted = tfEmpty) then
7094 raise EglBitmapException.Create('inverted RGB format is empty');
7095 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7096 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7097 (Converter.PixelSize <> FormatDesc.PixelSize) then
7098 raise EglBitmapException.Create('invalid inverted RGB format');
7101 if Assigned(Converter) then begin
7102 LineSize := FormatDesc.GetSize(Width, 1);
7103 LineBuf := GetMem(LineSize);
7104 SourceMD := FormatDesc.CreateMappingData;
7105 DestMD := Converter.CreateMappingData;
7108 for y := 0 to Height-1 do begin
7109 DestData := LineBuf;
7110 for x := 0 to Width-1 do begin
7111 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7112 Converter.Map(Pixel, DestData, DestMD);
7114 aStream.Write(LineBuf^, LineSize);
7118 FormatDesc.FreeMappingData(SourceMD);
7119 FormatDesc.FreeMappingData(DestMD);
7122 aStream.Write(Data^, Size);
7125 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7126 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7127 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7129 DDS_MAGIC: Cardinal = $20534444;
7131 // DDS_header.dwFlags
7132 DDSD_CAPS = $00000001;
7133 DDSD_HEIGHT = $00000002;
7134 DDSD_WIDTH = $00000004;
7135 DDSD_PIXELFORMAT = $00001000;
7137 // DDS_header.sPixelFormat.dwFlags
7138 DDPF_ALPHAPIXELS = $00000001;
7139 DDPF_ALPHA = $00000002;
7140 DDPF_FOURCC = $00000004;
7141 DDPF_RGB = $00000040;
7142 DDPF_LUMINANCE = $00020000;
7144 // DDS_header.sCaps.dwCaps1
7145 DDSCAPS_TEXTURE = $00001000;
7147 // DDS_header.sCaps.dwCaps2
7148 DDSCAPS2_CUBEMAP = $00000200;
7150 D3DFMT_DXT1 = $31545844;
7151 D3DFMT_DXT3 = $33545844;
7152 D3DFMT_DXT5 = $35545844;
7155 TDDSPixelFormat = packed record
7159 dwRGBBitCount: Cardinal;
7160 dwRBitMask: Cardinal;
7161 dwGBitMask: Cardinal;
7162 dwBBitMask: Cardinal;
7163 dwABitMask: Cardinal;
7166 TDDSCaps = packed record
7170 dwReserved: Cardinal;
7173 TDDSHeader = packed record
7178 dwPitchOrLinearSize: Cardinal;
7180 dwMipMapCount: Cardinal;
7181 dwReserved: array[0..10] of Cardinal;
7182 PixelFormat: TDDSPixelFormat;
7184 dwReserved2: Cardinal;
7187 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7188 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7191 Converter: TbmpBitfieldFormat;
7193 function GetDDSFormat: TglBitmapFormat;
7195 fd: TFormatDescriptor;
7197 Range: TglBitmapColorRec;
7201 with Header.PixelFormat do begin
7203 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7204 case Header.PixelFormat.dwFourCC of
7205 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7206 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7207 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7209 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7211 //find matching format
7212 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7213 fd := TFormatDescriptor.Get(result);
7214 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7215 (8 * fd.PixelSize = dwRGBBitCount) then
7219 //find format with same Range
7220 Range.r := dwRBitMask;
7221 Range.g := dwGBitMask;
7222 Range.b := dwBBitMask;
7223 Range.a := dwABitMask;
7224 for i := 0 to 3 do begin
7225 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7226 Range.arr[i] := Range.arr[i] shr 1;
7228 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7229 fd := TFormatDescriptor.Get(result);
7232 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7240 //no format with same range found -> use default
7241 if (result = tfEmpty) then begin
7242 if (dwABitMask > 0) then
7248 Converter := TbmpBitfieldFormat.Create;
7249 Converter.RedMask := dwRBitMask;
7250 Converter.GreenMask := dwGBitMask;
7251 Converter.BlueMask := dwBBitMask;
7252 Converter.AlphaMask := dwABitMask;
7253 Converter.PixelSize := dwRGBBitCount / 8;
7260 x, y, LineSize, RowSize, Magic: Cardinal;
7261 NewImage, TmpData, RowData, SrcData: System.PByte;
7262 SourceMD, DestMD: Pointer;
7263 Pixel: TglBitmapPixelData;
7264 ddsFormat: TglBitmapFormat;
7265 FormatDesc: TFormatDescriptor;
7270 StreamPos := aStream.Position;
7273 aStream.Read(Magic{%H-}, sizeof(Magic));
7274 if (Magic <> DDS_MAGIC) then begin
7275 aStream.Position := StreamPos;
7280 aStream.Read(Header{%H-}, sizeof(Header));
7281 if (Header.dwSize <> SizeOf(Header)) or
7282 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7283 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7285 aStream.Position := StreamPos;
7289 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7290 raise EglBitmapException.Create('LoadDDS - CubeMaps are not supported');
7292 ddsFormat := GetDDSFormat;
7294 if (ddsFormat = tfEmpty) then
7295 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7297 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7298 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7299 GetMem(NewImage, Header.dwHeight * LineSize);
7301 TmpData := NewImage;
7304 if Assigned(Converter) then begin
7305 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7306 GetMem(RowData, RowSize);
7307 SourceMD := Converter.CreateMappingData;
7308 DestMD := FormatDesc.CreateMappingData;
7310 for y := 0 to Header.dwHeight-1 do begin
7311 TmpData := NewImage + y * LineSize;
7313 aStream.Read(SrcData^, RowSize);
7314 for x := 0 to Header.dwWidth-1 do begin
7315 Converter.Unmap(SrcData, Pixel, SourceMD);
7316 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7317 FormatDesc.Map(Pixel, TmpData, DestMD);
7321 Converter.FreeMappingData(SourceMD);
7322 FormatDesc.FreeMappingData(DestMD);
7328 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7329 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7330 for Y := 0 to Header.dwHeight-1 do begin
7331 aStream.Read(TmpData^, RowSize);
7332 Inc(TmpData, LineSize);
7337 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7338 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7339 for Y := 0 to Header.dwHeight-1 do begin
7340 aStream.Read(TmpData^, RowSize);
7341 Inc(TmpData, LineSize);
7344 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7346 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
7353 FreeAndNil(Converter);
7357 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7358 procedure TglBitmap.SaveDDS(const aStream: TStream);
7361 FormatDesc: TFormatDescriptor;
7363 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7364 raise EglBitmapUnsupportedFormat.Create(Format);
7366 FormatDesc := TFormatDescriptor.Get(Format);
7369 FillChar(Header{%H-}, SizeOf(Header), 0);
7370 Header.dwSize := SizeOf(Header);
7371 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7373 Header.dwWidth := Max(1, Width);
7374 Header.dwHeight := Max(1, Height);
7377 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7380 Header.PixelFormat.dwSize := sizeof(Header);
7381 if (FormatDesc.IsCompressed) then begin
7382 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7384 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7385 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7386 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7388 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7389 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7390 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7391 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7392 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7393 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7394 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7395 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7396 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7398 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7399 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7400 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7401 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7402 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7403 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7406 if (FormatDesc.HasAlpha) then
7407 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7409 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7410 aStream.Write(Header, SizeOf(Header));
7411 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7414 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7415 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7416 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7417 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7419 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7420 result := fLines[aIndex]
7425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7426 procedure TglBitmap2D.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
7427 const aWidth: Integer; const aHeight: Integer);
7429 Idx, LineWidth: Integer;
7431 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7433 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7435 fGetPixelFunc := GetPixel2DUnmap;
7436 fSetPixelFunc := SetPixel2DUnmap;
7439 if Assigned(Data) then begin
7440 SetLength(fLines, GetHeight);
7441 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7443 for Idx := 0 to GetHeight -1 do begin
7444 fLines[Idx] := Data;
7445 Inc(fLines[Idx], Idx * LineWidth);
7448 else SetLength(fLines, 0);
7450 SetLength(fLines, 0);
7452 fSetPixelFunc := nil;
7456 fGetPixelFunc := GetPixel2DDXT1;
7458 fGetPixelFunc := GetPixel2DDXT3;
7460 fGetPixelFunc := GetPixel2DDXT5;
7462 fGetPixelFunc := nil;
7468 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7469 procedure TglBitmap2D.UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
7471 FormatDesc: TFormatDescriptor;
7473 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7475 FormatDesc := TFormatDescriptor.Get(Format);
7476 if FormatDesc.IsCompressed then begin
7477 glCompressedTexImage2D(Target, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7478 end else if aBuildWithGlu then begin
7479 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7480 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7482 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7483 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7487 if (FreeDataAfterGenTexture) then
7491 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7492 procedure TglBitmap2D.AfterConstruction;
7495 Target := GL_TEXTURE_2D;
7498 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7499 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7502 Size, w, h: Integer;
7503 FormatDesc: TFormatDescriptor;
7505 FormatDesc := TFormatDescriptor.Get(Format);
7506 if FormatDesc.IsCompressed then
7507 raise EglBitmapUnsupportedFormat.Create(Format);
7509 w := aRight - aLeft;
7510 h := aBottom - aTop;
7511 Size := FormatDesc.GetSize(w, h);
7514 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7515 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7516 SetDataPointer(Temp, Format, w, h);
7524 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7525 procedure TglBitmap2D.GetDataFromTexture;
7528 TempWidth, TempHeight: Integer;
7529 TempIntFormat: Cardinal;
7530 IntFormat, f: TglBitmapFormat;
7531 FormatDesc: TFormatDescriptor;
7536 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7537 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7538 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7540 IntFormat := tfEmpty;
7541 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
7542 FormatDesc := TFormatDescriptor.Get(f);
7543 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
7544 IntFormat := FormatDesc.Format;
7549 // Getting data from OpenGL
7550 FormatDesc := TFormatDescriptor.Get(IntFormat);
7551 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
7553 if FormatDesc.IsCompressed then
7554 glGetCompressedTexImage(Target, 0, Temp)
7556 glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
7557 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
7564 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7565 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
7567 BuildWithGlu, PotTex, TexRec: Boolean;
7570 if Assigned(Data) then begin
7571 // Check Texture Size
7572 if (aTestTextureSize) then begin
7573 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7575 if ((Height > TexSize) or (Width > TexSize)) then
7576 raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7578 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
7579 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
7581 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7582 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7586 SetupParameters(BuildWithGlu);
7587 UploadData(Target, BuildWithGlu);
7588 glAreTexturesResident(1, @fID, @fIsResident);
7592 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7593 function TglBitmap2D.FlipHorz: Boolean;
7596 TempDestData, DestData, SourceData: PByte;
7599 result := inherited FlipHorz;
7600 if Assigned(Data) then begin
7602 ImgSize := Height * fRowSize;
7603 GetMem(DestData, ImgSize);
7605 TempDestData := DestData;
7606 Dec(TempDestData, fRowSize + fPixelSize);
7607 for Row := 0 to Height -1 do begin
7608 Inc(TempDestData, fRowSize * 2);
7609 for Col := 0 to Width -1 do begin
7610 Move(SourceData^, TempDestData^, fPixelSize);
7611 Inc(SourceData, fPixelSize);
7612 Dec(TempDestData, fPixelSize);
7615 SetDataPointer(DestData, Format);
7624 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7625 function TglBitmap2D.FlipVert: Boolean;
7628 TempDestData, DestData, SourceData: PByte;
7630 result := inherited FlipVert;
7631 if Assigned(Data) then begin
7633 GetMem(DestData, Height * fRowSize);
7635 TempDestData := DestData;
7636 Inc(TempDestData, Width * (Height -1) * fPixelSize);
7637 for Row := 0 to Height -1 do begin
7638 Move(SourceData^, TempDestData^, fRowSize);
7639 Dec(TempDestData, fRowSize);
7640 Inc(SourceData, fRowSize);
7642 SetDataPointer(DestData, Format);
7651 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7652 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7653 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7655 TMatrixItem = record
7660 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
7661 TglBitmapToNormalMapRec = Record
7663 Heights: array of Single;
7664 MatrixU : array of TMatrixItem;
7665 MatrixV : array of TMatrixItem;
7669 ONE_OVER_255 = 1 / 255;
7671 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7672 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
7676 with FuncRec do begin
7678 Source.Data.r * LUMINANCE_WEIGHT_R +
7679 Source.Data.g * LUMINANCE_WEIGHT_G +
7680 Source.Data.b * LUMINANCE_WEIGHT_B;
7681 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
7685 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7686 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
7689 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
7692 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7693 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
7695 TVec = Array[0..2] of Single;
7702 function GetHeight(X, Y: Integer): Single;
7704 with FuncRec do begin
7705 X := Max(0, Min(Size.X -1, X));
7706 Y := Max(0, Min(Size.Y -1, Y));
7707 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
7712 with FuncRec do begin
7713 with PglBitmapToNormalMapRec(Args)^ do begin
7715 for Idx := Low(MatrixU) to High(MatrixU) do
7716 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
7719 for Idx := Low(MatrixU) to High(MatrixU) do
7720 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
7722 Vec[0] := -du * Scale;
7723 Vec[1] := -dv * Scale;
7728 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
7729 if Len <> 0 then begin
7730 Vec[0] := Vec[0] * Len;
7731 Vec[1] := Vec[1] * Len;
7732 Vec[2] := Vec[2] * Len;
7736 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
7737 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
7738 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
7742 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7743 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
7745 Rec: TglBitmapToNormalMapRec;
7747 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
7749 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
7750 Matrix[Index].X := X;
7751 Matrix[Index].Y := Y;
7752 Matrix[Index].W := W;
7757 if TFormatDescriptor.Get(Format).IsCompressed then
7758 raise EglBitmapUnsupportedFormat.Create(Format);
7760 if aScale > 100 then
7762 else if aScale < -100 then
7765 Rec.Scale := aScale;
7767 SetLength(Rec.Heights, Width * Height);
7771 SetLength(Rec.MatrixU, 2);
7772 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
7773 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
7775 SetLength(Rec.MatrixV, 2);
7776 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
7777 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
7781 SetLength(Rec.MatrixU, 6);
7782 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
7783 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
7784 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
7785 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
7786 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
7787 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
7789 SetLength(Rec.MatrixV, 6);
7790 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
7791 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
7792 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
7793 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
7794 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
7795 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
7799 SetLength(Rec.MatrixU, 6);
7800 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
7801 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
7802 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
7803 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
7804 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
7805 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
7807 SetLength(Rec.MatrixV, 6);
7808 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
7809 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
7810 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
7811 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
7812 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
7813 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
7817 SetLength(Rec.MatrixU, 20);
7818 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
7819 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
7820 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
7821 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
7822 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
7823 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
7824 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
7825 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
7826 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
7827 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
7828 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
7829 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
7830 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
7831 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
7832 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
7833 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
7834 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
7835 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
7836 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
7837 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
7839 SetLength(Rec.MatrixV, 20);
7840 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
7841 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
7842 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
7843 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
7844 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
7845 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
7846 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
7847 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
7848 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
7849 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
7850 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
7851 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
7852 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
7853 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
7854 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
7855 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
7856 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
7857 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
7858 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
7859 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
7864 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
7865 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
7867 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
7868 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
7870 SetLength(Rec.Heights, 0);
7883 procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
7888 if Height > 1 then begin
7889 // extract first line of the data
7890 Size := FormatGetImageSize(glBitmapPosition(Width), Format);
7891 GetMem(pTemp, Size);
7893 Move(Data^, pTemp^, Size);
7900 inherited SetDataPointer(pTemp, Format, Width);
7902 if FormatIsUncompressed(Format) then begin
7903 fUnmapFunc := FormatGetUnMapFunc(Format);
7904 fGetPixelFunc := GetPixel1DUnmap;
7909 procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
7914 Inc(pTemp, Pos.X * fPixelSize);
7916 fUnmapFunc(pTemp, Pixel);
7920 function TglBitmap1D.FlipHorz: Boolean;
7923 pTempDest, pDest, pSource: pByte;
7925 result := inherited FlipHorz;
7927 if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin
7930 GetMem(pDest, fRowSize);
7934 Inc(pTempDest, fRowSize);
7935 for Col := 0 to Width -1 do begin
7936 Move(pSource^, pTempDest^, fPixelSize);
7938 Inc(pSource, fPixelSize);
7939 Dec(pTempDest, fPixelSize);
7942 SetDataPointer(pDest, InternalFormat);
7952 procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
7955 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
7956 glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data)
7960 if BuildWithGlu then
7961 gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data)
7963 glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data);
7966 if (FreeDataAfterGenTexture) then
7971 procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean);
7973 BuildWithGlu, TexRec: Boolean;
7974 glFormat, glInternalFormat, glType: Cardinal;
7977 if Assigned(Data) then begin
7978 // Check Texture Size
7979 if (TestTextureSize) then begin
7980 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7982 if (Width > TexSize) then
7983 raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7985 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7986 (Target = GL_TEXTURE_RECTANGLE_ARB);
7988 if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7989 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7994 SetupParameters(BuildWithGlu);
7995 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
7997 UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
8000 glAreTexturesResident(1, @fID, @fIsResident);
8005 procedure TglBitmap1D.AfterConstruction;
8009 Target := GL_TEXTURE_1D;
8013 { TglBitmapCubeMap }
8015 procedure TglBitmapCubeMap.AfterConstruction;
8019 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8020 raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8022 SetWrap; // set all to GL_CLAMP_TO_EDGE
8023 Target := GL_TEXTURE_CUBE_MAP;
8024 fGenMode := GL_REFLECTION_MAP;
8028 procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean);
8030 inherited Bind (EnableTextureUnit);
8032 if EnableTexCoordsGen then begin
8033 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8034 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8035 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8036 glEnable(GL_TEXTURE_GEN_S);
8037 glEnable(GL_TEXTURE_GEN_T);
8038 glEnable(GL_TEXTURE_GEN_R);
8043 procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean);
8045 glFormat, glInternalFormat, glType: Cardinal;
8046 BuildWithGlu: Boolean;
8049 // Check Texture Size
8050 if (TestTextureSize) then begin
8051 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8053 if ((Height > TexSize) or (Width > TexSize)) then
8054 raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8056 if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8057 raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8061 if ID = 0 then begin
8063 SetupParameters(BuildWithGlu);
8066 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
8068 UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu);
8072 procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean);
8074 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8078 procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen,
8079 DisableTextureUnit: Boolean);
8081 inherited Unbind (DisableTextureUnit);
8083 if DisableTexCoordsGen then begin
8084 glDisable(GL_TEXTURE_GEN_S);
8085 glDisable(GL_TEXTURE_GEN_T);
8086 glDisable(GL_TEXTURE_GEN_R);
8091 { TglBitmapNormalMap }
8094 TVec = Array[0..2] of Single;
8095 TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8097 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8098 TglBitmapNormalMapRec = record
8100 Func: TglBitmapNormalMapGetVectorFunc;
8104 procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8107 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8108 Vec[2] := - (Position.X + 0.5 - HalfSize);
8112 procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8114 Vec[0] := - HalfSize;
8115 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8116 Vec[2] := Position.X + 0.5 - HalfSize;
8120 procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8122 Vec[0] := Position.X + 0.5 - HalfSize;
8124 Vec[2] := Position.Y + 0.5 - HalfSize;
8128 procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8130 Vec[0] := Position.X + 0.5 - HalfSize;
8131 Vec[1] := - HalfSize;
8132 Vec[2] := - (Position.Y + 0.5 - HalfSize);
8136 procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8138 Vec[0] := Position.X + 0.5 - HalfSize;
8139 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8144 procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8146 Vec[0] := - (Position.X + 0.5 - HalfSize);
8147 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8148 Vec[2] := - HalfSize;
8152 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8157 with FuncRec do begin
8158 with PglBitmapNormalMapRec (CustomData)^ do begin
8159 Func(Vec, Position, HalfSize);
8162 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8163 if Len <> 0 then begin
8164 Vec[0] := Vec[0] * Len;
8165 Vec[1] := Vec[1] * Len;
8166 Vec[2] := Vec[2] * Len;
8169 // Scale Vector and AddVectro
8170 Vec[0] := Vec[0] * 0.5 + 0.5;
8171 Vec[1] := Vec[1] * 0.5 + 0.5;
8172 Vec[2] := Vec[2] * 0.5 + 0.5;
8176 Dest.Red := Round(Vec[0] * 255);
8177 Dest.Green := Round(Vec[1] * 255);
8178 Dest.Blue := Round(Vec[2] * 255);
8183 procedure TglBitmapNormalMap.AfterConstruction;
8187 fGenMode := GL_NORMAL_MAP;
8191 procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer;
8192 TestTextureSize: Boolean);
8194 Rec: TglBitmapNormalMapRec;
8195 SizeRec: TglBitmapPixelPosition;
8197 Rec.HalfSize := Size div 2;
8199 FreeDataAfterGenTexture := false;
8201 SizeRec.Fields := [ffX, ffY];
8206 Rec.Func := glBitmapNormalMapPosX;
8207 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8208 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize);
8211 Rec.Func := glBitmapNormalMapNegX;
8212 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8213 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize);
8216 Rec.Func := glBitmapNormalMapPosY;
8217 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8218 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize);
8221 Rec.Func := glBitmapNormalMapNegY;
8222 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8223 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize);
8226 Rec.Func := glBitmapNormalMapPosZ;
8227 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8228 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize);
8231 Rec.Func := glBitmapNormalMapNegZ;
8232 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8233 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize);
8238 glBitmapSetDefaultFormat(tfEmpty);
8239 glBitmapSetDefaultMipmap(mmMipmap);
8240 glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8241 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8243 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8244 glBitmapSetDefaultDeleteTextureOnFree (true);
8246 TFormatDescriptor.Init;
8248 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8249 OpenGLInitialized := false;
8250 InitOpenGLCS := TCriticalSection.Create;
8254 TFormatDescriptor.Finalize;
8256 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8257 FreeAndNil(InitOpenGLCS);