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('unsupported format: ' + 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;
5629 Row, Col, PixSize, LineSize: Integer;
5630 NewImage, pSource, pDest, pAlpha: pByte;
5631 PngFormat: TglBitmapFormat;
5632 FormatDesc: TFormatDescriptor;
5635 PngHeader: String[8] = #137#80#78#71#13#10#26#10;
5640 StreamPos := aStream.Position;
5641 aStream.Read(Header[0], SizeOf(Header));
5642 aStream.Position := StreamPos;
5644 {Test if the header matches}
5645 if Header = PngHeader then begin
5646 Png := TPNGObject.Create;
5648 Png.LoadFromStream(aStream);
5650 case Png.Header.ColorType of
5652 PngFormat := tfLuminance8;
5653 COLOR_GRAYSCALEALPHA:
5654 PngFormat := tfLuminance8Alpha8;
5656 PngFormat := tfBGR8;
5658 PngFormat := tfBGRA8;
5660 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5663 FormatDesc := TFormatDescriptor.Get(PngFormat);
5664 PixSize := Round(FormatDesc.PixelSize);
5665 LineSize := FormatDesc.GetSize(Png.Header.Width, 1);
5667 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5671 case Png.Header.ColorType of
5672 COLOR_RGB, COLOR_GRAYSCALE:
5674 for Row := 0 to Png.Height -1 do begin
5675 Move (Png.Scanline[Row]^, pDest^, LineSize);
5676 Inc(pDest, LineSize);
5679 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5681 PixSize := PixSize -1;
5683 for Row := 0 to Png.Height -1 do begin
5684 pSource := Png.Scanline[Row];
5685 pAlpha := pByte(Png.AlphaScanline[Row]);
5687 for Col := 0 to Png.Width -1 do begin
5688 Move (pSource^, pDest^, PixSize);
5689 Inc(pSource, PixSize);
5690 Inc(pDest, PixSize);
5699 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5702 SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height);
5717 {$IFDEF GLB_SUPPORT_PNG_WRITE}
5718 {$IFDEF GLB_LIB_PNG}
5719 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5720 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5722 TStream(png_get_io_ptr(png)).Write(buffer^, size);
5726 {$IF DEFINED(GLB_LIB_PNG)}
5727 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5728 procedure TglBitmap.SavePNG(const aStream: TStream);
5731 png_info: png_infop;
5732 png_rows: array of pByte;
5736 FormatDesc: TFormatDescriptor;
5738 if not (ftPNG in FormatGetSupportedFiles(Format)) then
5739 raise EglBitmapUnsupportedFormat.Create(Format);
5741 if not init_libPNG then
5742 raise Exception.Create('unable to initialize libPNG.');
5746 tfAlpha8, tfLuminance8:
5747 ColorType := PNG_COLOR_TYPE_GRAY;
5749 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
5751 ColorType := PNG_COLOR_TYPE_RGB;
5753 ColorType := PNG_COLOR_TYPE_RGBA;
5755 raise EglBitmapUnsupportedFormat.Create(Format);
5758 FormatDesc := TFormatDescriptor.Get(Format);
5759 LineSize := FormatDesc.GetSize(Width, 1);
5761 // creating array for scanline
5762 SetLength(png_rows, Height);
5764 for Row := 0 to Height - 1 do begin
5765 png_rows[Row] := Data;
5766 Inc(png_rows[Row], Row * LineSize)
5770 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5772 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
5775 png_info := png_create_info_struct(png);
5776 if png_info = nil then begin
5777 png_destroy_write_struct(@png, nil);
5778 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
5781 // set read callback
5782 png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil);
5785 png_set_compression_level(png, 6);
5787 if Format in [tfBGR8, tfBGRA8] then
5790 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
5791 png_write_info(png, png_info);
5792 png_write_image(png, @png_rows[0]);
5793 png_write_end(png, png_info);
5794 png_destroy_write_struct(@png, @png_info);
5796 SetLength(png_rows, 0);
5803 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5804 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5805 procedure TglBitmap.SavePNG(const aStream: TStream);
5809 pSource, pDest: pByte;
5810 X, Y, PixSize: Integer;
5811 ColorType: Cardinal;
5817 if not (ftPNG in FormatGetSupportedFiles (Format)) then
5818 raise EglBitmapUnsupportedFormat.Create(Format);
5821 tfAlpha8, tfLuminance8: begin
5822 ColorType := COLOR_GRAYSCALE;
5826 tfLuminance8Alpha8: begin
5827 ColorType := COLOR_GRAYSCALEALPHA;
5831 tfBGR8, tfRGB8: begin
5832 ColorType := COLOR_RGB;
5836 tfBGRA8, tfRGBA8: begin
5837 ColorType := COLOR_RGBALPHA;
5842 raise EglBitmapUnsupportedFormat.Create(Format);
5845 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
5849 for Y := 0 to Height -1 do begin
5850 pDest := png.ScanLine[Y];
5851 for X := 0 to Width -1 do begin
5852 Move(pSource^, pDest^, PixSize);
5853 Inc(pDest, PixSize);
5854 Inc(pSource, PixSize);
5856 png.AlphaScanline[Y]^[X] := pSource^;
5861 // convert RGB line to BGR
5862 if Format in [tfRGB8, tfRGBA8] then begin
5863 pTemp := png.ScanLine[Y];
5864 for X := 0 to Width -1 do begin
5865 Temp := pByteArray(pTemp)^[0];
5866 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
5867 pByteArray(pTemp)^[2] := Temp;
5874 Png.CompressionLevel := 6;
5875 Png.SaveToStream(aStream);
5883 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5884 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5885 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5886 {$IFDEF GLB_LIB_JPEG}
5888 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
5889 glBitmap_libJPEG_source_mgr = record
5890 pub: jpeg_source_mgr;
5893 SrcBuffer: array [1..4096] of byte;
5896 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
5897 glBitmap_libJPEG_dest_mgr = record
5898 pub: jpeg_destination_mgr;
5900 DestStream: TStream;
5901 DestBuffer: array [1..4096] of byte;
5904 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
5910 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
5916 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
5921 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
5927 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
5933 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5934 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
5936 src: glBitmap_libJPEG_source_mgr_ptr;
5939 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5941 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
5942 if (bytes <= 0) then begin
5943 src^.SrcBuffer[1] := $FF;
5944 src^.SrcBuffer[2] := JPEG_EOI;
5948 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
5949 src^.pub.bytes_in_buffer := bytes;
5954 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5955 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
5957 src: glBitmap_libJPEG_source_mgr_ptr;
5959 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5961 if num_bytes > 0 then begin
5962 // wanted byte isn't in buffer so set stream position and read buffer
5963 if num_bytes > src^.pub.bytes_in_buffer then begin
5964 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
5965 src^.pub.fill_input_buffer(cinfo);
5967 // wanted byte is in buffer so only skip
5968 inc(src^.pub.next_input_byte, num_bytes);
5969 dec(src^.pub.bytes_in_buffer, num_bytes);
5974 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5975 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
5977 dest: glBitmap_libJPEG_dest_mgr_ptr;
5979 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5981 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
5982 // write complete buffer
5983 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
5986 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
5987 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
5993 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5994 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
5997 dest: glBitmap_libJPEG_dest_mgr_ptr;
5999 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
6001 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
6002 // check for endblock
6003 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
6005 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
6010 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
6015 {$IFDEF GLB_SUPPORT_JPEG_READ}
6016 {$IF DEFINED(GLB_SDL_IMAGE)}
6017 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6018 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6020 Surface: PSDL_Surface;
6025 RWops := glBitmapCreateRWops(aStream);
6027 if IMG_isJPG(RWops) > 0 then begin
6028 Surface := IMG_LoadJPG_RW(RWops);
6030 AssignFromSurface(Surface);
6033 SDL_FreeSurface(Surface);
6041 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
6042 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6043 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6046 Temp: array[0..1]of Byte;
6048 jpeg: jpeg_decompress_struct;
6049 jpeg_err: jpeg_error_mgr;
6051 IntFormat: TglBitmapFormat;
6053 TempHeight, TempWidth: Integer;
6058 FormatDesc: TFormatDescriptor;
6062 if not init_libJPEG then
6063 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
6066 // reading first two bytes to test file and set cursor back to begin
6067 StreamPos := aStream.Position;
6068 aStream.Read({%H-}Temp[0], 2);
6069 aStream.Position := StreamPos;
6071 // if Bitmap then read file.
6072 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6073 FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
6074 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6077 jpeg.err := jpeg_std_error(@jpeg_err);
6078 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6079 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6081 // decompression struct
6082 jpeg_create_decompress(@jpeg);
6084 // allocation space for streaming methods
6085 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
6087 // seeting up custom functions
6088 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
6089 pub.init_source := glBitmap_libJPEG_init_source;
6090 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
6091 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
6092 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
6093 pub.term_source := glBitmap_libJPEG_term_source;
6095 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
6096 pub.next_input_byte := nil; // until buffer loaded
6098 SrcStream := aStream;
6101 // set global decoding state
6102 jpeg.global_state := DSTATE_START;
6104 // read header of jpeg
6105 jpeg_read_header(@jpeg, false);
6107 // setting output parameter
6108 case jpeg.jpeg_color_space of
6111 jpeg.out_color_space := JCS_GRAYSCALE;
6112 IntFormat := tfLuminance8;
6115 jpeg.out_color_space := JCS_RGB;
6116 IntFormat := tfRGB8;
6120 jpeg_start_decompress(@jpeg);
6122 TempHeight := jpeg.output_height;
6123 TempWidth := jpeg.output_width;
6125 FormatDesc := TFormatDescriptor.Get(IntFormat);
6127 // creating new image
6128 GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
6132 for Row := 0 to TempHeight -1 do begin
6133 jpeg_read_scanlines(@jpeg, @pTemp, 1);
6134 Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
6137 // finish decompression
6138 jpeg_finish_decompress(@jpeg);
6140 // destroy decompression
6141 jpeg_destroy_decompress(@jpeg);
6143 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight);
6156 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6157 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6158 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
6163 Temp: array[0..1]of Byte;
6167 // reading first two bytes to test file and set cursor back to begin
6168 StreamPos := Stream.Position;
6169 Stream.Read(Temp[0], 2);
6170 Stream.Position := StreamPos;
6172 // if Bitmap then read file.
6173 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
6174 bmp := TBitmap.Create;
6176 jpg := TJPEGImage.Create;
6178 jpg.LoadFromStream(Stream);
6180 result := AssignFromBitmap(bmp);
6192 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6193 {$IF DEFINED(GLB_LIB_JPEG)}
6194 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6195 procedure TglBitmap.SaveJPEG(const aStream: TStream);
6197 jpeg: jpeg_compress_struct;
6198 jpeg_err: jpeg_error_mgr;
6200 pTemp, pTemp2: pByte;
6202 procedure CopyRow(pDest, pSource: pByte);
6206 for X := 0 to Width - 1 do begin
6207 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6208 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6209 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6216 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6217 raise EglBitmapUnsupportedFormat.Create(Format);
6219 if not init_libJPEG then
6220 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6223 FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
6224 FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
6227 jpeg.err := jpeg_std_error(@jpeg_err);
6228 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6229 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6231 // compression struct
6232 jpeg_create_compress(@jpeg);
6234 // allocation space for streaming methods
6235 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6237 // seeting up custom functions
6238 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6239 pub.init_destination := glBitmap_libJPEG_init_destination;
6240 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6241 pub.term_destination := glBitmap_libJPEG_term_destination;
6243 pub.next_output_byte := @DestBuffer[1];
6244 pub.free_in_buffer := Length(DestBuffer);
6246 DestStream := aStream;
6249 // very important state
6250 jpeg.global_state := CSTATE_START;
6251 jpeg.image_width := Width;
6252 jpeg.image_height := Height;
6254 tfAlpha8, tfLuminance8: begin
6255 jpeg.input_components := 1;
6256 jpeg.in_color_space := JCS_GRAYSCALE;
6258 tfRGB8, tfBGR8: begin
6259 jpeg.input_components := 3;
6260 jpeg.in_color_space := JCS_RGB;
6264 jpeg_set_defaults(@jpeg);
6265 jpeg_set_quality(@jpeg, 95, true);
6266 jpeg_start_compress(@jpeg, true);
6269 if Format = tfBGR8 then
6270 GetMem(pTemp2, fRowSize)
6275 for Row := 0 to jpeg.image_height -1 do begin
6277 if Format = tfBGR8 then
6278 CopyRow(pTemp2, pTemp)
6283 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6284 inc(pTemp, fRowSize);
6288 if Format = tfBGR8 then
6291 jpeg_finish_compress(@jpeg);
6292 jpeg_destroy_compress(@jpeg);
6298 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6299 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6300 procedure TglBitmap.SaveJPEG(Stream: TStream);
6305 if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then
6306 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
6308 Bmp := TBitmap.Create;
6310 Jpg := TJPEGImage.Create;
6312 AssignToBitmap(Bmp);
6313 if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
6314 Jpg.Grayscale := true;
6315 Jpg.PixelFormat := jf8Bit;
6318 Jpg.SaveToStream(Stream);
6329 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6330 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6331 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6338 BMP_COMP_BITFIELDS = 3;
6341 TBMPHeader = packed record
6346 bfOffBits: Cardinal;
6349 TBMPInfo = packed record
6355 biCompression: Cardinal;
6356 biSizeImage: Cardinal;
6357 biXPelsPerMeter: Longint;
6358 biYPelsPerMeter: Longint;
6359 biClrUsed: Cardinal;
6360 biClrImportant: Cardinal;
6363 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6364 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6366 //////////////////////////////////////////////////////////////////////////////////////////////////
6367 function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat;
6370 aStream.Read(aInfo{%H-}, SizeOf(aInfo));
6371 FillChar(aMask{%H-}, SizeOf(aMask), 0);
6374 case aInfo.biCompression of
6376 BMP_COMP_RLE8: begin
6377 raise EglBitmapException.Create('RLE compression is not supported');
6379 BMP_COMP_BITFIELDS: begin
6380 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6381 aStream.Read(aMask.r, SizeOf(aMask.r));
6382 aStream.Read(aMask.g, SizeOf(aMask.g));
6383 aStream.Read(aMask.b, SizeOf(aMask.b));
6384 aStream.Read(aMask.a, SizeOf(aMask.a));
6386 raise EglBitmapException.Create('Bitfields are only supported for 16bit and 32bit formats');
6390 //get suitable format
6391 case aInfo.biBitCount of
6392 8: result := tfLuminance8;
6393 16: result := tfBGR5;
6394 24: result := tfBGR8;
6395 32: result := tfBGRA8;
6399 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6402 ColorTable: TbmpColorTable;
6405 if (aInfo.biBitCount >= 16) then
6407 aFormat := tfLuminance8;
6408 c := aInfo.biClrUsed;
6410 c := 1 shl aInfo.biBitCount;
6411 SetLength(ColorTable, c);
6412 for i := 0 to c-1 do begin
6413 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6414 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6418 result := TbmpColorTableFormat.Create;
6419 result.PixelSize := aInfo.biBitCount / 8;
6420 result.ColorTable := ColorTable;
6421 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6424 //////////////////////////////////////////////////////////////////////////////////////////////////
6425 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6426 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6428 TmpFormat: TglBitmapFormat;
6429 FormatDesc: TFormatDescriptor;
6432 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6433 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6434 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6435 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6436 aFormat := FormatDesc.Format;
6441 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6442 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6443 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6444 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6446 result := TbmpBitfieldFormat.Create;
6447 result.PixelSize := aInfo.biBitCount / 8;
6448 result.RedMask := aMask.r;
6449 result.GreenMask := aMask.g;
6450 result.BlueMask := aMask.b;
6451 result.AlphaMask := aMask.a;
6458 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6459 PaddingBuff: Cardinal;
6460 LineBuf, ImageData, TmpData: PByte;
6461 SourceMD, DestMD: Pointer;
6462 BmpFormat: TglBitmapFormat;
6465 Mask: TglBitmapColorRec;
6470 SpecialFormat: TFormatDescriptor;
6471 FormatDesc: TFormatDescriptor;
6473 //////////////////////////////////////////////////////////////////////////////////////////////////
6474 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6477 Pixel: TglBitmapPixelData;
6479 aStream.Read(aLineBuf^, rbLineSize);
6480 SpecialFormat.PreparePixel(Pixel);
6481 for i := 0 to Info.biWidth-1 do begin
6482 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6483 glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc);
6484 FormatDesc.Map(Pixel, aData, DestMD);
6490 BmpFormat := tfEmpty;
6491 SpecialFormat := nil;
6497 StartPos := aStream.Position;
6498 aStream.Read(Header{%H-}, SizeOf(Header));
6500 if Header.bfType = BMP_MAGIC then begin
6502 BmpFormat := ReadInfo(Info, Mask);
6503 SpecialFormat := ReadColorTable(BmpFormat, Info);
6504 if not Assigned(SpecialFormat) then
6505 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6506 aStream.Position := StartPos + Header.bfOffBits;
6508 if (BmpFormat <> tfEmpty) then begin
6509 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6510 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6511 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6512 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6515 DestMD := FormatDesc.CreateMappingData;
6516 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6517 GetMem(ImageData, ImageSize);
6518 if Assigned(SpecialFormat) then begin
6519 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6520 SourceMD := SpecialFormat.CreateMappingData;
6525 FillChar(ImageData^, ImageSize, $FF);
6526 TmpData := ImageData;
6527 if (Info.biHeight > 0) then
6528 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6529 for i := 0 to Abs(Info.biHeight)-1 do begin
6530 if Assigned(SpecialFormat) then
6531 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6533 aStream.Read(TmpData^, wbLineSize); //else only read data
6534 if (Info.biHeight > 0) then
6535 dec(TmpData, wbLineSize)
6537 inc(TmpData, wbLineSize);
6538 aStream.Read(PaddingBuff{%H-}, Padding);
6540 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight));
6543 if Assigned(LineBuf) then
6545 if Assigned(SourceMD) then
6546 SpecialFormat.FreeMappingData(SourceMD);
6547 FormatDesc.FreeMappingData(DestMD);
6554 raise EglBitmapException.Create('LoadBMP - No suitable format found');
6556 aStream.Position := StartPos;
6560 FreeAndNil(SpecialFormat);
6563 else aStream.Position := StartPos;
6566 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6567 procedure TglBitmap.SaveBMP(const aStream: TStream);
6571 Converter: TbmpColorTableFormat;
6572 FormatDesc: TFormatDescriptor;
6573 SourceFD, DestFD: Pointer;
6574 pData, srcData, dstData, ConvertBuffer: pByte;
6576 Pixel: TglBitmapPixelData;
6577 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer;
6578 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6580 PaddingBuff: Cardinal;
6582 function GetLineWidth : Integer;
6584 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6588 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6589 raise EglBitmapUnsupportedFormat.Create(Format);
6592 FormatDesc := TFormatDescriptor.Get(Format);
6593 ImageSize := FormatDesc.GetSize(Dimension);
6595 FillChar(Header{%H-}, SizeOf(Header), 0);
6596 Header.bfType := BMP_MAGIC;
6597 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6598 Header.bfReserved1 := 0;
6599 Header.bfReserved2 := 0;
6600 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6602 FillChar(Info{%H-}, SizeOf(Info), 0);
6603 Info.biSize := SizeOf(Info);
6604 Info.biWidth := Width;
6605 Info.biHeight := Height;
6607 Info.biCompression := BMP_COMP_RGB;
6608 Info.biSizeImage := ImageSize;
6613 Info.biBitCount := 4;
6614 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6615 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6616 Converter := TbmpColorTableFormat.Create;
6617 Converter.PixelSize := 0.5;
6618 Converter.Format := Format;
6619 Converter.Range := glBitmapColorRec($F, $F, $F, $0);
6620 Converter.CreateColorTable;
6623 tfR3G3B2, tfLuminance8: begin
6624 Info.biBitCount := 8;
6625 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6626 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6627 Converter := TbmpColorTableFormat.Create;
6628 Converter.PixelSize := 1;
6629 Converter.Format := Format;
6630 if (Format = tfR3G3B2) then begin
6631 Converter.Range := glBitmapColorRec($7, $7, $3, $0);
6632 Converter.Shift := glBitmapShiftRec(0, 3, 6, 0);
6634 Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0);
6635 Converter.CreateColorTable;
6638 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6639 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6640 Info.biBitCount := 16;
6641 Info.biCompression := BMP_COMP_BITFIELDS;
6644 tfBGR8, tfRGB8: begin
6645 Info.biBitCount := 24;
6648 tfRGB10, tfRGB10A2, tfRGBA8,
6649 tfBGR10, tfBGR10A2, tfBGRA8: begin
6650 Info.biBitCount := 32;
6651 Info.biCompression := BMP_COMP_BITFIELDS;
6654 raise EglBitmapUnsupportedFormat.Create(Format);
6656 Info.biXPelsPerMeter := 2835;
6657 Info.biYPelsPerMeter := 2835;
6660 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6661 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
6662 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
6664 RedMask := FormatDesc.RedMask;
6665 GreenMask := FormatDesc.GreenMask;
6666 BlueMask := FormatDesc.BlueMask;
6667 AlphaMask := FormatDesc.AlphaMask;
6671 aStream.Write(Header, SizeOf(Header));
6672 aStream.Write(Info, SizeOf(Info));
6675 if Assigned(Converter) then
6676 aStream.Write(Converter.ColorTable[0].b,
6677 SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable));
6680 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6681 aStream.Write(RedMask, SizeOf(Cardinal));
6682 aStream.Write(GreenMask, SizeOf(Cardinal));
6683 aStream.Write(BlueMask, SizeOf(Cardinal));
6684 aStream.Write(AlphaMask, SizeOf(Cardinal));
6688 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
6689 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
6690 Padding := GetLineWidth - wbLineSize;
6694 inc(pData, (Height-1) * rbLineSize);
6696 // prepare row buffer. But only for RGB because RGBA supports color masks
6697 // so it's possible to change color within the image.
6698 if Assigned(Converter) then begin
6699 FormatDesc.PreparePixel(Pixel);
6700 GetMem(ConvertBuffer, wbLineSize);
6701 SourceFD := FormatDesc.CreateMappingData;
6702 DestFD := Converter.CreateMappingData;
6704 ConvertBuffer := nil;
6707 for LineIdx := 0 to Height - 1 do begin
6709 if Assigned(Converter) then begin
6711 dstData := ConvertBuffer;
6712 for PixelIdx := 0 to Info.biWidth-1 do begin
6713 FormatDesc.Unmap(srcData, Pixel, SourceFD);
6714 glBitmapConvertPixel(Pixel, FormatDesc, Converter);
6715 Converter.Map(Pixel, dstData, DestFD);
6717 aStream.Write(ConvertBuffer^, wbLineSize);
6719 aStream.Write(pData^, rbLineSize);
6721 dec(pData, rbLineSize);
6722 if (Padding > 0) then
6723 aStream.Write(PaddingBuff, Padding);
6726 // destroy row buffer
6727 if Assigned(ConvertBuffer) then begin
6728 FormatDesc.FreeMappingData(SourceFD);
6729 Converter.FreeMappingData(DestFD);
6730 FreeMem(ConvertBuffer);
6734 if Assigned(Converter) then
6739 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6740 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6741 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6743 TTGAHeader = packed record
6747 //ColorMapSpec: Array[0..4] of Byte;
6748 ColorMapStart: Word;
6749 ColorMapLength: Word;
6750 ColorMapEntrySize: Byte;
6760 TGA_UNCOMPRESSED_RGB = 2;
6761 TGA_UNCOMPRESSED_GRAY = 3;
6762 TGA_COMPRESSED_RGB = 10;
6763 TGA_COMPRESSED_GRAY = 11;
6765 TGA_NONE_COLOR_TABLE = 0;
6767 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6768 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
6771 ImageData: System.PByte;
6772 StartPosition: Int64;
6773 PixelSize, LineSize: Integer;
6774 tgaFormat: TglBitmapFormat;
6775 FormatDesc: TFormatDescriptor;
6776 Counter: packed record
6778 low, high, dir: Integer;
6785 ////////////////////////////////////////////////////////////////////////////////////////
6786 procedure ReadUncompressed;
6789 buf, tmp1, tmp2: System.PByte;
6792 if (Counter.X.dir < 0) then
6793 buf := GetMem(LineSize);
6795 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
6796 tmp1 := ImageData + (Counter.Y.low * LineSize); //pointer to LineStart
6797 if (Counter.X.dir < 0) then begin //flip X
6798 aStream.Read(buf^, LineSize);
6799 tmp2 := buf + LineSize - PixelSize; //pointer to last pixel in line
6800 for i := 0 to Header.Width-1 do begin //for all pixels in line
6801 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
6806 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
6809 aStream.Read(tmp1^, LineSize);
6810 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
6813 if Assigned(buf) then
6818 ////////////////////////////////////////////////////////////////////////////////////////
6819 procedure ReadCompressed;
6821 /////////////////////////////////////////////////////////////////
6823 TmpData: System.PByte;
6824 LinePixelsRead: Integer;
6825 procedure CheckLine;
6827 if (LinePixelsRead >= Header.Width) then begin
6828 LinePixelsRead := 0;
6829 inc(Counter.Y.low, Counter.Y.dir); //next line index
6830 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6831 if (Counter.X.dir < 0) then //if x flipped then
6832 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6836 /////////////////////////////////////////////////////////////////
6839 CacheSize, CachePos: Integer;
6840 procedure CachedRead(out Buffer; Count: Integer);
6844 if (CachePos + Count > CacheSize) then begin
6845 //if buffer overflow save non read bytes
6847 if (CacheSize - CachePos > 0) then begin
6848 BytesRead := CacheSize - CachePos;
6849 Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead);
6850 inc(CachePos, BytesRead);
6853 //load cache from file
6854 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
6855 aStream.Read(Cache^, CacheSize);
6858 //read rest of requested bytes
6859 if (Count - BytesRead > 0) then begin
6860 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
6861 inc(CachePos, Count - BytesRead);
6864 //if no buffer overflow just read the data
6865 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
6866 inc(CachePos, Count);
6870 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
6875 inc(aBuffer, Counter.X.dir);
6878 PWord(aBuffer)^ := PWord(aData)^;
6879 inc(aBuffer, 2 * Counter.X.dir);
6882 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
6883 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
6884 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
6885 inc(aBuffer, 3 * Counter.X.dir);
6888 PCardinal(aBuffer)^ := PCardinal(aData)^;
6889 inc(aBuffer, 4 * Counter.X.dir);
6895 TotalPixelsToRead, TotalPixelsRead: Integer;
6897 buf: array [0..3] of Byte; //1 pixel is max 32bit long
6898 PixelRepeat: Boolean;
6899 PixelsToRead, PixelCount: Integer;
6904 TotalPixelsToRead := Header.Width * Header.Height;
6905 TotalPixelsRead := 0;
6906 LinePixelsRead := 0;
6908 GetMem(Cache, CACHE_SIZE);
6910 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6911 if (Counter.X.dir < 0) then //if x flipped then
6912 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6916 CachedRead(Temp, 1);
6917 PixelRepeat := (Temp and $80) > 0;
6918 PixelsToRead := (Temp and $7F) + 1;
6919 inc(TotalPixelsRead, PixelsToRead);
6922 CachedRead(buf[0], PixelSize);
6923 while (PixelsToRead > 0) do begin
6925 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
6926 while (PixelCount > 0) do begin
6927 if not PixelRepeat then
6928 CachedRead(buf[0], PixelSize);
6929 PixelToBuffer(@buf[0], TmpData);
6930 inc(LinePixelsRead);
6935 until (TotalPixelsRead >= TotalPixelsToRead);
6941 function IsGrayFormat: Boolean;
6943 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
6949 // reading header to test file and set cursor back to begin
6950 StartPosition := aStream.Position;
6951 aStream.Read(Header{%H-}, SizeOf(Header));
6953 // no colormapped files
6954 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
6955 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
6958 if Header.ImageID <> 0 then // skip image ID
6959 aStream.Position := aStream.Position + Header.ImageID;
6962 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
6963 0: tgaFormat := tfLuminance8;
6964 8: tgaFormat := tfAlpha8;
6967 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
6968 0: tgaFormat := tfLuminance16;
6969 8: tgaFormat := tfLuminance8Alpha8;
6970 end else case (Header.ImageDesc and $F) of
6971 0: tgaFormat := tfBGR5;
6972 1: tgaFormat := tfBGR5A1;
6973 4: tgaFormat := tfBGRA4;
6976 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6977 0: tgaFormat := tfBGR8;
6980 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6981 2: tgaFormat := tfBGR10A2;
6982 8: tgaFormat := tfBGRA8;
6986 if (tgaFormat = tfEmpty) then
6987 raise EglBitmapException.Create('LoadTga - unsupported format');
6989 FormatDesc := TFormatDescriptor.Get(tgaFormat);
6990 PixelSize := FormatDesc.GetSize(1, 1);
6991 LineSize := FormatDesc.GetSize(Header.Width, 1);
6993 GetMem(ImageData, LineSize * Header.Height);
6996 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
6997 Counter.X.low := Header.Height-1;;
6998 Counter.X.high := 0;
6999 Counter.X.dir := -1;
7002 Counter.X.high := Header.Height-1;
7007 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
7009 Counter.Y.high := Header.Height-1;
7012 Counter.Y.low := Header.Height-1;;
7013 Counter.Y.high := 0;
7014 Counter.Y.dir := -1;
7018 case Header.ImageType of
7019 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
7021 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
7025 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height);
7032 aStream.Position := StartPosition;
7035 else aStream.Position := StartPosition;
7038 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7039 procedure TglBitmap.SaveTGA(const aStream: TStream);
7042 LineSize, Size, x, y: Integer;
7043 Pixel: TglBitmapPixelData;
7044 LineBuf, SourceData, DestData: PByte;
7045 SourceMD, DestMD: Pointer;
7046 FormatDesc: TFormatDescriptor;
7047 Converter: TFormatDescriptor;
7049 if not (ftTGA in FormatGetSupportedFiles(Format)) then
7050 raise EglBitmapUnsupportedFormat.Create(Format);
7053 FillChar(Header{%H-}, SizeOf(Header), 0);
7056 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
7057 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
7058 Header.ImageType := TGA_UNCOMPRESSED_GRAY
7060 Header.ImageType := TGA_UNCOMPRESSED_RGB;
7063 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
7065 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
7066 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
7068 else if (Format in [tfBGR8, tfRGB8]) then
7076 Header.ImageDesc := 1 and $F;
7077 tfRGB10A2, tfBGR10A2:
7078 Header.ImageDesc := 2 and $F;
7080 Header.ImageDesc := 4 and $F;
7081 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
7082 Header.ImageDesc := 8 and $F;
7085 Header.Width := Width;
7086 Header.Height := Height;
7087 Header.ImageDesc := Header.ImageDesc or $20; //flip y
7088 aStream.Write(Header, SizeOf(Header));
7090 // convert RGB(A) to BGR(A)
7092 FormatDesc := TFormatDescriptor.Get(Format);
7093 Size := FormatDesc.GetSize(Dimension);
7094 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
7095 if (FormatDesc.RGBInverted = tfEmpty) then
7096 raise EglBitmapException.Create('inverted RGB format is empty');
7097 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
7098 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
7099 (Converter.PixelSize <> FormatDesc.PixelSize) then
7100 raise EglBitmapException.Create('invalid inverted RGB format');
7103 if Assigned(Converter) then begin
7104 LineSize := FormatDesc.GetSize(Width, 1);
7105 LineBuf := GetMem(LineSize);
7106 SourceMD := FormatDesc.CreateMappingData;
7107 DestMD := Converter.CreateMappingData;
7110 for y := 0 to Height-1 do begin
7111 DestData := LineBuf;
7112 for x := 0 to Width-1 do begin
7113 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
7114 Converter.Map(Pixel, DestData, DestMD);
7116 aStream.Write(LineBuf^, LineSize);
7120 FormatDesc.FreeMappingData(SourceMD);
7121 FormatDesc.FreeMappingData(DestMD);
7124 aStream.Write(Data^, Size);
7127 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7128 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7129 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7131 DDS_MAGIC: Cardinal = $20534444;
7133 // DDS_header.dwFlags
7134 DDSD_CAPS = $00000001;
7135 DDSD_HEIGHT = $00000002;
7136 DDSD_WIDTH = $00000004;
7137 DDSD_PIXELFORMAT = $00001000;
7139 // DDS_header.sPixelFormat.dwFlags
7140 DDPF_ALPHAPIXELS = $00000001;
7141 DDPF_ALPHA = $00000002;
7142 DDPF_FOURCC = $00000004;
7143 DDPF_RGB = $00000040;
7144 DDPF_LUMINANCE = $00020000;
7146 // DDS_header.sCaps.dwCaps1
7147 DDSCAPS_TEXTURE = $00001000;
7149 // DDS_header.sCaps.dwCaps2
7150 DDSCAPS2_CUBEMAP = $00000200;
7152 D3DFMT_DXT1 = $31545844;
7153 D3DFMT_DXT3 = $33545844;
7154 D3DFMT_DXT5 = $35545844;
7157 TDDSPixelFormat = packed record
7161 dwRGBBitCount: Cardinal;
7162 dwRBitMask: Cardinal;
7163 dwGBitMask: Cardinal;
7164 dwBBitMask: Cardinal;
7165 dwABitMask: Cardinal;
7168 TDDSCaps = packed record
7172 dwReserved: Cardinal;
7175 TDDSHeader = packed record
7180 dwPitchOrLinearSize: Cardinal;
7182 dwMipMapCount: Cardinal;
7183 dwReserved: array[0..10] of Cardinal;
7184 PixelFormat: TDDSPixelFormat;
7186 dwReserved2: Cardinal;
7189 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7190 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7193 Converter: TbmpBitfieldFormat;
7195 function GetDDSFormat: TglBitmapFormat;
7197 fd: TFormatDescriptor;
7199 Range: TglBitmapColorRec;
7203 with Header.PixelFormat do begin
7205 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7206 case Header.PixelFormat.dwFourCC of
7207 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7208 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7209 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7211 end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin
7213 //find matching format
7214 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7215 fd := TFormatDescriptor.Get(result);
7216 if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and
7217 (8 * fd.PixelSize = dwRGBBitCount) then
7221 //find format with same Range
7222 Range.r := dwRBitMask;
7223 Range.g := dwGBitMask;
7224 Range.b := dwBBitMask;
7225 Range.a := dwABitMask;
7226 for i := 0 to 3 do begin
7227 while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do
7228 Range.arr[i] := Range.arr[i] shr 1;
7230 for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
7231 fd := TFormatDescriptor.Get(result);
7234 if (fd.Range.arr[i] <> Range.arr[i]) then begin
7242 //no format with same range found -> use default
7243 if (result = tfEmpty) then begin
7244 if (dwABitMask > 0) then
7250 Converter := TbmpBitfieldFormat.Create;
7251 Converter.RedMask := dwRBitMask;
7252 Converter.GreenMask := dwGBitMask;
7253 Converter.BlueMask := dwBBitMask;
7254 Converter.AlphaMask := dwABitMask;
7255 Converter.PixelSize := dwRGBBitCount / 8;
7262 x, y, LineSize, RowSize, Magic: Cardinal;
7263 NewImage, TmpData, RowData, SrcData: System.PByte;
7264 SourceMD, DestMD: Pointer;
7265 Pixel: TglBitmapPixelData;
7266 ddsFormat: TglBitmapFormat;
7267 FormatDesc: TFormatDescriptor;
7272 StreamPos := aStream.Position;
7275 aStream.Read(Magic{%H-}, sizeof(Magic));
7276 if (Magic <> DDS_MAGIC) then begin
7277 aStream.Position := StreamPos;
7282 aStream.Read(Header{%H-}, sizeof(Header));
7283 if (Header.dwSize <> SizeOf(Header)) or
7284 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7285 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7287 aStream.Position := StreamPos;
7291 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7292 raise EglBitmapException.Create('LoadDDS - CubeMaps are not supported');
7294 ddsFormat := GetDDSFormat;
7296 if (ddsFormat = tfEmpty) then
7297 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7299 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7300 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7301 GetMem(NewImage, Header.dwHeight * LineSize);
7303 TmpData := NewImage;
7306 if Assigned(Converter) then begin
7307 RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8);
7308 GetMem(RowData, RowSize);
7309 SourceMD := Converter.CreateMappingData;
7310 DestMD := FormatDesc.CreateMappingData;
7312 for y := 0 to Header.dwHeight-1 do begin
7313 TmpData := NewImage + y * LineSize;
7315 aStream.Read(SrcData^, RowSize);
7316 for x := 0 to Header.dwWidth-1 do begin
7317 Converter.Unmap(SrcData, Pixel, SourceMD);
7318 glBitmapConvertPixel(Pixel, Converter, FormatDesc);
7319 FormatDesc.Map(Pixel, TmpData, DestMD);
7323 Converter.FreeMappingData(SourceMD);
7324 FormatDesc.FreeMappingData(DestMD);
7330 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7331 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7332 for Y := 0 to Header.dwHeight-1 do begin
7333 aStream.Read(TmpData^, RowSize);
7334 Inc(TmpData, LineSize);
7339 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7340 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7341 for Y := 0 to Header.dwHeight-1 do begin
7342 aStream.Read(TmpData^, RowSize);
7343 Inc(TmpData, LineSize);
7346 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7348 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
7355 FreeAndNil(Converter);
7359 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7360 procedure TglBitmap.SaveDDS(const aStream: TStream);
7363 FormatDesc: TFormatDescriptor;
7365 if not (ftDDS in FormatGetSupportedFiles(Format)) then
7366 raise EglBitmapUnsupportedFormat.Create(Format);
7368 FormatDesc := TFormatDescriptor.Get(Format);
7371 FillChar(Header{%H-}, SizeOf(Header), 0);
7372 Header.dwSize := SizeOf(Header);
7373 Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT;
7375 Header.dwWidth := Max(1, Width);
7376 Header.dwHeight := Max(1, Height);
7379 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7382 Header.PixelFormat.dwSize := sizeof(Header);
7383 if (FormatDesc.IsCompressed) then begin
7384 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC;
7386 tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1;
7387 tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3;
7388 tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5;
7390 end else if (Format in [tfAlpha8, tfAlpha16]) then begin
7391 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA;
7392 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7393 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7394 end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin
7395 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE;
7396 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7397 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7398 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7400 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB;
7401 Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8);
7402 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7403 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7404 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7405 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7408 if (FormatDesc.HasAlpha) then
7409 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7411 aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC));
7412 aStream.Write(Header, SizeOf(Header));
7413 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7416 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7417 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7418 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7419 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7421 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7422 result := fLines[aIndex]
7427 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7428 procedure TglBitmap2D.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
7429 const aWidth: Integer; const aHeight: Integer);
7431 Idx, LineWidth: Integer;
7433 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7435 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7437 fGetPixelFunc := GetPixel2DUnmap;
7438 fSetPixelFunc := SetPixel2DUnmap;
7441 if Assigned(Data) then begin
7442 SetLength(fLines, GetHeight);
7443 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7445 for Idx := 0 to GetHeight -1 do begin
7446 fLines[Idx] := Data;
7447 Inc(fLines[Idx], Idx * LineWidth);
7450 else SetLength(fLines, 0);
7452 SetLength(fLines, 0);
7454 fSetPixelFunc := nil;
7458 fGetPixelFunc := GetPixel2DDXT1;
7460 fGetPixelFunc := GetPixel2DDXT3;
7462 fGetPixelFunc := GetPixel2DDXT5;
7464 fGetPixelFunc := nil;
7470 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7471 procedure TglBitmap2D.UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
7473 FormatDesc: TFormatDescriptor;
7475 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7477 FormatDesc := TFormatDescriptor.Get(Format);
7478 if FormatDesc.IsCompressed then begin
7479 glCompressedTexImage2D(Target, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7480 end else if aBuildWithGlu then begin
7481 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7482 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7484 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7485 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7489 if (FreeDataAfterGenTexture) then
7493 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7494 procedure TglBitmap2D.AfterConstruction;
7497 Target := GL_TEXTURE_2D;
7500 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7501 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7504 Size, w, h: Integer;
7505 FormatDesc: TFormatDescriptor;
7507 FormatDesc := TFormatDescriptor.Get(Format);
7508 if FormatDesc.IsCompressed then
7509 raise EglBitmapUnsupportedFormat.Create(Format);
7511 w := aRight - aLeft;
7512 h := aBottom - aTop;
7513 Size := FormatDesc.GetSize(w, h);
7516 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7517 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7518 SetDataPointer(Temp, Format, w, h);
7526 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7527 procedure TglBitmap2D.GetDataFromTexture;
7530 TempWidth, TempHeight: Integer;
7531 TempIntFormat: Cardinal;
7532 IntFormat, f: TglBitmapFormat;
7533 FormatDesc: TFormatDescriptor;
7538 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7539 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7540 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7542 IntFormat := tfEmpty;
7543 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin
7544 FormatDesc := TFormatDescriptor.Get(f);
7545 if (FormatDesc.glInternalFormat = TempIntFormat) then begin
7546 IntFormat := FormatDesc.Format;
7551 // Getting data from OpenGL
7552 FormatDesc := TFormatDescriptor.Get(IntFormat);
7553 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
7555 if FormatDesc.IsCompressed then
7556 glGetCompressedTexImage(Target, 0, Temp)
7558 glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
7559 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
7566 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7567 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
7569 BuildWithGlu, PotTex, TexRec: Boolean;
7572 if Assigned(Data) then begin
7573 // Check Texture Size
7574 if (aTestTextureSize) then begin
7575 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7577 if ((Height > TexSize) or (Width > TexSize)) then
7578 raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7580 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
7581 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE);
7583 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7584 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7588 SetupParameters(BuildWithGlu);
7589 UploadData(Target, BuildWithGlu);
7590 glAreTexturesResident(1, @fID, @fIsResident);
7594 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7595 function TglBitmap2D.FlipHorz: Boolean;
7598 TempDestData, DestData, SourceData: PByte;
7601 result := inherited FlipHorz;
7602 if Assigned(Data) then begin
7604 ImgSize := Height * fRowSize;
7605 GetMem(DestData, ImgSize);
7607 TempDestData := DestData;
7608 Dec(TempDestData, fRowSize + fPixelSize);
7609 for Row := 0 to Height -1 do begin
7610 Inc(TempDestData, fRowSize * 2);
7611 for Col := 0 to Width -1 do begin
7612 Move(SourceData^, TempDestData^, fPixelSize);
7613 Inc(SourceData, fPixelSize);
7614 Dec(TempDestData, fPixelSize);
7617 SetDataPointer(DestData, Format);
7626 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7627 function TglBitmap2D.FlipVert: Boolean;
7630 TempDestData, DestData, SourceData: PByte;
7632 result := inherited FlipVert;
7633 if Assigned(Data) then begin
7635 GetMem(DestData, Height * fRowSize);
7637 TempDestData := DestData;
7638 Inc(TempDestData, Width * (Height -1) * fPixelSize);
7639 for Row := 0 to Height -1 do begin
7640 Move(SourceData^, TempDestData^, fRowSize);
7641 Dec(TempDestData, fRowSize);
7642 Inc(SourceData, fRowSize);
7644 SetDataPointer(DestData, Format);
7653 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7654 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7655 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7657 TMatrixItem = record
7662 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
7663 TglBitmapToNormalMapRec = Record
7665 Heights: array of Single;
7666 MatrixU : array of TMatrixItem;
7667 MatrixV : array of TMatrixItem;
7671 ONE_OVER_255 = 1 / 255;
7673 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7674 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
7678 with FuncRec do begin
7680 Source.Data.r * LUMINANCE_WEIGHT_R +
7681 Source.Data.g * LUMINANCE_WEIGHT_G +
7682 Source.Data.b * LUMINANCE_WEIGHT_B;
7683 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
7687 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7688 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
7691 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
7694 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7695 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
7697 TVec = Array[0..2] of Single;
7704 function GetHeight(X, Y: Integer): Single;
7706 with FuncRec do begin
7707 X := Max(0, Min(Size.X -1, X));
7708 Y := Max(0, Min(Size.Y -1, Y));
7709 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
7714 with FuncRec do begin
7715 with PglBitmapToNormalMapRec(Args)^ do begin
7717 for Idx := Low(MatrixU) to High(MatrixU) do
7718 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
7721 for Idx := Low(MatrixU) to High(MatrixU) do
7722 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
7724 Vec[0] := -du * Scale;
7725 Vec[1] := -dv * Scale;
7730 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
7731 if Len <> 0 then begin
7732 Vec[0] := Vec[0] * Len;
7733 Vec[1] := Vec[1] * Len;
7734 Vec[2] := Vec[2] * Len;
7738 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
7739 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
7740 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
7744 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7745 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
7747 Rec: TglBitmapToNormalMapRec;
7749 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
7751 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
7752 Matrix[Index].X := X;
7753 Matrix[Index].Y := Y;
7754 Matrix[Index].W := W;
7759 if TFormatDescriptor.Get(Format).IsCompressed then
7760 raise EglBitmapUnsupportedFormat.Create(Format);
7762 if aScale > 100 then
7764 else if aScale < -100 then
7767 Rec.Scale := aScale;
7769 SetLength(Rec.Heights, Width * Height);
7773 SetLength(Rec.MatrixU, 2);
7774 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
7775 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
7777 SetLength(Rec.MatrixV, 2);
7778 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
7779 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
7783 SetLength(Rec.MatrixU, 6);
7784 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
7785 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
7786 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
7787 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
7788 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
7789 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
7791 SetLength(Rec.MatrixV, 6);
7792 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
7793 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
7794 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
7795 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
7796 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
7797 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
7801 SetLength(Rec.MatrixU, 6);
7802 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
7803 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
7804 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
7805 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
7806 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
7807 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
7809 SetLength(Rec.MatrixV, 6);
7810 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
7811 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
7812 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
7813 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
7814 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
7815 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
7819 SetLength(Rec.MatrixU, 20);
7820 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
7821 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
7822 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
7823 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
7824 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
7825 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
7826 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
7827 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
7828 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
7829 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
7830 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
7831 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
7832 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
7833 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
7834 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
7835 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
7836 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
7837 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
7838 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
7839 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
7841 SetLength(Rec.MatrixV, 20);
7842 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
7843 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
7844 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
7845 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
7846 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
7847 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
7848 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
7849 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
7850 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
7851 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
7852 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
7853 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
7854 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
7855 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
7856 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
7857 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
7858 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
7859 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
7860 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
7861 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
7866 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
7867 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec)
7869 AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec);
7870 AddFunc(glBitmapToNormalMapFunc, false, @Rec);
7872 SetLength(Rec.Heights, 0);
7885 procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
7890 if Height > 1 then begin
7891 // extract first line of the data
7892 Size := FormatGetImageSize(glBitmapPosition(Width), Format);
7893 GetMem(pTemp, Size);
7895 Move(Data^, pTemp^, Size);
7902 inherited SetDataPointer(pTemp, Format, Width);
7904 if FormatIsUncompressed(Format) then begin
7905 fUnmapFunc := FormatGetUnMapFunc(Format);
7906 fGetPixelFunc := GetPixel1DUnmap;
7911 procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
7916 Inc(pTemp, Pos.X * fPixelSize);
7918 fUnmapFunc(pTemp, Pixel);
7922 function TglBitmap1D.FlipHorz: Boolean;
7925 pTempDest, pDest, pSource: pByte;
7927 result := inherited FlipHorz;
7929 if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin
7932 GetMem(pDest, fRowSize);
7936 Inc(pTempDest, fRowSize);
7937 for Col := 0 to Width -1 do begin
7938 Move(pSource^, pTempDest^, fPixelSize);
7940 Inc(pSource, fPixelSize);
7941 Dec(pTempDest, fPixelSize);
7944 SetDataPointer(pDest, InternalFormat);
7954 procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
7957 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
7958 glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data)
7962 if BuildWithGlu then
7963 gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data)
7965 glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data);
7968 if (FreeDataAfterGenTexture) then
7973 procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean);
7975 BuildWithGlu, TexRec: Boolean;
7976 glFormat, glInternalFormat, glType: Cardinal;
7979 if Assigned(Data) then begin
7980 // Check Texture Size
7981 if (TestTextureSize) then begin
7982 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7984 if (Width > TexSize) then
7985 raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7987 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7988 (Target = GL_TEXTURE_RECTANGLE_ARB);
7990 if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7991 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7996 SetupParameters(BuildWithGlu);
7997 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
7999 UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
8002 glAreTexturesResident(1, @fID, @fIsResident);
8007 procedure TglBitmap1D.AfterConstruction;
8011 Target := GL_TEXTURE_1D;
8015 { TglBitmapCubeMap }
8017 procedure TglBitmapCubeMap.AfterConstruction;
8021 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
8022 raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
8024 SetWrap; // set all to GL_CLAMP_TO_EDGE
8025 Target := GL_TEXTURE_CUBE_MAP;
8026 fGenMode := GL_REFLECTION_MAP;
8030 procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean);
8032 inherited Bind (EnableTextureUnit);
8034 if EnableTexCoordsGen then begin
8035 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
8036 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
8037 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
8038 glEnable(GL_TEXTURE_GEN_S);
8039 glEnable(GL_TEXTURE_GEN_T);
8040 glEnable(GL_TEXTURE_GEN_R);
8045 procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean);
8047 glFormat, glInternalFormat, glType: Cardinal;
8048 BuildWithGlu: Boolean;
8051 // Check Texture Size
8052 if (TestTextureSize) then begin
8053 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
8055 if ((Height > TexSize) or (Width > TexSize)) then
8056 raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
8058 if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
8059 raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
8063 if ID = 0 then begin
8065 SetupParameters(BuildWithGlu);
8068 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
8070 UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu);
8074 procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean);
8076 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
8080 procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen,
8081 DisableTextureUnit: Boolean);
8083 inherited Unbind (DisableTextureUnit);
8085 if DisableTexCoordsGen then begin
8086 glDisable(GL_TEXTURE_GEN_S);
8087 glDisable(GL_TEXTURE_GEN_T);
8088 glDisable(GL_TEXTURE_GEN_R);
8093 { TglBitmapNormalMap }
8096 TVec = Array[0..2] of Single;
8097 TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8099 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
8100 TglBitmapNormalMapRec = record
8102 Func: TglBitmapNormalMapGetVectorFunc;
8106 procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8109 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8110 Vec[2] := - (Position.X + 0.5 - HalfSize);
8114 procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8116 Vec[0] := - HalfSize;
8117 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8118 Vec[2] := Position.X + 0.5 - HalfSize;
8122 procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8124 Vec[0] := Position.X + 0.5 - HalfSize;
8126 Vec[2] := Position.Y + 0.5 - HalfSize;
8130 procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8132 Vec[0] := Position.X + 0.5 - HalfSize;
8133 Vec[1] := - HalfSize;
8134 Vec[2] := - (Position.Y + 0.5 - HalfSize);
8138 procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8140 Vec[0] := Position.X + 0.5 - HalfSize;
8141 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8146 procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
8148 Vec[0] := - (Position.X + 0.5 - HalfSize);
8149 Vec[1] := - (Position.Y + 0.5 - HalfSize);
8150 Vec[2] := - HalfSize;
8154 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
8159 with FuncRec do begin
8160 with PglBitmapNormalMapRec (CustomData)^ do begin
8161 Func(Vec, Position, HalfSize);
8164 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
8165 if Len <> 0 then begin
8166 Vec[0] := Vec[0] * Len;
8167 Vec[1] := Vec[1] * Len;
8168 Vec[2] := Vec[2] * Len;
8171 // Scale Vector and AddVectro
8172 Vec[0] := Vec[0] * 0.5 + 0.5;
8173 Vec[1] := Vec[1] * 0.5 + 0.5;
8174 Vec[2] := Vec[2] * 0.5 + 0.5;
8178 Dest.Red := Round(Vec[0] * 255);
8179 Dest.Green := Round(Vec[1] * 255);
8180 Dest.Blue := Round(Vec[2] * 255);
8185 procedure TglBitmapNormalMap.AfterConstruction;
8189 fGenMode := GL_NORMAL_MAP;
8193 procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer;
8194 TestTextureSize: Boolean);
8196 Rec: TglBitmapNormalMapRec;
8197 SizeRec: TglBitmapPixelPosition;
8199 Rec.HalfSize := Size div 2;
8201 FreeDataAfterGenTexture := false;
8203 SizeRec.Fields := [ffX, ffY];
8208 Rec.Func := glBitmapNormalMapPosX;
8209 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8210 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize);
8213 Rec.Func := glBitmapNormalMapNegX;
8214 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8215 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize);
8218 Rec.Func := glBitmapNormalMapPosY;
8219 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8220 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize);
8223 Rec.Func := glBitmapNormalMapNegY;
8224 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8225 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize);
8228 Rec.Func := glBitmapNormalMapPosZ;
8229 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8230 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize);
8233 Rec.Func := glBitmapNormalMapNegZ;
8234 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8235 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize);
8240 glBitmapSetDefaultFormat(tfEmpty);
8241 glBitmapSetDefaultMipmap(mmMipmap);
8242 glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8243 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8245 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8246 glBitmapSetDefaultDeleteTextureOnFree (true);
8248 TFormatDescriptor.Init;
8250 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8251 OpenGLInitialized := false;
8252 InitOpenGLCS := TCriticalSection.Create;
8256 TFormatDescriptor.Finalize;
8258 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
8259 FreeAndNil(InitOpenGLCS);