1 {***********************************************************
2 glBitmap by Steffen Xonna aka Lossy eX (2003-2008)
3 http://www.opengl24.de/index.php?cat=header&file=glbitmap
4 ------------------------------------------------------------
5 The contents of this file are used with permission, subject to
6 the Mozilla Public License Version 1.1 (the "License"); you may
7 not use this file except in compliance with the License. You may
8 obtain a copy of the License at
9 http://www.mozilla.org/MPL/MPL-1.1.html
10 ------------------------------------------------------------
12 ------------------------------------------------------------
15 - The define GLB_DELPHI dosn't check versions anymore. If you say you are using delphi
16 then it's your problem if that isn't true. This prevents the unit for incompatibility
17 with newer versions of Delphi.
18 - Problems with D2009+ resolved (Thanks noeska and all i forgot)
19 - GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson)
21 - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson)
22 - Additional Datapointer for functioninterface now has the name CustomData
24 - AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson)
25 - If you load an texture from an file the property Filename will be set to the name of the file
26 - Three new properties to attach custom data to the Texture objects
27 - CustomName (free for use string)
28 - CustomNameW (free for use widestring)
29 - CustomDataPointer (free for use pointer to attach other objects or complex structures)
31 - RLE TGAs loaded much faster
33 - fixed some problem with reading RLE TGAs.
35 - function clone now only copys data if it's assigned and now it also copies the ID
36 - it seems that lazarus dont like comments in comments.
38 - It's possible to set the id of the texture
39 - define GLB_NO_NATIVE_GL deactivated by default
41 - Now supports the following libraries
45 - Linux compatibillity via free pascal compatibility (delphi sources optional)
46 - BMPs now loaded manuel
48 - Property DataPtr now has the name Data
49 - Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR
50 - Unused Depth removed
51 - Function FreeData to freeing image data added
53 - ImageID flag of TGAs was ignored. (Thanks Zwoetzen)
55 - Function SetBorderColor implemented (only used by opengl if wrap is set to GL_CLAMP_TO_BORDER)
56 - Function AddAlphaFromValue implemented to use an fixed Value as Alphachannel
57 - Function ReadOpenGLExtension is now only intern
59 - pngimage now disabled by default like all other versions.
61 - Setting up an anisotropic filter of 0 isnt allowed by nvidia (Thanks Ogridi)
63 - Fixed some Problem with Delphi 5
64 - Now uses the newest version of pngimage. Makes saving pngs much easier.
66 - Property IsCompressed and Size removed. Not really supported by Spec (Thanks Ogridi)
68 - Internal Format ifDepth8 added
69 - function GrabScreen now supports all uncompressed formats
71 - AddAlphaFromglBitmap implemented
73 - LoadFromResource and LoadFromResourceId now needs an Instance and an ResourceType (for ID)
75 - Width, Height and Depth internal changed to TglBitmapPixelPosition.
76 property Width, Height, Depth are still existing and new property Dimension are avail
78 - Added native OpenGL Support. Breaking the dglOpenGL "barrier".
80 - Added function GrabScreen to class TglBitmap2D
82 - Added support to Save images
83 - Added function Clone to Clone Instance
85 - Functions now works with Cardinals for each channel. Up to 32 Bits per channel.
87 - Several speed optimizations
89 - Internal structure change. Loading of TGA, PNG and DDS improved.
90 Data, format and size will now set directly with SetDataPtr.
91 - AddFunc now works with all Types of Images and Formats
92 - Some Funtions moved to Baseclass TglBitmap
94 - Added Support to decompress DXT3 and DXT5 compressed Images.
95 - Added Mapping to convert data from one format into an other.
97 - Added method ConvertTo in Class TglBitmap2D. Method allows to convert every
98 supported Input format (supported by GetPixel) into any uncompresed Format
99 - Added Support to decompress DXT1 compressed Images.
100 - SwapColors replaced by ConvertTo
102 - Added Support for compressed DDSs
103 - Added new internal formats (DXT1, DXT3, DXT5)
105 - Parameter Components renamed to InternalFormat
107 - Some AllocMem replaced with GetMem (little speed change)
108 - better exception handling. Better protection from memory leaks.
110 - Added support for Direct Draw Surfaces (.DDS) (uncompressed images only)
111 - Added new internal formats (RGB8, RGBA8, RGBA4, RGB5A1, RGB10A2, R5G6B5)
113 - Added support for Grayscale textures
114 - Added internal formats (Alpha, Luminance, LuminanceAlpha, BGR8, BGRA8)
116 - Added support for GL_VERSION_2_0
117 - Added support for GL_EXT_texture_filter_anisotropic
119 - Function FillWithColor fills the Image with one Color
120 - Function LoadNormalMap added
122 - ToNormalMap allows to Create an NormalMap from the Alphachannel
123 - ToNormalMap now supports Sobel (nmSobel) function.
125 - support for RLE Compressed RGB TGAs added
127 - Class TglBitmapNormalMap added to support Normalmap generation
128 - Added function ToNormalMap in class TglBitmap2D to genereate normal maps from textures.
129 3 Filters are supported. (4 Samples, 3x3 and 5x5)
131 - Method LoadCubeMapClass removed
132 - LoadCubeMap returnvalue is now the Texture paramter. Such as LoadTextures
133 - virtual abstract method GenTexture in class TglBitmap now is protected
135 - now support DescriptionFlag in LoadTga. Allows vertical flipped images to be loaded as normal
137 - little enhancement for IsPowerOfTwo
138 - TglBitmap1D.GenTexture now tests NPOT Textures
140 - some little name changes. All properties or function with Texture in name are
141 now without texture in name. We have allways texture so we dosn't name it.
143 - GenTexture now tests if texture is NPOT and NPOT-Texture are supported or
144 TextureTarget is GL_TEXTURE_RECTANGLE. Else it raised an exception.
146 - added support for GL_ARB_texture_rectangle, GL_EXT_texture_rectangle and GL_NV_texture_rectangle
148 - Function Unbind added
149 - call of SetFilter or SetTextureWrap if TextureID exists results in setting properties to opengl texture.
151 - class TglBitmapCubeMap added (allows to Create Cubemaps)
153 - Added Support for PNG Images. (http://pngdelphi.sourceforge.net/)
154 To Enable png's use the define pngimage
156 - New Functioninterface added
157 - Function GetPixel added
159 - Property BuildMipMaps renamed to MipMap
161 - property Name removed.
162 - BuildMipMaps is now a set of 3 values. None, GluBuildMipmaps and SGIS_generate_mipmap
164 - property name added. Only used in glForms!
166 - property FreeDataAfterGenTexture is now available as default (default = true)
167 - BuildMipmaps now implemented in TglBitmap1D (i've forgotten it)
168 - function MoveMemory replaced with function Move (little speed change)
169 - several calculations stored in variables (little speed change)
171 - property BuildMipsMaps added (default = true)
172 if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps
173 - property FreeDataAfterGenTexture added (default = true)
174 if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated.
175 - parameter DisableOtherTextureUnits of Bind removed
176 - parameter FreeDataAfterGeneration of GenTextures removed
178 - TglBitmap dosn't delete data if class was destroyed (fixed)
180 - Bind now enables TextureUnits (by params)
181 - GenTextures can leave data (by param)
182 - LoadTextures now optimal
184 - Performance optimization in AddFunc
185 - procedure Bind moved to subclasses
186 - Added new Class TglBitmap1D to support real OpenGL 1D Textures
188 - Texturefilter and texturewrap now also as defaults
189 Minfilter = GL_LINEAR_MIPMAP_LINEAR
190 Magfilter = GL_LINEAR
191 Wrap(str) = GL_CLAMP_TO_EDGE
192 - Added new format tfCompressed to create a compressed texture.
193 - propertys IsCompressed, TextureSize and IsResident added
194 IsCompressed and TextureSize only contains data from level 0
196 - Added function AddFunc to add PerPixelEffects to Image
197 - LoadFromFunc now based on AddFunc
198 - Invert now based on AddFunc
199 - SwapColors now based on AddFunc
201 - Added function FlipHorz
203 - Added function LaodFromFunc to create images with function
204 - Added function FlipVert
205 - Added internal format RGB(A) if GL_EXT_bgra or OpenGL 1.2 isn't supported
207 - Added Alphafunctions to calculate alpha per function
208 - Added Alpha from ColorKey using alphafunctions
210 - First full functionally Version of glBitmap
211 - Support for 24Bit and 32Bit TGA Pictures added
213 - begin of programming
214 ***********************************************************}
217 {.$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
218 // Please uncomment the defines below to configure the glBitmap to your preferences.
219 // If you have configured the unit you can uncomment the warning above.
221 // ###### Start of preferences ################################################
223 {$DEFINE GLB_NO_NATIVE_GL}
224 // To enable the dglOpenGL.pas Header
225 // With native GL then bindings are staticlly declared to support other headers
226 // or use the glBitmap inside of DLLs (minimize codesize).
230 // To enable the support for SDL_surfaces
232 {.$DEFINE GLB_DELPHI}
233 // To enable the support for TBitmap from Delphi (not lazarus)
236 // *** image libs ***
238 {.$DEFINE GLB_SDL_IMAGE}
239 // To enable the support of SDL_image to load files. (READ ONLY)
240 // If you enable SDL_image all other libraries will be ignored!
243 {.$DEFINE GLB_PNGIMAGE}
244 // to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/
245 // if you enable pngimage the libPNG will be ignored
247 {.$DEFINE GLB_LIB_PNG}
248 // to use the libPNG http://www.libpng.org/
249 // You will need an aditional header.
250 // http://www.opengl24.de/index.php?cat=header&file=libpng
252 {.$DEFINE GLB_DELPHI_JPEG}
253 // if you enable delphi jpegs the libJPEG will be ignored
255 {.$DEFINE GLB_LIB_JPEG}
256 // to use the libJPEG http://www.ijg.org/
257 // You will need an aditional header.
258 // http://www.opengl24.de/index.php?cat=header&file=libjpeg
260 // ###### End of preferences ##################################################
263 // ###### PRIVATE. Do not change anything. ####################################
264 // *** old defines for compatibility ***
265 {$IFDEF NO_NATIVE_GL}
266 {$DEFINE GLB_NO_NATIVE_GL}
269 {$definde GLB_PNGIMAGE}
272 // *** Delphi Versions ***
286 // *** checking define combinations ***
287 {$IFDEF GLB_SDL_IMAGE}
289 {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
292 {$IFDEF GLB_PNGIMAGE}
293 {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
294 {$undef GLB_PNGIMAGE}
296 {$IFDEF GLB_DELPHI_JPEG}
297 {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
298 {$undef GLB_DELPHI_JPEG}
301 {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
304 {$IFDEF GLB_LIB_JPEG}
305 {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
306 {$undef GLB_LIB_JPEG}
309 {$DEFINE GLB_SUPPORT_PNG_READ}
310 {$DEFINE GLB_SUPPORT_JPEG_READ}
313 {$IFDEF GLB_PNGIMAGE}
315 {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'}
319 {$DEFINE GLB_SUPPORT_PNG_READ}
320 {$DEFINE GLB_SUPPORT_PNG_WRITE}
324 {$DEFINE GLB_SUPPORT_PNG_READ}
325 {$DEFINE GLB_SUPPORT_PNG_WRITE}
328 {$IFDEF GLB_DELPHI_JPEG}
329 {$IFDEF GLB_LIB_JPEG}
330 {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
331 {$undef GLB_LIB_JPEG}
334 {$DEFINE GLB_SUPPORT_JPEG_READ}
335 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
338 {$IFDEF GLB_LIB_JPEG}
339 {$DEFINE GLB_SUPPORT_JPEG_READ}
340 {$DEFINE GLB_SUPPORT_JPEG_WRITE}
343 // *** general options ***
354 {$IFDEF GLB_NO_NATIVE_GL} dglOpenGL, {$ENDIF}
356 {$IFDEF GLB_SDL} SDL, {$ENDIF}
357 {$IFDEF GLB_DELPHI} Dialogs, Windows, Graphics, {$ENDIF}
359 {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF}
361 {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF}
362 {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF}
364 {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF}
365 {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF}
374 TRGBQuad = packed record
383 {$IFNDEF GLB_NO_NATIVE_GL}
384 // Native OpenGL Implementation
386 PByteBool = ^ByteBool;
396 GL_EXTENSIONS = $1F03;
401 GL_TEXTURE_1D = $0DE0;
402 GL_TEXTURE_2D = $0DE1;
404 GL_MAX_TEXTURE_SIZE = $0D33;
405 GL_PACK_ALIGNMENT = $0D05;
406 GL_UNPACK_ALIGNMENT = $0CF5;
419 GL_LUMINANCE4 = $803F;
420 GL_LUMINANCE8 = $8040;
421 GL_LUMINANCE4_ALPHA4 = $8043;
422 GL_LUMINANCE8_ALPHA8 = $8045;
423 GL_DEPTH_COMPONENT = $1902;
425 GL_UNSIGNED_BYTE = $1401;
427 GL_LUMINANCE = $1909;
428 GL_LUMINANCE_ALPHA = $190A;
430 GL_TEXTURE_WIDTH = $1000;
431 GL_TEXTURE_HEIGHT = $1001;
432 GL_TEXTURE_INTERNAL_FORMAT = $1003;
433 GL_TEXTURE_RED_SIZE = $805C;
434 GL_TEXTURE_GREEN_SIZE = $805D;
435 GL_TEXTURE_BLUE_SIZE = $805E;
436 GL_TEXTURE_ALPHA_SIZE = $805F;
437 GL_TEXTURE_LUMINANCE_SIZE = $8060;
440 GL_UNSIGNED_SHORT_5_6_5 = $8363;
441 GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
442 GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
443 GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
444 GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
449 GL_NEAREST_MIPMAP_NEAREST = $2700;
450 GL_LINEAR_MIPMAP_NEAREST = $2701;
451 GL_NEAREST_MIPMAP_LINEAR = $2702;
452 GL_LINEAR_MIPMAP_LINEAR = $2703;
453 GL_TEXTURE_MAG_FILTER = $2800;
454 GL_TEXTURE_MIN_FILTER = $2801;
457 GL_TEXTURE_WRAP_S = $2802;
458 GL_TEXTURE_WRAP_T = $2803;
461 GL_CLAMP_TO_EDGE = $812F;
462 GL_CLAMP_TO_BORDER = $812D;
463 GL_TEXTURE_WRAP_R = $8072;
465 GL_MIRRORED_REPEAT = $8370;
468 GL_TEXTURE_BORDER_COLOR = $1004;
471 GL_NORMAL_MAP = $8511;
472 GL_REFLECTION_MAP = $8512;
476 GL_TEXTURE_GEN_MODE = $2500;
477 GL_TEXTURE_GEN_S = $0C60;
478 GL_TEXTURE_GEN_T = $0C61;
479 GL_TEXTURE_GEN_R = $0C62;
482 GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C;
483 GL_TEXTURE_CUBE_MAP = $8513;
484 GL_TEXTURE_BINDING_CUBE_MAP = $8514;
485 GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515;
486 GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516;
487 GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517;
488 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518;
489 GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519;
490 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A;
492 GL_TEXTURE_RECTANGLE_ARB = $84F5;
494 // GL_SGIS_generate_mipmap
495 GL_GENERATE_MIPMAP = $8191;
497 // GL_EXT_texture_compression_s3tc
498 GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
499 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
500 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
501 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
503 // GL_EXT_texture_filter_anisotropic
504 GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
505 GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
507 // GL_ARB_texture_compression
508 GL_COMPRESSED_RGB = $84ED;
509 GL_COMPRESSED_RGBA = $84EE;
510 GL_COMPRESSED_ALPHA = $84E9;
511 GL_COMPRESSED_LUMINANCE = $84EA;
512 GL_COMPRESSED_LUMINANCE_ALPHA = $84EB;
521 GL_ARB_texture_border_clamp,
522 GL_ARB_texture_cube_map,
523 GL_ARB_texture_compression,
524 GL_ARB_texture_non_power_of_two,
525 GL_ARB_texture_rectangle,
526 GL_ARB_texture_mirrored_repeat,
528 GL_EXT_texture_edge_clamp,
529 GL_EXT_texture_cube_map,
530 GL_EXT_texture_compression_s3tc,
531 GL_EXT_texture_filter_anisotropic,
532 GL_EXT_texture_rectangle,
533 GL_NV_texture_rectangle,
534 GL_IBM_texture_mirrored_repeat,
535 GL_SGIS_generate_mipmap: Boolean;
539 libglu = 'libGLU.so.1';
540 libopengl = 'libGL.so.1';
542 libglu = 'glu32.dll';
543 libopengl = 'opengl32.dll';
547 function glXGetProcAddress(ProcName: PAnsiChar): Pointer; cdecl; external libopengl;
549 function wglGetProcAddress(ProcName: PAnsiChar): Pointer; stdcall; external libopengl;
552 function glGetString(name: Cardinal): PAnsiChar; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
554 procedure glEnable(cap: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
555 procedure glDisable(cap: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
556 procedure glGetIntegerv(pname: Cardinal; params: PInteger); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
558 procedure glTexImage1D(target: Cardinal; level, internalformat, width, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
559 procedure glTexImage2D(target: Cardinal; level, internalformat, width, height, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
561 procedure glGenTextures(n: Integer; Textures: PCardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
562 procedure glBindTexture(target: Cardinal; Texture: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
563 procedure glDeleteTextures(n: Integer; const textures: PCardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
565 procedure glReadPixels(x, y: Integer; width, height: Integer; format, atype: Cardinal; pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
566 procedure glPixelStorei(pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
567 procedure glGetTexImage(target: Cardinal; level: Integer; format: Cardinal; _type: Cardinal; pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
569 function glAreTexturesResident(n: Integer; const Textures: PCardinal; residences: PByteBool): ByteBool; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
570 procedure glTexParameteri(target: Cardinal; pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
571 procedure glTexParameterfv(target: Cardinal; pname: Cardinal; const params: PSingle); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
572 procedure glGetTexLevelParameteriv(target: Cardinal; level: Integer; pname: Cardinal; params: PInteger); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
573 procedure glTexGeni(coord, pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl;
575 function gluBuild1DMipmaps(Target: Cardinal; Components, Width: Integer; Format, atype: Cardinal; Data: Pointer): Integer; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libglu;
576 function gluBuild2DMipmaps(Target: Cardinal; Components, Width, Height: Integer; Format, aType: Cardinal; Data: Pointer): Integer; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libglu;
579 glCompressedTexImage2D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width, height: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF}
580 glCompressedTexImage1D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF}
581 glGetCompressedTexImage : procedure(target: Cardinal; level: Integer; img: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF}
586 ////////////////////////////////////////////////////////////////////////////////////////////////////
587 EglBitmapException = class(Exception);
588 EglBitmapSizeToLargeException = class(EglBitmapException);
589 EglBitmapNonPowerOfTwoException = class(EglBitmapException);
590 EglBitmapUnsupportedFormatFormat = class(EglBitmapException);
592 ////////////////////////////////////////////////////////////////////////////////////////////////////
610 tfLuminance12Alpha12,
611 tfLuminance16Alpha16,
655 TglBitmapFileType = (
656 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
657 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
661 TglBitmapFileTypes = set of TglBitmapFileType;
668 TglBitmapNormalMapFunc = (
674 ////////////////////////////////////////////////////////////////////////////////////////////////////
675 TglBitmapColorRec = packed record
677 0: (r, g, b, a: Cardinal);
678 1: (arr: array[0..3] of Cardinal);
681 TglBitmapPixelData = packed record
682 Data, Range: TglBitmapColorRec;
683 Format: TglBitmapFormat;
685 PglBitmapPixelData = ^TglBitmapPixelData;
687 ////////////////////////////////////////////////////////////////////////////////////////////////////
688 TglBitmapPixelPositionFields = set of (ffX, ffY);
689 TglBitmapPixelPosition = record
690 Fields : TglBitmapPixelPositionFields;
695 ////////////////////////////////////////////////////////////////////////////////////////////////////
697 TglBitmapFunctionRec = record
699 Size: TglBitmapPixelPosition;
700 Position: TglBitmapPixelPosition;
701 Source: TglBitmapPixelData;
702 Dest: TglBitmapPixelData;
705 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
707 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
712 fAnisotropic: Integer;
713 fDeleteTextureOnFree: Boolean;
714 fFreeDataAfterGenTexture: Boolean;
716 fIsResident: Boolean;
717 fBorderColor: array[0..3] of Single;
719 fDimension: TglBitmapPixelPosition;
720 fMipMap: TglBitmapMipMap;
721 fFormat: TglBitmapFormat;
728 fFilterMin: Cardinal;
729 fFilterMag: Cardinal;
739 fCustomNameW: WideString;
740 fCustomData: Pointer;
743 function GetWidth: Integer; virtual;
744 function GetHeight: Integer; virtual;
746 function GetFileWidth: Integer; virtual;
747 function GetFileHeight: Integer; virtual;
750 procedure SetCustomData(const aValue: Pointer);
751 procedure SetCustomName(const aValue: String);
752 procedure SetCustomNameW(const aValue: WideString);
753 procedure SetDeleteTextureOnFree(const aValue: Boolean);
754 procedure SetFormat(const aValue: TglBitmapFormat);
755 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
756 procedure SetID(const aValue: Cardinal);
757 procedure SetMipMap(const aValue: TglBitmapMipMap);
758 procedure SetTarget(const aValue: Cardinal);
759 procedure SetAnisotropic(const aValue: Integer);
762 procedure SetupParameters(var aBuildWithGlu: Boolean);
763 procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
764 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual;
765 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
767 function FlipHorz: Boolean; virtual;
768 function FlipVert: Boolean; virtual;
770 property Width: Integer read GetWidth;
771 property Height: Integer read GetHeight;
773 property FileWidth: Integer read GetFileWidth;
774 property FileHeight: Integer read GetFileHeight;
777 property ID: Cardinal read fID write SetID;
778 property Target: Cardinal read fTarget write SetTarget;
779 property Format: TglBitmapFormat read fFormat write SetFormat;
780 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
781 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
783 property Filename: String read fFilename;
784 property CustomName: String read fCustomName write SetCustomName;
785 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
786 property CustomData: Pointer read fCustomData write SetCustomData;
788 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
789 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
791 property Dimension: TglBitmapPixelPosition read fDimension;
792 property Data: PByte read fData;
793 property IsResident: Boolean read fIsResident;
795 procedure AfterConstruction; override;
796 procedure BeforeDestruction; override;
799 procedure LoadFromFile(const aFilename: String);
800 procedure LoadFromStream(const aStream: TStream); virtual;
801 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
802 const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0);
804 procedure LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
805 procedure LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
809 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
810 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
813 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt = 0): Boolean; overload;
814 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
815 const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0): Boolean; overload;
819 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
820 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
821 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
822 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
823 const aArgs: PtrInt = 0): Boolean;
827 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
828 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
829 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
830 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
831 const aArgs: PtrInt = 0): Boolean;
832 function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil;
833 const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
834 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
835 const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
838 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0): Boolean; virtual;
839 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
840 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
841 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
843 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
844 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
845 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
847 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
848 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
849 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
851 function RemoveAlpha: Boolean; virtual;
854 function Clone: TglBitmap;
855 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
856 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
857 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
861 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
862 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
863 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
866 procedure SetFilter(const aMin, aMag: Cardinal);
868 const S: Cardinal = GL_CLAMP_TO_EDGE;
869 const T: Cardinal = GL_CLAMP_TO_EDGE;
870 const R: Cardinal = GL_CLAMP_TO_EDGE);
872 procedure GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData); virtual;
873 procedure SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData); virtual;
875 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
876 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
879 constructor Create; overload;
880 constructor Create(const aFileName: String); overload;
881 constructor Create(const aStream: TStream); overload;
882 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload;
883 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0); overload;
885 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
886 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
889 {$IFDEF GLB_SUPPORT_PNG_READ}
890 function LoadPNG(const aStream: TStream): Boolean; virtual;
891 procedure SavePNG(const aStream: TStream); virtual;
893 {$IFDEF GLB_SUPPORT_JPEG_READ}
894 function LoadJPEG(const aStream: TStream): Boolean; virtual;
895 procedure SaveJPEG(const aStream: TStream); virtual;
897 function LoadBMP(const aStream: TStream): Boolean; virtual;
898 procedure SaveBMP(const aStream: TStream); virtual;
900 function LoadTGA(const aStream: TStream): Boolean; virtual;
901 procedure SaveTGA(const aStream: TStream); virtual;
903 function LoadDDS(const aStream: TStream): Boolean; virtual;
904 procedure SaveDDS(const aStream: TStream); virtual;
907 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
908 TglBitmap2D = class(TglBitmap)
911 fLines: array of PByte;
914 procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
915 procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
916 procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
917 procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
918 procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
919 procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
922 function GetScanline(const aIndex: Integer): Pointer;
923 procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
924 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
925 procedure UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
929 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
931 procedure AfterConstruction; override;
933 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
934 procedure GetDataFromTexture;
935 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
937 function FlipHorz: Boolean; override;
938 function FlipVert: Boolean; override;
940 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
941 const aScale: Single = 2; const aUseAlpha: Boolean = false);
945 TglBitmapCubeMap = class(TglBitmap2D)
950 procedure GenTexture(TestTextureSize: Boolean = true); reintroduce;
952 procedure AfterConstruction; override;
954 procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true);
956 procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = true); reintroduce; virtual;
957 procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = true); reintroduce; virtual;
961 TglBitmapNormalMap = class(TglBitmapCubeMap)
963 procedure AfterConstruction; override;
965 procedure GenerateNormalMap(Size: Integer = 32; TestTextureSize: Boolean = true);
969 TglBitmap1D = class(TglBitmap)
971 procedure GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
973 procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override;
974 procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
979 procedure AfterConstruction; override;
982 function FlipHorz: Boolean; override;
985 procedure GenTexture(TestTextureSize: Boolean = true); override;
990 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
992 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
993 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
994 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
995 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
996 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
997 procedure glBitmapSetDefaultWrap(
998 const S: Cardinal = GL_CLAMP_TO_EDGE;
999 const T: Cardinal = GL_CLAMP_TO_EDGE;
1000 const R: Cardinal = GL_CLAMP_TO_EDGE);
1002 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1003 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1004 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1005 function glBitmapGetDefaultFormat: TglBitmapFormat;
1006 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1007 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1009 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1010 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1011 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1014 glBitmapDefaultDeleteTextureOnFree: Boolean;
1015 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1016 glBitmapDefaultFormat: TglBitmapFormat;
1017 glBitmapDefaultMipmap: TglBitmapMipMap;
1018 glBitmapDefaultFilterMin: Cardinal;
1019 glBitmapDefaultFilterMag: Cardinal;
1020 glBitmapDefaultWrapS: Cardinal;
1021 glBitmapDefaultWrapT: Cardinal;
1022 glBitmapDefaultWrapR: Cardinal;
1025 function CreateGrayPalette: HPALETTE;
1032 function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
1033 function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
1034 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
1035 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
1036 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
1043 ////////////////////////////////////////////////////////////////////////////////////////////////////
1044 TShiftRec = packed record
1046 0: (r, g, b, a: Byte);
1047 1: (arr: array[0..3] of Byte);
1050 TFormatDescriptor = class(TObject)
1052 function GetRedMask: UInt64;
1053 function GetGreenMask: UInt64;
1054 function GetBlueMask: UInt64;
1055 function GetAlphaMask: UInt64;
1057 fFormat: TglBitmapFormat;
1058 fWithAlpha: TglBitmapFormat;
1059 fWithoutAlpha: TglBitmapFormat;
1060 fRGBInverted: TglBitmapFormat;
1061 fUncompressed: TglBitmapFormat;
1063 fIsCompressed: Boolean;
1065 fRange: TglBitmapColorRec;
1068 fglFormat: Cardinal;
1069 fglInternalFormat: Cardinal;
1070 fglDataFormat: Cardinal;
1072 function GetComponents: Integer; virtual;
1074 property Format: TglBitmapFormat read fFormat;
1075 property WithAlpha: TglBitmapFormat read fWithAlpha;
1076 property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
1077 property RGBInverted: TglBitmapFormat read fRGBInverted;
1078 property Components: Integer read GetComponents;
1079 property PixelSize: Single read fPixelSize;
1080 property IsCompressed: Boolean read fIsCompressed;
1082 property glFormat: Cardinal read fglFormat;
1083 property glInternalFormat: Cardinal read fglInternalFormat;
1084 property glDataFormat: Cardinal read fglDataFormat;
1086 property Range: TglBitmapColorRec read fRange;
1087 property Shift: TShiftRec read fShift;
1089 property RedMask: UInt64 read GetRedMask;
1090 property GreenMask: UInt64 read GetGreenMask;
1091 property BlueMask: UInt64 read GetBlueMask;
1092 property AlphaMask: UInt64 read GetAlphaMask;
1094 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
1095 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
1097 function GetSize(const aSize: TglBitmapPixelPosition): Integer; virtual; overload;
1098 function GetSize(const aWidth, aHeight: Integer): Integer; virtual; overload;
1100 function CreateMappingData: Pointer; virtual;
1101 procedure FreeMappingData(var aMappingData: Pointer); virtual;
1103 function IsEmpty: Boolean; virtual;
1104 function HasAlpha: Boolean; virtual;
1105 function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual;
1107 procedure PreparePixel(var aPixel: TglBitmapPixelData); virtual;
1109 constructor Create; virtual;
1111 class procedure Init;
1112 class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
1113 class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
1114 class procedure Clear;
1115 class procedure Finalize;
1117 TFormatDescriptorClass = class of TFormatDescriptor;
1119 TfdEmpty = class(TFormatDescriptor);
1121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1122 TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte
1123 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1124 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1125 constructor Create; override;
1128 TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte
1129 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1130 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1131 constructor Create; override;
1134 TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte
1135 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1136 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1137 constructor Create; override;
1140 TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte
1141 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1142 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1143 constructor Create; override;
1146 TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte
1147 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1148 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1149 constructor Create; override;
1152 TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse)
1153 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1154 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1155 constructor Create; override;
1158 TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte
1159 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1160 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1161 constructor Create; override;
1164 TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse)
1165 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1166 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1167 constructor Create; override;
1170 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1171 TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short
1172 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1173 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1174 constructor Create; override;
1177 TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short
1178 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1179 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1180 constructor Create; override;
1183 TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short
1184 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1185 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1186 constructor Create; override;
1189 TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short
1190 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1191 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1192 constructor Create; override;
1195 TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short
1196 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1197 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1198 constructor Create; override;
1201 TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short
1202 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1203 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1204 constructor Create; override;
1207 TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse)
1208 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1209 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1210 constructor Create; override;
1213 TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short
1214 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1215 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1216 constructor Create; override;
1219 TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse)
1220 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1221 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1222 constructor Create; override;
1225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1226 TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int
1227 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1228 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1229 constructor Create; override;
1232 TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int
1233 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1234 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1235 constructor Create; override;
1238 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1239 TfdAlpha4 = class(TfdAlpha_UB1)
1240 constructor Create; override;
1243 TfdAlpha8 = class(TfdAlpha_UB1)
1244 constructor Create; override;
1247 TfdAlpha12 = class(TfdAlpha_US1)
1248 constructor Create; override;
1251 TfdAlpha16 = class(TfdAlpha_US1)
1252 constructor Create; override;
1255 TfdLuminance4 = class(TfdLuminance_UB1)
1256 constructor Create; override;
1259 TfdLuminance8 = class(TfdLuminance_UB1)
1260 constructor Create; override;
1263 TfdLuminance12 = class(TfdLuminance_US1)
1264 constructor Create; override;
1267 TfdLuminance16 = class(TfdLuminance_US1)
1268 constructor Create; override;
1271 TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2)
1272 constructor Create; override;
1275 TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2)
1276 constructor Create; override;
1279 TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2)
1280 constructor Create; override;
1283 TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2)
1284 constructor Create; override;
1287 TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2)
1288 constructor Create; override;
1291 TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2)
1292 constructor Create; override;
1295 TfdR3G3B2 = class(TfdUniversal_UB1)
1296 constructor Create; override;
1299 TfdRGB4 = class(TfdUniversal_US1)
1300 constructor Create; override;
1303 TfdR5G6B5 = class(TfdUniversal_US1)
1304 constructor Create; override;
1307 TfdRGB5 = class(TfdUniversal_US1)
1308 constructor Create; override;
1311 TfdRGB8 = class(TfdRGB_UB3)
1312 constructor Create; override;
1315 TfdRGB10 = class(TfdUniversal_UI1)
1316 constructor Create; override;
1319 TfdRGB12 = class(TfdRGB_US3)
1320 constructor Create; override;
1323 TfdRGB16 = class(TfdRGB_US3)
1324 constructor Create; override;
1327 TfdRGBA2 = class(TfdRGBA_UB4)
1328 constructor Create; override;
1331 TfdRGBA4 = class(TfdUniversal_US1)
1332 constructor Create; override;
1335 TfdRGB5A1 = class(TfdUniversal_US1)
1336 constructor Create; override;
1339 TfdRGBA8 = class(TfdRGBA_UB4)
1340 constructor Create; override;
1343 TfdRGB10A2 = class(TfdUniversal_UI1)
1344 constructor Create; override;
1347 TfdRGBA12 = class(TfdRGBA_US4)
1348 constructor Create; override;
1351 TfdRGBA16 = class(TfdRGBA_US4)
1352 constructor Create; override;
1355 TfdBGR4 = class(TfdUniversal_US1)
1356 constructor Create; override;
1359 TfdB5G6R5 = class(TfdUniversal_US1)
1360 constructor Create; override;
1363 TfdBGR5 = class(TfdUniversal_US1)
1364 constructor Create; override;
1367 TfdBGR8 = class(TfdBGR_UB3)
1368 constructor Create; override;
1371 TfdBGR10 = class(TfdUniversal_UI1)
1372 constructor Create; override;
1375 TfdBGR12 = class(TfdBGR_US3)
1376 constructor Create; override;
1379 TfdBGR16 = class(TfdBGR_US3)
1380 constructor Create; override;
1383 TfdBGRA2 = class(TfdBGRA_UB4)
1384 constructor Create; override;
1387 TfdBGRA4 = class(TfdUniversal_US1)
1388 constructor Create; override;
1391 TfdBGR5A1 = class(TfdUniversal_US1)
1392 constructor Create; override;
1395 TfdBGRA8 = class(TfdBGRA_UB4)
1396 constructor Create; override;
1399 TfdBGR10A2 = class(TfdUniversal_UI1)
1400 constructor Create; override;
1403 TfdBGRA12 = class(TfdBGRA_US4)
1404 constructor Create; override;
1407 TfdBGRA16 = class(TfdBGRA_US4)
1408 constructor Create; override;
1411 TfdDepth16 = class(TfdDepth_US1)
1412 constructor Create; override;
1415 TfdDepth24 = class(TfdDepth_UI1)
1416 constructor Create; override;
1419 TfdDepth32 = class(TfdDepth_UI1)
1420 constructor Create; override;
1423 TfdS3tcDtx1RGBA = class(TFormatDescriptor)
1424 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1425 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1426 constructor Create; override;
1429 TfdS3tcDtx3RGBA = class(TFormatDescriptor)
1430 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1431 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1432 constructor Create; override;
1435 TfdS3tcDtx5RGBA = class(TFormatDescriptor)
1436 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1437 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1438 constructor Create; override;
1441 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1442 TbmpBitfieldFormat = class(TFormatDescriptor)
1444 procedure SetRedMask (const aValue: UInt64);
1445 procedure SetGreenMask(const aValue: UInt64);
1446 procedure SetBlueMask (const aValue: UInt64);
1447 procedure SetAlphaMask(const aValue: UInt64);
1449 procedure Update(aMask: UInt64; out aRange: Cardinal; out aShift: Byte);
1451 property RedMask: UInt64 read GetRedMask write SetRedMask;
1452 property GreenMask: UInt64 read GetGreenMask write SetGreenMask;
1453 property BlueMask: UInt64 read GetBlueMask write SetBlueMask;
1454 property AlphaMask: UInt64 read GetAlphaMask write SetAlphaMask;
1456 property PixelSize: Single read fPixelSize write fPixelSize;
1458 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1459 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1462 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1463 TbmpColorTableEnty = packed record
1466 TbmpColorTable = array of TbmpColorTableEnty;
1467 TbmpColorTableFormat = class(TFormatDescriptor)
1469 fColorTable: TbmpColorTable;
1471 property PixelSize: Single read fPixelSize write fPixelSize;
1472 property ColorTable: TbmpColorTable read fColorTable write fColorTable;
1473 property Range: TglBitmapColorRec read fRange write fRange;
1474 property Shift: TShiftRec read fShift write fShift;
1475 property Format: TglBitmapFormat read fFormat write fFormat;
1477 procedure CreateColorTable;
1479 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
1480 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
1481 destructor Destroy; override;
1485 LUMINANCE_WEIGHT_R = 0.30;
1486 LUMINANCE_WEIGHT_G = 0.59;
1487 LUMINANCE_WEIGHT_B = 0.11;
1489 ALPHA_WEIGHT_R = 0.30;
1490 ALPHA_WEIGHT_G = 0.59;
1491 ALPHA_WEIGHT_B = 0.11;
1493 DEPTH_WEIGHT_R = 0.333333333;
1494 DEPTH_WEIGHT_G = 0.333333333;
1495 DEPTH_WEIGHT_B = 0.333333333;
1497 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1499 FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
1512 TfdLuminance4Alpha4,
1513 TfdLuminance6Alpha2,
1514 TfdLuminance8Alpha8,
1515 TfdLuminance12Alpha4,
1516 TfdLuminance12Alpha12,
1517 TfdLuminance16Alpha16,
1562 FormatDescriptorCS: TCriticalSection;
1563 FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
1565 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1566 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1568 result.Fields := [];
1571 result.Fields := result.Fields + [ffX];
1573 result.Fields := result.Fields + [ffY];
1575 result.X := Max(0, X);
1576 result.Y := Max(0, Y);
1579 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1580 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
1588 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1589 function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
1594 for i := 0 to high(r1.arr) do
1595 if (r1.arr[i] <> r2.arr[i]) then
1600 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1601 function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
1609 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1610 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1619 tfR3G3B2, tfLuminance8,
1622 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
1623 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
1629 tfRGB10, tfRGB10A2, tfRGBA8,
1630 tfBGR10, tfBGR10A2, tfBGRA8]) then
1631 result := result + [ftBMP];
1635 tfLuminance8, tfAlpha8,
1638 tfLuminance16, tfLuminance8Alpha8,
1639 tfRGB5, tfRGB5A1, tfRGBA4,
1640 tfBGR5, tfBGR5A1, tfBGRA4,
1646 tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
1647 result := result + [ftTGA];
1649 //TODO Supported File Formats!
1652 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1654 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1655 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1656 tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
1657 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1658 tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
1659 tfDepth16, tfDepth24, tfDepth32]
1661 result := result + [ftPNG];
1664 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1666 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1667 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1668 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1669 tfDepth16, tfDepth24, tfDepth32]
1671 result := result + [ftJPEG];
1675 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1676 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1677 tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
1678 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1679 tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
1680 tfDepth16, tfDepth24, tfDepth32]
1682 result := result + [ftDDS, ftTGA, ftBMP];
1686 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1687 function IsPowerOfTwo(aNumber: Integer): Boolean;
1689 while (aNumber and 1) = 0 do
1690 aNumber := aNumber shr 1;
1691 result := aNumber = 1;
1694 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1695 function GetTopMostBit(aBitSet: UInt64): Integer;
1698 while aBitSet > 0 do begin
1700 aBitSet := aBitSet shr 1;
1704 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1705 function CountSetBits(aBitSet: UInt64): Integer;
1708 while aBitSet > 0 do begin
1709 if (aBitSet and 1) = 1 then
1711 aBitSet := aBitSet shr 1;
1715 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1716 function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
1719 LUMINANCE_WEIGHT_R * aPixel.Data.r +
1720 LUMINANCE_WEIGHT_G * aPixel.Data.g +
1721 LUMINANCE_WEIGHT_B * aPixel.Data.b);
1724 function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal;
1727 DEPTH_WEIGHT_R * aPixel.Data.r +
1728 DEPTH_WEIGHT_G * aPixel.Data.g +
1729 DEPTH_WEIGHT_B * aPixel.Data.b);
1732 //TODO check _ARB functions and constants
1735 {$IFNDEF GLB_NO_NATIVE_GL}
1736 procedure ReadOpenGLExtensions;
1742 MajorVersion, MinorVersion: Integer;
1745 procedure TrimVersionString(Buffer: AnsiString; var Major, Minor: Integer);
1752 Separator := Pos(AnsiString('.'), Buffer);
1754 if (Separator > 1) and (Separator < Length(Buffer)) and
1755 (Buffer[Separator - 1] in ['0'..'9']) and
1756 (Buffer[Separator + 1] in ['0'..'9']) then begin
1759 while (Separator > 0) and (Buffer[Separator] in ['0'..'9']) do
1762 Delete(Buffer, 1, Separator);
1763 Separator := Pos(AnsiString('.'), Buffer) + 1;
1765 while (Separator <= Length(Buffer)) and (AnsiChar(Buffer[Separator]) in ['0'..'9']) do
1768 Delete(Buffer, Separator, 255);
1769 Separator := Pos(AnsiString('.'), Buffer);
1771 Major := StrToInt(Copy(String(Buffer), 1, Separator - 1));
1772 Minor := StrToInt(Copy(String(Buffer), Separator + 1, 1));
1777 function CheckExtension(const Extension: AnsiString): Boolean;
1781 ExtPos := Pos(Extension, Buffer);
1782 result := ExtPos > 0;
1785 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
1789 function glLoad (aFunc: pAnsiChar): pointer;
1792 result := glXGetProcAddress(aFunc);
1794 result := wglGetProcAddress(aFunc);
1801 Context := wglGetCurrentContext;
1803 if Context <> gLastContext then begin
1804 gLastContext := Context;
1808 Buffer := glGetString(GL_VERSION);
1809 TrimVersionString(Buffer, MajorVersion, MinorVersion);
1811 GL_VERSION_1_2 := false;
1812 GL_VERSION_1_3 := false;
1813 GL_VERSION_1_4 := false;
1814 GL_VERSION_2_0 := false;
1816 if MajorVersion = 1 then begin
1817 if MinorVersion >= 1 then begin
1818 if MinorVersion >= 2 then
1819 GL_VERSION_1_2 := true;
1821 if MinorVersion >= 3 then
1822 GL_VERSION_1_3 := true;
1824 if MinorVersion >= 4 then
1825 GL_VERSION_1_4 := true;
1829 if MajorVersion >= 2 then begin
1830 GL_VERSION_1_2 := true;
1831 GL_VERSION_1_3 := true;
1832 GL_VERSION_1_4 := true;
1833 GL_VERSION_2_0 := true;
1837 Buffer := glGetString(GL_EXTENSIONS);
1838 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
1839 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
1840 GL_ARB_texture_compression := CheckExtension('GL_ARB_texture_compression');
1841 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
1842 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
1843 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
1844 GL_EXT_bgra := CheckExtension('GL_EXT_bgra');
1845 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
1846 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
1847 GL_EXT_texture_compression_s3tc := CheckExtension('GL_EXT_texture_compression_s3tc');
1848 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
1849 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
1850 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
1851 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
1852 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
1855 if GL_VERSION_1_3 then begin
1857 glCompressedTexImage1D := glLoad('glCompressedTexImage1D');
1858 glCompressedTexImage2D := glLoad('glCompressedTexImage2D');
1859 glGetCompressedTexImage := glLoad('glGetCompressedTexImage');
1863 // Try loading Extension
1864 glCompressedTexImage1D := glLoad('glCompressedTexImage1DARB');
1865 glCompressedTexImage2D := glLoad('glCompressedTexImage2DARB');
1866 glGetCompressedTexImage := glLoad('glGetCompressedTexImageARB');
1877 function CreateGrayPalette: HPALETTE;
1882 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
1884 Pal.palVersion := $300;
1885 Pal.palNumEntries := 256;
1888 {$DEFINE GLB_TEMPRANGECHECK}
1892 for Idx := 0 to 256 - 1 do begin
1893 Pal.palPalEntry[Idx].peRed := Idx;
1894 Pal.palPalEntry[Idx].peGreen := Idx;
1895 Pal.palPalEntry[Idx].peBlue := Idx;
1896 Pal.palPalEntry[Idx].peFlags := 0;
1899 {$IFDEF GLB_TEMPRANGECHECK}
1900 {$UNDEF GLB_TEMPRANGECHECK}
1904 result := CreatePalette(Pal^);
1911 (* TODO GLB_SDL_IMAGE
1912 {$IFDEF GLB_SDL_IMAGE}
1913 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
1915 result := TStream(context^.unknown.data1).Seek(offset, whence);
1918 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
1920 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
1923 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
1925 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
1928 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
1933 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
1935 result := SDL_AllocRW;
1937 if result = nil then
1938 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
1940 result^.seek := glBitmapRWseek;
1941 result^.read := glBitmapRWread;
1942 result^.write := glBitmapRWwrite;
1943 result^.close := glBitmapRWclose;
1944 result^.unknown.data1 := Stream;
1950 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
1952 glBitmap: TglBitmap2D;
1958 if Instance = 0 then
1959 Instance := HInstance;
1961 if (LoadFromRes) then
1962 glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName)
1965 glBitmap := TglBitmap2D.Create(FileName);
1968 glBitmap.DeleteTextureOnFree := false;
1969 glBitmap.FreeDataAfterGenTexture := false;
1970 glBitmap.GenTexture(true);
1971 if (glBitmap.ID > 0) then begin
1972 Texture := glBitmap.ID;
1980 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
1982 CM: TglBitmapCubeMap;
1987 if Instance = 0 then
1988 Instance := HInstance;
1991 CM := TglBitmapCubeMap.Create;
1993 CM.DeleteTextureOnFree := false;
1997 if (LoadFromRes) then
1998 CM.LoadFromResource(Instance, PositiveX)
2001 CM.LoadFromFile(PositiveX);
2002 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
2005 if (LoadFromRes) then
2006 CM.LoadFromResource(Instance, NegativeX)
2009 CM.LoadFromFile(NegativeX);
2010 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
2013 if (LoadFromRes) then
2014 CM.LoadFromResource(Instance, PositiveY)
2017 CM.LoadFromFile(PositiveY);
2018 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
2021 if (LoadFromRes) then
2022 CM.LoadFromResource(Instance, NegativeY)
2025 CM.LoadFromFile(NegativeY);
2026 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
2029 if (LoadFromRes) then
2030 CM.LoadFromResource(Instance, PositiveZ)
2033 CM.LoadFromFile(PositiveZ);
2034 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
2037 if (LoadFromRes) then
2038 CM.LoadFromResource(Instance, NegativeZ)
2041 CM.LoadFromFile(NegativeZ);
2042 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
2051 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
2053 NM: TglBitmapNormalMap;
2057 NM := TglBitmapNormalMap.Create;
2059 NM.DeleteTextureOnFree := false;
2060 NM.GenerateNormalMap(Size);
2070 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2071 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
2073 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
2076 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2077 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
2079 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
2082 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2083 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
2085 glBitmapDefaultMipmap := aValue;
2088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2089 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
2091 glBitmapDefaultFormat := aFormat;
2094 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2095 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
2097 glBitmapDefaultFilterMin := aMin;
2098 glBitmapDefaultFilterMag := aMag;
2101 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2102 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
2104 glBitmapDefaultWrapS := S;
2105 glBitmapDefaultWrapT := T;
2106 glBitmapDefaultWrapR := R;
2109 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2110 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2112 result := glBitmapDefaultDeleteTextureOnFree;
2115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2116 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2118 result := glBitmapDefaultFreeDataAfterGenTextures;
2121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2122 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
2124 result := glBitmapDefaultMipmap;
2127 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2128 function glBitmapGetDefaultFormat: TglBitmapFormat;
2130 result := glBitmapDefaultFormat;
2133 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2134 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
2136 aMin := glBitmapDefaultFilterMin;
2137 aMag := glBitmapDefaultFilterMag;
2140 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2141 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
2143 S := glBitmapDefaultWrapS;
2144 T := glBitmapDefaultWrapT;
2145 R := glBitmapDefaultWrapR;
2148 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2149 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2150 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2151 function TFormatDescriptor.GetRedMask: UInt64;
2153 result := fRange.r shl fShift.r;
2156 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2157 function TFormatDescriptor.GetGreenMask: UInt64;
2159 result := fRange.g shl fShift.g;
2162 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2163 function TFormatDescriptor.GetBlueMask: UInt64;
2165 result := fRange.b shl fShift.b;
2168 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2169 function TFormatDescriptor.GetAlphaMask: UInt64;
2171 result := fRange.a shl fShift.a;
2174 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2175 function TFormatDescriptor.GetComponents: Integer;
2181 if (fRange.arr[i] > 0) then
2185 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2186 function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2190 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2191 w := Max(1, aSize.X);
2192 h := Max(1, aSize.Y);
2193 result := GetSize(w, h);
2198 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2199 function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
2202 if (aWidth <= 0) or (aHeight <= 0) then
2204 result := Ceil(aWidth * aHeight * fPixelSize);
2207 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2208 function TFormatDescriptor.CreateMappingData: Pointer;
2213 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2214 procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
2219 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2220 function TFormatDescriptor.IsEmpty: Boolean;
2222 result := (fFormat = tfEmpty);
2225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2226 function TFormatDescriptor.HasAlpha: Boolean;
2228 result := (fRange.a > 0);
2231 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2232 function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean;
2236 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2237 raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
2239 if (aRedMask <> RedMask) then
2241 if (aGreenMask <> GreenMask) then
2243 if (aBlueMask <> BlueMask) then
2245 if (aAlphaMask <> AlphaMask) then
2250 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2251 procedure TFormatDescriptor.PreparePixel(var aPixel: TglBitmapPixelData);
2253 FillChar(aPixel, SizeOf(aPixel), 0);
2254 aPixel.Data := fRange;
2255 aPixel.Range := fRange;
2256 aPixel.Format := fFormat;
2259 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2260 constructor TFormatDescriptor.Create;
2265 fWithAlpha := tfEmpty;
2266 fWithoutAlpha := tfEmpty;
2267 fRGBInverted := tfEmpty;
2268 fUncompressed := tfEmpty;
2270 fIsCompressed := false;
2273 fglInternalFormat := 0;
2276 FillChar(fRange, 0, SizeOf(fRange));
2277 FillChar(fShift, 0, SizeOf(fShift));
2280 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2281 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2282 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2283 procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2285 aData^ := aPixel.Data.a;
2289 procedure TfdAlpha_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2294 aPixel.Data.a := aData^;
2298 constructor TfdAlpha_UB1.Create;
2303 fglFormat := GL_ALPHA;
2304 fglDataFormat := GL_UNSIGNED_BYTE;
2307 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2308 //TfdLuminance_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2309 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2310 procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2312 aData^ := LuminanceWeight(aPixel);
2316 procedure TfdLuminance_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2318 aPixel.Data.r := aData^;
2319 aPixel.Data.g := aData^;
2320 aPixel.Data.b := aData^;
2325 constructor TfdLuminance_UB1.Create;
2332 fglFormat := GL_LUMINANCE;
2333 fglDataFormat := GL_UNSIGNED_BYTE;
2336 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2337 //TfdUniversal_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2338 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2339 procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2345 if (fRange.arr[i] > 0) then
2346 aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2350 procedure TfdUniversal_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2355 aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
2359 constructor TfdUniversal_UB1.Create;
2365 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2366 //TfdLuminanceAlpha_UB2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2367 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2368 procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2370 inherited Map(aPixel, aData, aMapData);
2371 aData^ := aPixel.Data.a;
2375 procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2377 inherited Unmap(aData, aPixel, aMapData);
2378 aPixel.Data.a := aData^;
2382 constructor TfdLuminanceAlpha_UB2.Create;
2388 fglFormat := GL_LUMINANCE_ALPHA;
2389 fglDataFormat := GL_UNSIGNED_BYTE;
2392 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2393 //TfdRGB_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2394 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2395 procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2397 aData^ := aPixel.Data.r;
2399 aData^ := aPixel.Data.g;
2401 aData^ := aPixel.Data.b;
2405 procedure TfdRGB_UB3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2407 aPixel.Data.r := aData^;
2409 aPixel.Data.g := aData^;
2411 aPixel.Data.b := aData^;
2416 constructor TfdRGB_UB3.Create;
2426 fglFormat := GL_RGB;
2427 fglDataFormat := GL_UNSIGNED_BYTE;
2430 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2431 //TfdBGR_UB3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2432 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2433 procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2435 aData^ := aPixel.Data.b;
2437 aData^ := aPixel.Data.g;
2439 aData^ := aPixel.Data.r;
2443 procedure TfdBGR_UB3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2445 aPixel.Data.b := aData^;
2447 aPixel.Data.g := aData^;
2449 aPixel.Data.r := aData^;
2454 constructor TfdBGR_UB3.Create;
2463 fglFormat := GL_BGR;
2464 fglDataFormat := GL_UNSIGNED_BYTE;
2467 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2468 //TdfRGBA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2469 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2470 procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2472 inherited Map(aPixel, aData, aMapData);
2473 aData^ := aPixel.Data.a;
2477 procedure TfdRGBA_UB4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2479 inherited Unmap(aData, aPixel, aMapData);
2480 aPixel.Data.a := aData^;
2484 constructor TfdRGBA_UB4.Create;
2490 fglFormat := GL_RGBA;
2491 fglDataFormat := GL_UNSIGNED_BYTE;
2494 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2495 //TfdBGRA_UB4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2496 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2497 procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2499 inherited Map(aPixel, aData, aMapData);
2500 aData^ := aPixel.Data.a;
2504 procedure TfdBGRA_UB4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2506 inherited Unmap(aData, aPixel, aMapData);
2507 aPixel.Data.a := aData^;
2511 constructor TfdBGRA_UB4.Create;
2517 fglFormat := GL_BGRA;
2518 fglDataFormat := GL_UNSIGNED_BYTE;
2521 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2522 //TfdAlpha_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2523 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2524 procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2526 PWord(aData)^ := aPixel.Data.a;
2530 procedure TfdAlpha_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2535 aPixel.Data.a := PWord(aData)^;
2539 constructor TfdAlpha_US1.Create;
2544 fglFormat := GL_ALPHA;
2545 fglDataFormat := GL_UNSIGNED_SHORT;
2548 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2549 //TfdLuminance_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2550 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2551 procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2553 PWord(aData)^ := LuminanceWeight(aPixel);
2557 procedure TfdLuminance_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2559 aPixel.Data.r := PWord(aData)^;
2560 aPixel.Data.g := PWord(aData)^;
2561 aPixel.Data.b := PWord(aData)^;
2566 constructor TfdLuminance_US1.Create;
2573 fglFormat := GL_LUMINANCE;
2574 fglDataFormat := GL_UNSIGNED_SHORT;
2577 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2578 //TfdUniversal_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2579 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2580 procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2586 if (fRange.arr[i] > 0) then
2587 PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2591 procedure TfdUniversal_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2596 aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2600 constructor TfdUniversal_US1.Create;
2606 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2607 //TfdDepth_US1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2608 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2609 procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2611 PWord(aData)^ := DepthWeight(aPixel);
2615 procedure TfdDepth_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2617 aPixel.Data.r := PWord(aData)^;
2618 aPixel.Data.g := PWord(aData)^;
2619 aPixel.Data.b := PWord(aData)^;
2624 constructor TfdDepth_US1.Create;
2631 fglFormat := GL_DEPTH_COMPONENT;
2632 fglDataFormat := GL_UNSIGNED_SHORT;
2635 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2636 //TfdLuminanceAlpha_US2///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2637 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2638 procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2640 inherited Map(aPixel, aData, aMapData);
2641 PWord(aData)^ := aPixel.Data.a;
2645 procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2647 inherited Unmap(aData, aPixel, aMapData);
2648 aPixel.Data.a := PWord(aData)^;
2652 constructor TfdLuminanceAlpha_US2.Create;
2658 fglFormat := GL_LUMINANCE_ALPHA;
2659 fglDataFormat := GL_UNSIGNED_SHORT;
2662 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2663 //TfdRGB_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2664 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2665 procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2667 PWord(aData)^ := aPixel.Data.r;
2669 PWord(aData)^ := aPixel.Data.g;
2671 PWord(aData)^ := aPixel.Data.b;
2675 procedure TfdRGB_US3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2677 aPixel.Data.r := PWord(aData)^;
2679 aPixel.Data.g := PWord(aData)^;
2681 aPixel.Data.b := PWord(aData)^;
2686 constructor TfdRGB_US3.Create;
2696 fglFormat := GL_RGB;
2697 fglDataFormat := GL_UNSIGNED_SHORT;
2700 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2701 //TfdBGR_US3//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2702 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2703 procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2705 PWord(aData)^ := aPixel.Data.b;
2707 PWord(aData)^ := aPixel.Data.g;
2709 PWord(aData)^ := aPixel.Data.r;
2713 procedure TfdBGR_US3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2715 aPixel.Data.b := PWord(aData)^;
2717 aPixel.Data.g := PWord(aData)^;
2719 aPixel.Data.r := PWord(aData)^;
2724 constructor TfdBGR_US3.Create;
2734 fglFormat := GL_BGR;
2735 fglDataFormat := GL_UNSIGNED_SHORT;
2738 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2739 //TfdRGBA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2740 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2741 procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2743 inherited Map(aPixel, aData, aMapData);
2744 PWord(aData)^ := aPixel.Data.a;
2748 procedure TfdRGBA_US4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2750 inherited Unmap(aData, aPixel, aMapData);
2751 aPixel.Data.a := PWord(aData)^;
2755 constructor TfdRGBA_US4.Create;
2761 fglFormat := GL_RGBA;
2762 fglDataFormat := GL_UNSIGNED_SHORT;
2765 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2766 //TfdBGRA_US4/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2767 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2768 procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2770 inherited Map(aPixel, aData, aMapData);
2771 PWord(aData)^ := aPixel.Data.a;
2775 procedure TfdBGRA_US4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2777 inherited Unmap(aData, aPixel, aMapData);
2778 aPixel.Data.a := PWord(aData)^;
2782 constructor TfdBGRA_US4.Create;
2788 fglFormat := GL_BGRA;
2789 fglDataFormat := GL_UNSIGNED_SHORT;
2792 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2793 //TfdUniversal_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2794 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2795 procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2799 PCardinal(aData)^ := 0;
2801 if (fRange.arr[i] > 0) then
2802 PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
2806 procedure TfdUniversal_UI1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2811 aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
2815 constructor TfdUniversal_UI1.Create;
2821 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2822 //TfdDepth_UI1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2823 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2824 procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
2826 PCardinal(aData)^ := DepthWeight(aPixel);
2830 procedure TfdDepth_UI1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
2832 aPixel.Data.r := PCardinal(aData)^;
2833 aPixel.Data.g := PCardinal(aData)^;
2834 aPixel.Data.b := PCardinal(aData)^;
2839 constructor TfdDepth_UI1.Create;
2843 fRange.r := $FFFFFFFF;
2844 fRange.g := $FFFFFFFF;
2845 fRange.b := $FFFFFFFF;
2846 fglFormat := GL_DEPTH_COMPONENT;
2847 fglDataFormat := GL_UNSIGNED_INT;
2850 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2851 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2852 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2853 constructor TfdAlpha4.Create;
2856 fFormat := tfAlpha4;
2857 fWithAlpha := tfAlpha4;
2858 fglInternalFormat := GL_ALPHA4;
2861 constructor TfdAlpha8.Create;
2864 fFormat := tfAlpha8;
2865 fWithAlpha := tfAlpha8;
2866 fglInternalFormat := GL_ALPHA8;
2869 constructor TfdAlpha12.Create;
2872 fFormat := tfAlpha12;
2873 fWithAlpha := tfAlpha12;
2874 fglInternalFormat := GL_ALPHA12;
2877 constructor TfdAlpha16.Create;
2880 fFormat := tfAlpha16;
2881 fWithAlpha := tfAlpha16;
2882 fglInternalFormat := GL_ALPHA16;
2885 constructor TfdLuminance4.Create;
2888 fFormat := tfLuminance4;
2889 fWithAlpha := tfLuminance4Alpha4;
2890 fWithoutAlpha := tfLuminance4;
2891 fglInternalFormat := GL_LUMINANCE4;
2894 constructor TfdLuminance8.Create;
2897 fFormat := tfLuminance8;
2898 fWithAlpha := tfLuminance8Alpha8;
2899 fWithoutAlpha := tfLuminance8;
2900 fglInternalFormat := GL_LUMINANCE8;
2903 constructor TfdLuminance12.Create;
2906 fFormat := tfLuminance12;
2907 fWithAlpha := tfLuminance12Alpha12;
2908 fWithoutAlpha := tfLuminance12;
2909 fglInternalFormat := GL_LUMINANCE12;
2912 constructor TfdLuminance16.Create;
2915 fFormat := tfLuminance16;
2916 fWithAlpha := tfLuminance16Alpha16;
2917 fWithoutAlpha := tfLuminance16;
2918 fglInternalFormat := GL_LUMINANCE16;
2921 constructor TfdLuminance4Alpha4.Create;
2924 fFormat := tfLuminance4Alpha4;
2925 fWithAlpha := tfLuminance4Alpha4;
2926 fWithoutAlpha := tfLuminance4;
2927 fglInternalFormat := GL_LUMINANCE4_ALPHA4;
2930 constructor TfdLuminance6Alpha2.Create;
2933 fFormat := tfLuminance6Alpha2;
2934 fWithAlpha := tfLuminance6Alpha2;
2935 fWithoutAlpha := tfLuminance8;
2936 fglInternalFormat := GL_LUMINANCE6_ALPHA2;
2939 constructor TfdLuminance8Alpha8.Create;
2942 fFormat := tfLuminance8Alpha8;
2943 fWithAlpha := tfLuminance8Alpha8;
2944 fWithoutAlpha := tfLuminance8;
2945 fglInternalFormat := GL_LUMINANCE8_ALPHA8;
2948 constructor TfdLuminance12Alpha4.Create;
2951 fFormat := tfLuminance12Alpha4;
2952 fWithAlpha := tfLuminance12Alpha4;
2953 fWithoutAlpha := tfLuminance12;
2954 fglInternalFormat := GL_LUMINANCE12_ALPHA4;
2957 constructor TfdLuminance12Alpha12.Create;
2960 fFormat := tfLuminance12Alpha12;
2961 fWithAlpha := tfLuminance12Alpha12;
2962 fWithoutAlpha := tfLuminance12;
2963 fglInternalFormat := GL_LUMINANCE12_ALPHA12;
2966 constructor TfdLuminance16Alpha16.Create;
2969 fFormat := tfLuminance16Alpha16;
2970 fWithAlpha := tfLuminance16Alpha16;
2971 fWithoutAlpha := tfLuminance16;
2972 fglInternalFormat := GL_LUMINANCE16_ALPHA16;
2975 constructor TfdR3G3B2.Create;
2978 fFormat := tfR3G3B2;
2979 fWithAlpha := tfRGBA2;
2980 fWithoutAlpha := tfR3G3B2;
2987 fglFormat := GL_RGB;
2988 fglInternalFormat := GL_R3_G3_B2;
2989 fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV;
2992 constructor TfdRGB4.Create;
2996 fWithAlpha := tfRGBA4;
2997 fWithoutAlpha := tfRGB4;
2998 fRGBInverted := tfBGR4;
3005 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3006 fglInternalFormat := GL_RGB4;
3007 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3010 constructor TfdR5G6B5.Create;
3013 fFormat := tfR5G6B5;
3014 fWithAlpha := tfRGBA4;
3015 fWithoutAlpha := tfR5G6B5;
3016 fRGBInverted := tfB5G6R5;
3023 fglFormat := GL_RGB;
3024 fglInternalFormat := GL_RGB565;
3025 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV;
3028 constructor TfdRGB5.Create;
3032 fWithAlpha := tfRGB5A1;
3033 fWithoutAlpha := tfRGB5;
3034 fRGBInverted := tfBGR5;
3041 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3042 fglInternalFormat := GL_RGB5;
3043 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3046 constructor TfdRGB8.Create;
3050 fWithAlpha := tfRGBA8;
3051 fWithoutAlpha := tfRGB8;
3052 fRGBInverted := tfBGR8;
3053 fglInternalFormat := GL_RGB8;
3056 constructor TfdRGB10.Create;
3060 fWithAlpha := tfRGB10A2;
3061 fWithoutAlpha := tfRGB10;
3062 fRGBInverted := tfBGR10;
3069 fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3070 fglInternalFormat := GL_RGB10;
3071 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3074 constructor TfdRGB12.Create;
3078 fWithAlpha := tfRGBA12;
3079 fWithoutAlpha := tfRGB12;
3080 fRGBInverted := tfBGR12;
3081 fglInternalFormat := GL_RGB12;
3084 constructor TfdRGB16.Create;
3088 fWithAlpha := tfRGBA16;
3089 fWithoutAlpha := tfRGB16;
3090 fRGBInverted := tfBGR16;
3091 fglInternalFormat := GL_RGB16;
3094 constructor TfdRGBA2.Create;
3098 fWithAlpha := tfRGBA2;
3099 fWithoutAlpha := tfR3G3B2;
3100 fRGBInverted := tfBGRA2;
3101 fglInternalFormat := GL_RGBA2;
3104 constructor TfdRGBA4.Create;
3108 fWithAlpha := tfRGBA4;
3109 fWithoutAlpha := tfRGB4;
3110 fRGBInverted := tfBGRA4;
3119 fglFormat := GL_RGBA;
3120 fglInternalFormat := GL_RGBA4;
3121 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3124 constructor TfdRGB5A1.Create;
3127 fFormat := tfRGB5A1;
3128 fWithAlpha := tfRGB5A1;
3129 fWithoutAlpha := tfRGB5;
3130 fRGBInverted := tfBGR5A1;
3139 fglFormat := GL_RGBA;
3140 fglInternalFormat := GL_RGB5_A1;
3141 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3144 constructor TfdRGBA8.Create;
3148 fWithAlpha := tfRGBA8;
3149 fWithoutAlpha := tfRGB8;
3150 fRGBInverted := tfBGRA8;
3151 fglInternalFormat := GL_RGBA8;
3154 constructor TfdRGB10A2.Create;
3157 fFormat := tfRGB10A2;
3158 fWithAlpha := tfRGB10A2;
3159 fWithoutAlpha := tfRGB10;
3160 fRGBInverted := tfBGR10A2;
3169 fglFormat := GL_RGBA;
3170 fglInternalFormat := GL_RGB10_A2;
3171 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3174 constructor TfdRGBA12.Create;
3177 fFormat := tfRGBA12;
3178 fWithAlpha := tfRGBA12;
3179 fWithoutAlpha := tfRGB12;
3180 fRGBInverted := tfBGRA12;
3181 fglInternalFormat := GL_RGBA12;
3184 constructor TfdRGBA16.Create;
3187 fFormat := tfRGBA16;
3188 fWithAlpha := tfRGBA16;
3189 fWithoutAlpha := tfRGB16;
3190 fRGBInverted := tfBGRA16;
3191 fglInternalFormat := GL_RGBA16;
3194 constructor TfdBGR4.Create;
3199 fWithAlpha := tfBGRA4;
3200 fWithoutAlpha := tfBGR4;
3201 fRGBInverted := tfRGB4;
3210 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3211 fglInternalFormat := GL_RGB4;
3212 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3217 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3218 constructor TfdB5G6R5.Create;
3221 fFormat := tfB5G6R5;
3222 fWithAlpha := tfBGRA4;
3223 fWithoutAlpha := tfB5G6R5;
3224 fRGBInverted := tfR5G6B5;
3231 fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat
3232 fglInternalFormat := GL_RGB8;
3233 fglDataFormat := GL_UNSIGNED_SHORT_5_6_5;
3236 constructor TfdBGR5.Create;
3241 fWithAlpha := tfBGR5A1;
3242 fWithoutAlpha := tfBGR5;
3243 fRGBInverted := tfRGB5;
3252 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3253 fglInternalFormat := GL_RGB5;
3254 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3257 constructor TfdBGR8.Create;
3261 fWithAlpha := tfBGRA8;
3262 fWithoutAlpha := tfBGR8;
3263 fRGBInverted := tfRGB8;
3264 fglInternalFormat := GL_RGB8;
3267 constructor TfdBGR10.Create;
3271 fWithAlpha := tfBGR10A2;
3272 fWithoutAlpha := tfBGR10;
3273 fRGBInverted := tfRGB10;
3282 fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
3283 fglInternalFormat := GL_RGB10;
3284 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3287 constructor TfdBGR12.Create;
3291 fWithAlpha := tfBGRA12;
3292 fWithoutAlpha := tfBGR12;
3293 fRGBInverted := tfRGB12;
3294 fglInternalFormat := GL_RGB12;
3297 constructor TfdBGR16.Create;
3301 fWithAlpha := tfBGRA16;
3302 fWithoutAlpha := tfBGR16;
3303 fRGBInverted := tfRGB16;
3304 fglInternalFormat := GL_RGB16;
3307 constructor TfdBGRA2.Create;
3311 fWithAlpha := tfBGRA4;
3312 fWithoutAlpha := tfBGR4;
3313 fRGBInverted := tfRGBA2;
3314 fglInternalFormat := GL_RGBA2;
3317 constructor TfdBGRA4.Create;
3321 fWithAlpha := tfBGRA4;
3322 fWithoutAlpha := tfBGR4;
3323 fRGBInverted := tfRGBA4;
3332 fglFormat := GL_BGRA;
3333 fglInternalFormat := GL_RGBA4;
3334 fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV;
3337 constructor TfdBGR5A1.Create;
3340 fFormat := tfBGR5A1;
3341 fWithAlpha := tfBGR5A1;
3342 fWithoutAlpha := tfBGR5;
3343 fRGBInverted := tfRGB5A1;
3352 fglFormat := GL_BGRA;
3353 fglInternalFormat := GL_RGB5_A1;
3354 fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV;
3357 constructor TfdBGRA8.Create;
3361 fWithAlpha := tfBGRA8;
3362 fWithoutAlpha := tfBGR8;
3363 fRGBInverted := tfRGBA8;
3364 fglInternalFormat := GL_RGBA8;
3367 constructor TfdBGR10A2.Create;
3370 fFormat := tfBGR10A2;
3371 fWithAlpha := tfBGR10A2;
3372 fWithoutAlpha := tfBGR10;
3373 fRGBInverted := tfRGB10A2;
3382 fglFormat := GL_BGRA;
3383 fglInternalFormat := GL_RGB10_A2;
3384 fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV;
3387 constructor TfdBGRA12.Create;
3390 fFormat := tfBGRA12;
3391 fWithAlpha := tfBGRA12;
3392 fWithoutAlpha := tfBGR12;
3393 fRGBInverted := tfRGBA12;
3394 fglInternalFormat := GL_RGBA12;
3397 constructor TfdBGRA16.Create;
3400 fFormat := tfBGRA16;
3401 fWithAlpha := tfBGRA16;
3402 fWithoutAlpha := tfBGR16;
3403 fRGBInverted := tfRGBA16;
3404 fglInternalFormat := GL_RGBA16;
3407 constructor TfdDepth16.Create;
3410 fFormat := tfDepth16;
3411 fWithAlpha := tfEmpty;
3412 fWithoutAlpha := tfDepth16;
3413 fglInternalFormat := GL_DEPTH_COMPONENT16;
3416 constructor TfdDepth24.Create;
3419 fFormat := tfDepth24;
3420 fWithAlpha := tfEmpty;
3421 fWithoutAlpha := tfDepth24;
3422 fglInternalFormat := GL_DEPTH_COMPONENT24;
3425 constructor TfdDepth32.Create;
3428 fFormat := tfDepth32;
3429 fWithAlpha := tfEmpty;
3430 fWithoutAlpha := tfDepth32;
3431 fglInternalFormat := GL_DEPTH_COMPONENT32;
3434 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3435 //TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3436 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3437 procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3439 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3442 procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
3444 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3447 constructor TfdS3tcDtx1RGBA.Create;
3450 fFormat := tfS3tcDtx1RGBA;
3451 fWithAlpha := tfS3tcDtx1RGBA;
3452 fUncompressed := tfRGB5A1;
3454 fIsCompressed := true;
3455 fglFormat := GL_COMPRESSED_RGBA;
3456 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
3457 fglDataFormat := GL_UNSIGNED_BYTE;
3460 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3461 //TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3462 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3463 procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3465 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3468 procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
3470 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3473 constructor TfdS3tcDtx3RGBA.Create;
3476 fFormat := tfS3tcDtx3RGBA;
3477 fWithAlpha := tfS3tcDtx3RGBA;
3478 fUncompressed := tfRGBA8;
3480 fIsCompressed := true;
3481 fglFormat := GL_COMPRESSED_RGBA;
3482 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
3483 fglDataFormat := GL_UNSIGNED_BYTE;
3486 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3487 //TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3488 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3489 procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3491 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3494 procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
3496 raise EglBitmapException.Create('mapping for compressed formats is not supported');
3499 constructor TfdS3tcDtx5RGBA.Create;
3502 fFormat := tfS3tcDtx3RGBA;
3503 fWithAlpha := tfS3tcDtx3RGBA;
3504 fUncompressed := tfRGBA8;
3506 fIsCompressed := true;
3507 fglFormat := GL_COMPRESSED_RGBA;
3508 fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
3509 fglDataFormat := GL_UNSIGNED_BYTE;
3512 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3513 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3514 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3515 class procedure TFormatDescriptor.Init;
3517 if not Assigned(FormatDescriptorCS) then
3518 FormatDescriptorCS := TCriticalSection.Create;
3521 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3522 class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
3524 FormatDescriptorCS.Enter;
3526 result := FormatDescriptors[aFormat];
3527 if not Assigned(result) then begin
3528 result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
3529 FormatDescriptors[aFormat] := result;
3532 FormatDescriptorCS.Leave;
3536 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3537 class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
3539 result := Get(Get(aFormat).WithAlpha);
3542 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3543 class procedure TFormatDescriptor.Clear;
3547 FormatDescriptorCS.Enter;
3549 for f := low(FormatDescriptors) to high(FormatDescriptors) do
3550 FreeAndNil(FormatDescriptors[f]);
3552 FormatDescriptorCS.Leave;
3556 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3557 class procedure TFormatDescriptor.Finalize;
3560 FreeAndNil(FormatDescriptorCS);
3563 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3564 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3565 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3566 procedure TbmpBitfieldFormat.SetRedMask(const aValue: UInt64);
3568 Update(aValue, fRange.r, fShift.r);
3571 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3572 procedure TbmpBitfieldFormat.SetGreenMask(const aValue: UInt64);
3574 Update(aValue, fRange.g, fShift.g);
3577 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3578 procedure TbmpBitfieldFormat.SetBlueMask(const aValue: UInt64);
3580 Update(aValue, fRange.b, fShift.b);
3583 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3584 procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: UInt64);
3586 Update(aValue, fRange.a, fShift.a);
3589 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3590 procedure TbmpBitfieldFormat.Update(aMask: UInt64; out aRange: Cardinal; out
3597 while (aMask > 0) and ((aMask and 1) = 0) do begin
3599 aMask := aMask shr 1;
3602 while (aMask > 0) do begin
3603 aRange := aRange shl 1;
3604 aMask := aMask shr 1;
3608 fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
3611 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3612 procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3620 ((aPixel.Data.r and fRange.r) shl fShift.r) or
3621 ((aPixel.Data.g and fRange.g) shl fShift.g) or
3622 ((aPixel.Data.b and fRange.b) shl fShift.b) or
3623 ((aPixel.Data.a and fRange.a) shl fShift.a);
3624 s := Round(fPixelSize);
3627 2: PWord(aData)^ := data;
3628 4: PCardinal(aData)^ := data;
3629 8: PUInt64(aData)^ := data;
3631 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3636 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3637 procedure TbmpBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
3644 s := Round(fPixelSize);
3647 2: data := PWord(aData)^;
3648 4: data := PCardinal(aData)^;
3649 8: data := PUInt64(aData)^;
3651 raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
3654 aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
3658 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3659 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3660 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3661 procedure TbmpColorTableFormat.CreateColorTable;
3667 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3668 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3670 if (Format = tfLuminance4) then
3671 SetLength(fColorTable, 16)
3673 SetLength(fColorTable, 256);
3677 for i := 0 to High(fColorTable) do begin
3678 fColorTable[i].r := 16 * i;
3679 fColorTable[i].g := 16 * i;
3680 fColorTable[i].b := 16 * i;
3681 fColorTable[i].a := 0;
3686 for i := 0 to High(fColorTable) do begin
3687 fColorTable[i].r := i;
3688 fColorTable[i].g := i;
3689 fColorTable[i].b := i;
3690 fColorTable[i].a := 0;
3695 for i := 0 to High(fColorTable) do begin
3696 fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
3697 fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
3698 fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
3699 fColorTable[i].a := 0;
3705 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3706 procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
3710 if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
3711 raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
3715 if (aMapData = nil) then
3717 d := LuminanceWeight(aPixel) and Range.r;
3718 aData^ := aData^ or (d shl (4 - PtrInt(aMapData)));
3720 if (PtrInt(aMapData) >= 8) then begin
3727 aData^ := LuminanceWeight(aPixel) and Range.r;
3733 ((aPixel.Data.r and Range.r) shl Shift.r) or
3734 ((aPixel.Data.g and Range.g) shl Shift.g) or
3735 ((aPixel.Data.b and Range.b) shl Shift.b));
3741 procedure TbmpColorTableFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
3750 s := Trunc(fPixelSize);
3751 f := fPixelSize - s;
3752 bits := Round(8 * f);
3754 0: idx := (aData^ shr (8 - bits - PtrInt(aMapData))) and ((1 shl bits) - 1);
3756 2: idx := PWord(aData)^;
3757 4: idx := PCardinal(aData)^;
3758 8: idx := PUInt64(aData)^;
3760 raise EglBitmapException.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
3762 if (idx >= Length(fColorTable)) then
3763 raise EglBitmapException.CreateFmt('invalid color index: %d', [idx]);
3764 with fColorTable[idx] do begin
3770 inc(aMapData, bits);
3771 if (PtrInt(aMapData) >= 8) then begin
3778 destructor TbmpColorTableFormat.Destroy;
3780 SetLength(fColorTable, 0);
3784 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3785 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3786 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3787 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
3789 with aFuncRec do begin
3790 if (Source.Range.r > 0) then
3791 Dest.Data.r := Source.Data.r;
3792 if (Source.Range.g > 0) then
3793 Dest.Data.g := Source.Data.g;
3794 if (Source.Range.b > 0) then
3795 Dest.Data.b := Source.Data.b;
3796 if (Source.Range.a > 0) then
3797 Dest.Data.a := Source.Data.a;
3801 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3802 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3806 with aFuncRec do begin
3808 if (Source.Range.arr[i] > 0) then
3809 Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
3814 TShiftData = packed record
3816 0: (r, g, b, a: SmallInt);
3817 1: (arr: array[0..3] of SmallInt);
3819 PShiftData = ^TShiftData;
3821 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3822 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
3828 if (Source.Range.arr[i] > 0) then
3829 Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
3832 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3833 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
3835 with aFuncRec do begin
3836 Dest.Data.r := Source.Data.r;
3837 Dest.Data.g := Source.Data.g;
3838 Dest.Data.b := Source.Data.b;
3839 Dest.Data.a := Source.Data.a;
3840 if (Args and $1 > 0) then begin
3841 Dest.Data.r := Dest.Data.r xor Dest.Range.r;
3842 Dest.Data.g := Dest.Data.g xor Dest.Range.g;
3843 Dest.Data.b := Dest.Data.b xor Dest.Range.b;
3845 if (Args and $2 > 0) then begin
3846 Dest.Data.a := Dest.Data.a xor Dest.Range.a;
3851 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3852 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
3856 with aFuncRec do begin
3858 Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
3862 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3863 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3867 with FuncRec do begin
3868 if (FuncRec.Args = 0) then begin //source has no alpha
3870 Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
3871 Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
3872 Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
3873 Dest.Data.a := Round(Dest.Range.a * Temp);
3875 Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
3879 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3880 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3882 PglBitmapPixelData = ^TglBitmapPixelData;
3884 with FuncRec do begin
3885 Dest.Data.r := Source.Data.r;
3886 Dest.Data.g := Source.Data.g;
3887 Dest.Data.b := Source.Data.b;
3889 with PglBitmapPixelData(Args)^ do
3890 if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
3891 (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
3892 (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
3895 Dest.Data.a := Dest.Range.a;
3899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3900 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3902 PglBitmapPixelData = ^TglBitmapPixelData;
3904 with FuncRec do begin
3905 Dest.Data.r := Source.Data.r;
3906 Dest.Data.g := Source.Data.g;
3907 Dest.Data.b := Source.Data.b;
3908 Dest.Data.a := PCardinal(Args)^;
3912 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3913 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
3916 TRGBPix = array [0..2] of byte;
3920 while aWidth > 0 do begin
3921 Temp := PRGBPix(aData)^[0];
3922 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
3923 PRGBPix(aData)^[2] := Temp;
3933 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3934 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3935 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3936 function TglBitmap.GetWidth: Integer;
3938 if (ffX in fDimension.Fields) then
3939 result := fDimension.X
3944 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3945 function TglBitmap.GetHeight: Integer;
3947 if (ffY in fDimension.Fields) then
3948 result := fDimension.Y
3953 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3954 function TglBitmap.GetFileWidth: Integer;
3956 result := Max(1, Width);
3959 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3960 function TglBitmap.GetFileHeight: Integer;
3962 result := Max(1, Height);
3965 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3966 procedure TglBitmap.SetCustomData(const aValue: Pointer);
3968 if fCustomData = aValue then
3970 fCustomData := aValue;
3973 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3974 procedure TglBitmap.SetCustomName(const aValue: String);
3976 if fCustomName = aValue then
3978 fCustomName := aValue;
3981 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3982 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
3984 if fCustomNameW = aValue then
3986 fCustomNameW := aValue;
3989 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3990 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
3992 if fDeleteTextureOnFree = aValue then
3994 fDeleteTextureOnFree := aValue;
3997 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3998 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4000 if fFormat = aValue then
4002 if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
4003 raise EglBitmapUnsupportedFormatFormat.Create('SetInternalFormat - ' + UNSUPPORTED_FORMAT);
4004 SetDataPointer(Data, aValue, Width, Height);
4007 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4008 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4010 if fFreeDataAfterGenTexture = aValue then
4012 fFreeDataAfterGenTexture := aValue;
4015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4016 procedure TglBitmap.SetID(const aValue: Cardinal);
4018 if fID = aValue then
4023 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4024 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4026 if fMipMap = aValue then
4031 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4032 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4034 if fTarget = aValue then
4039 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4040 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
4042 MaxAnisotropic: Integer;
4044 fAnisotropic := aValue;
4045 if (ID > 0) then begin
4046 if GL_EXT_texture_filter_anisotropic then begin
4047 if fAnisotropic > 0 then begin
4049 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
4050 if aValue > MaxAnisotropic then
4051 fAnisotropic := MaxAnisotropic;
4052 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
4060 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4061 procedure TglBitmap.CreateID;
4064 glDeleteTextures(1, @fID);
4065 glGenTextures(1, @fID);
4069 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4070 procedure TglBitmap.SetupParameters(var aBuildWithGlu: Boolean);
4072 // Set Up Parameters
4073 SetWrap(fWrapS, fWrapT, fWrapR);
4074 SetFilter(fFilterMin, fFilterMag);
4075 SetAnisotropic(fAnisotropic);
4076 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
4078 // Mip Maps Generation Mode
4079 aBuildWithGlu := false;
4080 if (MipMap = mmMipmap) then begin
4081 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
4082 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
4084 aBuildWithGlu := true;
4085 end else if (MipMap = mmMipmapGlu) then
4086 aBuildWithGlu := true;
4089 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4090 procedure TglBitmap.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
4091 const aWidth: Integer; const aHeight: Integer);
4095 if (Data <> aData) then begin
4096 if (Assigned(Data)) then
4101 FillChar(fDimension, SizeOf(fDimension), 0);
4102 if not Assigned(fData) then begin
4107 if aWidth <> -1 then begin
4108 fDimension.Fields := fDimension.Fields + [ffX];
4109 fDimension.X := aWidth;
4112 if aHeight <> -1 then begin
4113 fDimension.Fields := fDimension.Fields + [ffY];
4114 fDimension.Y := aHeight;
4117 s := TFormatDescriptor.Get(aFormat).PixelSize;
4119 fPixelSize := Ceil(s);
4120 fRowSize := Ceil(s * aWidth);
4124 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4125 function TglBitmap.FlipHorz: Boolean;
4130 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4131 function TglBitmap.FlipVert: Boolean;
4136 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4137 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4138 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4139 procedure TglBitmap.AfterConstruction;
4141 inherited AfterConstruction;
4145 fIsResident := false;
4147 fFormat := glBitmapGetDefaultFormat;
4148 fMipMap := glBitmapDefaultMipmap;
4149 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
4150 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
4152 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
4153 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
4156 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4157 procedure TglBitmap.BeforeDestruction;
4159 SetDataPointer(nil, tfEmpty);
4160 if (fID > 0) and fDeleteTextureOnFree then
4161 glDeleteTextures(1, @fID);
4162 inherited BeforeDestruction;
4165 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4166 procedure TglBitmap.LoadFromFile(const aFilename: String);
4170 if not FileExists(aFilename) then
4171 raise EglBitmapException.Create('file does not exist: ' + aFilename);
4172 fFilename := aFilename;
4173 fs := TFileStream.Create(fFilename, fmOpenRead);
4182 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4183 procedure TglBitmap.LoadFromStream(const aStream: TStream);
4185 {$IFDEF GLB_SUPPORT_PNG_READ}
4186 if not LoadPNG(aStream) then
4188 {$IFDEF GLB_SUPPORT_JPEG_READ}
4189 if not LoadJPEG(aStream) then
4191 if not LoadDDS(aStream) then
4192 if not LoadTGA(aStream) then
4193 if not LoadBMP(aStream) then
4194 raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
4197 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4198 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
4199 const aFormat: TglBitmapFormat; const aArgs: PtrInt);
4204 size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
4205 GetMem(tmpData, size);
4207 FillChar(tmpData^, size, #$FF);
4208 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y);
4213 AddFunc(Self, aFunc, false, Format, aArgs);
4217 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4218 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
4220 rs: TResourceStream;
4225 if not Assigned(ResType) then begin
4226 TempPos := Pos('.', Resource);
4227 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
4228 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
4229 TempResType := PChar(ResTypeStr);
4231 TempResType := ResType
4233 rs := TResourceStream.Create(Instance, Resource, TempResType);
4241 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4242 procedure TglBitmap.LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4244 rs: TResourceStream;
4246 rs := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
4255 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4256 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
4260 fs := TFileStream.Create(aFileName, fmCreate);
4263 SaveToStream(fs, aFileType);
4269 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4270 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
4273 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4274 ftPNG: SavePng(aStream);
4276 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4277 ftJPEG: SaveJPEG(aStream);
4279 ftDDS: SaveDDS(aStream);
4280 ftTGA: SaveTGA(aStream);
4281 ftBMP: SaveBMP(aStream);
4285 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4286 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt): Boolean;
4288 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
4291 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4292 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
4293 const aFormat: TglBitmapFormat; const aArgs: PtrInt): Boolean;
4295 DestData, TmpData, SourceData: pByte;
4296 TempHeight, TempWidth: Integer;
4297 SourceFD, DestFD: TFormatDescriptor;
4298 SourceMD, DestMD: Pointer;
4300 FuncRec: TglBitmapFunctionRec;
4302 Assert(Assigned(Data));
4303 Assert(Assigned(aSource));
4304 Assert(Assigned(aSource.Data));
4307 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
4308 SourceFD := TFormatDescriptor.Get(aSource.Format);
4309 DestFD := TFormatDescriptor.Get(aFormat);
4311 // inkompatible Formats so CreateTemp
4312 if (SourceFD.PixelSize <> DestFD.PixelSize) then
4313 aCreateTemp := true;
4316 TempHeight := Max(1, aSource.Height);
4317 TempWidth := Max(1, aSource.Width);
4319 FuncRec.Sender := Self;
4320 FuncRec.Args := aArgs;
4323 if aCreateTemp then begin
4324 GetMem(TmpData, TFormatDescriptor.Get(aFormat).GetSize(TempWidth, TempHeight));
4325 DestData := TmpData;
4330 SourceFD.PreparePixel(FuncRec.Source);
4331 DestFD.PreparePixel (FuncRec.Dest);
4333 SourceMD := SourceFD.CreateMappingData;
4334 DestMD := DestFD.CreateMappingData;
4336 FuncRec.Size := aSource.Dimension;
4337 FuncRec.Position.Fields := FuncRec.Size.Fields;
4340 SourceData := aSource.Data;
4341 FuncRec.Position.Y := 0;
4342 while FuncRec.Position.Y < TempHeight do begin
4343 FuncRec.Position.X := 0;
4344 while FuncRec.Position.X < TempWidth do begin
4345 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4347 DestFD.Map(FuncRec.Dest, DestData, DestMD);
4348 inc(FuncRec.Position.X);
4350 inc(FuncRec.Position.Y);
4353 // Updating Image or InternalFormat
4355 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height)
4356 else if (aFormat <> fFormat) then
4361 SourceFD.FreeMappingData(SourceMD);
4362 DestFD.FreeMappingData(DestMD);
4373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4374 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
4376 Row, RowSize: Integer;
4377 SourceData, TmpData: PByte;
4379 Pix: TglBitmapPixelData;
4380 FormatDesc: TglBitmapFormatDescriptor;
4382 function GetRowPointer(Row: Integer): pByte;
4384 result := Surface.pixels;
4385 Inc(result, Row * RowSize);
4392 if not FormatIsUncompressed(InternalFormat) then
4393 raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
4396 FormatDesc := FORMAT_DESCRIPTORS[Format];
4397 if Assigned(Data) then begin
4398 case Trunc(FormatDesc.GetSize) of
4404 raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
4406 FormatDesc.PreparePixel(Pix);
4407 with Pix.PixelDesc do
4408 Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
4409 RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift);
4412 RowSize := Ceil(FileWidth * FormatDesc.GetSize);
4414 for Row := 0 to FileHeight -1 do begin
4415 TmpData := GetRowPointer(Row);
4416 if Assigned(TmpData) then begin
4417 Move(SourceData^, TmpData^, RowSize);
4418 inc(SourceData, RowSize);
4425 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4426 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
4428 pSource, pData, pTempData: PByte;
4429 Row, RowSize, TempWidth, TempHeight: Integer;
4430 IntFormat, f: TglBitmapInternalFormat;
4431 FormatDesc: TglBitmapFormatDescriptor;
4433 function GetRowPointer(Row: Integer): pByte;
4435 result := Surface^.pixels;
4436 Inc(result, Row * RowSize);
4441 if (Assigned(Surface)) then begin
4442 with Surface^.format^ do begin
4443 IntFormat := tfEmpty;
4444 for f := Low(f) to High(f) do begin
4445 if FORMAT_DESCRIPTORS[f].MaskMatch(RMask, GMask, BMask, AMask) then begin
4450 if (IntFormat = tfEmpty) then
4451 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
4454 FormatDesc := FORMAT_DESCRIPTORS[IntFormat];
4455 TempWidth := Surface^.w;
4456 TempHeight := Surface^.h;
4457 RowSize := Trunc(TempWidth * FormatDesc.GetSize);
4458 GetMem(pData, TempHeight * RowSize);
4461 for Row := 0 to TempHeight -1 do begin
4462 pSource := GetRowPointer(Row);
4463 if (Assigned(pSource)) then begin
4464 Move(pSource^, pTempData^, RowSize);
4465 Inc(pTempData, RowSize);
4468 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
4477 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4478 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
4480 Row, Col, AlphaInterleave: Integer;
4481 pSource, pDest: PByte;
4483 function GetRowPointer(Row: Integer): pByte;
4485 result := aSurface.pixels;
4486 Inc(result, Row * Width);
4491 if Assigned(Data) then begin
4492 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
4493 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
4495 AlphaInterleave := 0;
4498 AlphaInterleave := 1;
4500 AlphaInterleave := 3;
4504 for Row := 0 to Height -1 do begin
4505 pDest := GetRowPointer(Row);
4506 if Assigned(pDest) then begin
4507 for Col := 0 to Width -1 do begin
4508 Inc(pSource, AlphaInterleave);
4520 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4521 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4525 bmp := TglBitmap2D.Create;
4527 bmp.AssignFromSurface(Surface);
4528 result := AddAlphaFromGlBitmap(bmp, Func, CustomData);
4536 //TODO rework & test
4537 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4538 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
4541 pSource, pData: PByte;
4544 if Assigned(Data) then begin
4545 if Assigned(aBitmap) then begin
4546 aBitmap.Width := Width;
4547 aBitmap.Height := Height;
4550 tfAlpha8, ifLuminance, ifDepth8:
4552 Bitmap.PixelFormat := pf8bit;
4553 Bitmap.Palette := CreateGrayPalette;
4556 Bitmap.PixelFormat := pf15bit;
4558 Bitmap.PixelFormat := pf16bit;
4560 Bitmap.PixelFormat := pf24bit;
4562 Bitmap.PixelFormat := pf32bit;
4564 raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
4568 for Row := 0 to FileHeight -1 do begin
4569 pData := Bitmap.Scanline[Row];
4571 Move(pSource^, pData^, fRowSize);
4572 Inc(pSource, fRowSize);
4574 // swap RGB(A) to BGR(A)
4575 if InternalFormat in [ifRGB8, ifRGBA8] then
4576 SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8);
4584 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4585 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
4587 pSource, pData, pTempData: PByte;
4588 Row, RowSize, TempWidth, TempHeight: Integer;
4589 IntFormat: TglBitmapInternalFormat;
4593 if (Assigned(Bitmap)) then begin
4594 case Bitmap.PixelFormat of
4596 IntFormat := ifLuminance;
4598 IntFormat := ifRGB5A1;
4600 IntFormat := ifR5G6B5;
4602 IntFormat := ifBGR8;
4604 IntFormat := ifBGRA8;
4606 raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
4609 TempWidth := Bitmap.Width;
4610 TempHeight := Bitmap.Height;
4612 RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
4614 GetMem(pData, TempHeight * RowSize);
4618 for Row := 0 to TempHeight -1 do begin
4619 pSource := Bitmap.Scanline[Row];
4621 if (Assigned(pSource)) then begin
4622 Move(pSource^, pTempData^, RowSize);
4623 Inc(pTempData, RowSize);
4627 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
4637 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4638 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
4640 Row, Col, AlphaInterleave: Integer;
4641 pSource, pDest: PByte;
4645 if Assigned(Data) then begin
4646 if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin
4647 if Assigned(Bitmap) then begin
4648 Bitmap.PixelFormat := pf8bit;
4649 Bitmap.Palette := CreateGrayPalette;
4650 Bitmap.Width := Width;
4651 Bitmap.Height := Height;
4653 case InternalFormat of
4655 AlphaInterleave := 1;
4657 AlphaInterleave := 3;
4659 AlphaInterleave := 0;
4665 for Row := 0 to Height -1 do begin
4666 pDest := Bitmap.Scanline[Row];
4668 if Assigned(pDest) then begin
4669 for Col := 0 to Width -1 do begin
4670 Inc(pSource, AlphaInterleave);
4684 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4685 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4689 tex := TglBitmap2D.Create;
4691 tex.AssignFromBitmap(Bitmap);
4692 result := AddAlphaFromglBitmap(tex, Func, CustomData);
4698 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4699 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar;
4700 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4702 RS: TResourceStream;
4707 if Assigned(ResType) then
4708 TempResType := ResType
4711 TempPos := Pos('.', Resource);
4712 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
4713 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
4714 TempResType := PChar(ResTypeStr);
4717 RS := TResourceStream.Create(Instance, Resource, TempResType);
4719 result := AddAlphaFromStream(RS, Func, CustomData);
4725 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4726 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
4727 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4729 RS: TResourceStream;
4731 RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
4733 result := AddAlphaFromStream(RS, Func, CustomData);
4740 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4741 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4744 if not FormatIsUncompressed(InternalFormat) then
4745 raise EglBitmapUnsupportedFormatFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_FORMAT);
4747 result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
4750 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4751 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4755 FS := TFileStream.Create(FileName, fmOpenRead);
4757 result := AddAlphaFromStream(FS, aFunc, aArgs);
4763 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4764 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4768 tex := TglBitmap2D.Create(aStream);
4770 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
4776 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4777 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
4779 DestData, DestData2, SourceData: pByte;
4780 TempHeight, TempWidth: Integer;
4781 SourceFD, DestFD: TFormatDescriptor;
4782 SourceMD, DestMD, DestMD2: Pointer;
4784 FuncRec: TglBitmapFunctionRec;
4788 Assert(Assigned(Data));
4789 Assert(Assigned(aBitmap));
4790 Assert(Assigned(aBitmap.Data));
4792 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
4793 result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
4794 if not Assigned(aFunc) then
4795 aFunc := glBitmapAlphaFunc;
4797 SourceFD := TFormatDescriptor.Get(aBitmap.Format);
4798 DestFD := TFormatDescriptor.Get(Format);
4801 TempHeight := aBitmap.FileHeight;
4802 TempWidth := aBitmap.FileWidth;
4804 FuncRec.Sender := Self;
4805 FuncRec.Args := aArgs;
4806 FuncRec.Size := Dimension;
4807 FuncRec.Position.Fields := FuncRec.Size.Fields;
4808 FuncRec.Args := PtrInt(SourceFD.HasAlpha) and 1;
4812 SourceData := aBitmap.Data;
4815 SourceFD.PreparePixel(FuncRec.Source);
4816 DestFD.PreparePixel (FuncRec.Dest);
4818 SourceMD := SourceFD.CreateMappingData;
4819 DestMD := DestFD.CreateMappingData;
4820 DestMD2 := DestFD.CreateMappingData;
4822 FuncRec.Position.Y := 0;
4823 while FuncRec.Position.Y < TempHeight do begin
4824 FuncRec.Position.X := 0;
4825 while FuncRec.Position.X < TempWidth do begin
4826 SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
4827 DestFD.Unmap (DestData, FuncRec.Dest, DestMD);
4829 DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
4830 inc(FuncRec.Position.X);
4832 inc(FuncRec.Position.Y);
4835 SourceFD.FreeMappingData(SourceMD);
4836 DestFD.FreeMappingData(DestMD);
4837 DestFD.FreeMappingData(DestMD2);
4842 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4843 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
4845 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
4848 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4849 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
4851 PixelData: TglBitmapPixelData;
4853 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
4854 result := AddAlphaFromColorKeyFloat(
4855 aRed / PixelData.Range.r,
4856 aGreen / PixelData.Range.g,
4857 aBlue / PixelData.Range.b,
4858 aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
4861 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4862 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
4864 values: array[0..2] of Single;
4867 PixelData: TglBitmapPixelData;
4869 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
4870 with PixelData do begin
4872 values[1] := aGreen;
4875 for i := 0 to 2 do begin
4876 tmp := Trunc(Range.arr[i] * aDeviation);
4877 Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
4878 Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp));
4883 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, PtrInt(@PixelData));
4886 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4887 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
4889 result := AddAlphaFromValueFloat(aAlpha / $FF);
4892 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4893 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
4895 PixelData: TglBitmapPixelData;
4897 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
4898 result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
4901 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4902 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
4904 PixelData: TglBitmapPixelData;
4906 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
4908 Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
4909 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, PtrInt(@PixelData.Data.a));
4912 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4913 function TglBitmap.RemoveAlpha: Boolean;
4915 FormatDesc: TFormatDescriptor;
4918 FormatDesc := TFormatDescriptor.Get(Format);
4919 if Assigned(Data) then begin
4920 if not ({FormatDesc.IsUncompressed or }FormatDesc.HasAlpha) then
4921 raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_FORMAT);
4922 result := ConvertTo(FormatDesc.WithoutAlpha);
4926 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4927 function TglBitmap.Clone: TglBitmap;
4934 Temp := (ClassType.Create as TglBitmap);
4936 // copy texture data if assigned
4937 if Assigned(Data) then begin
4938 Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
4939 GetMem(TempPtr, Size);
4941 Move(Data^, TempPtr^, Size);
4942 Temp.SetDataPointer(TempPtr, Format, Width, Height);
4948 Temp.SetDataPointer(nil, Format, Width, Height);
4952 Temp.fTarget := Target;
4953 Temp.fFormat := Format;
4954 Temp.fMipMap := MipMap;
4955 Temp.fAnisotropic := Anisotropic;
4956 Temp.fBorderColor := fBorderColor;
4957 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
4958 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
4959 Temp.fFilterMin := fFilterMin;
4960 Temp.fFilterMag := fFilterMag;
4961 Temp.fWrapS := fWrapS;
4962 Temp.fWrapT := fWrapT;
4963 Temp.fWrapR := fWrapR;
4964 Temp.fFilename := fFilename;
4965 Temp.fCustomName := fCustomName;
4966 Temp.fCustomNameW := fCustomNameW;
4967 Temp.fCustomData := fCustomData;
4976 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4977 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
4979 SourceFD, DestFD: TFormatDescriptor;
4980 SourcePD, DestPD: TglBitmapPixelData;
4981 ShiftData: TShiftData;
4983 function CanCopyDirect: Boolean;
4986 ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
4987 ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
4988 ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
4989 ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
4992 function CanShift: Boolean;
4995 ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
4996 ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
4997 ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
4998 ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
5001 function GetShift(aSource, aDest: Cardinal) : ShortInt;
5004 while (aSource > aDest) and (aSource > 0) do begin
5006 aSource := aSource shr 1;
5011 if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin
5012 SourceFD := TFormatDescriptor.Get(Format);
5013 DestFD := TFormatDescriptor.Get(aFormat);
5015 SourceFD.PreparePixel(SourcePD);
5016 DestFD.PreparePixel (DestPD);
5018 if CanCopyDirect then
5019 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
5020 else if CanShift then begin
5021 ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
5022 ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
5023 ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
5024 ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
5025 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, PtrInt(@ShiftData));
5027 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
5032 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5033 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
5035 if aUseRGB or aUseAlpha then
5036 AddFunc(glBitmapInvertFunc, false, ((PtrInt(aUseAlpha) and 1) shl 1) or (PtrInt(aUseRGB) and 1));
5039 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5040 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
5042 fBorderColor[0] := aRed;
5043 fBorderColor[1] := aGreen;
5044 fBorderColor[2] := aBlue;
5045 fBorderColor[3] := aAlpha;
5046 if (ID > 0) then begin
5048 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5052 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5053 procedure TglBitmap.FreeData;
5055 SetDataPointer(nil, tfEmpty);
5058 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5059 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
5060 const aAlpha: Byte);
5062 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
5065 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5066 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
5068 PixelData: TglBitmapPixelData;
5070 TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
5072 aRed / PixelData.Range.r,
5073 aGreen / PixelData.Range.g,
5074 aBlue / PixelData.Range.b,
5075 aAlpha / PixelData.Range.a);
5078 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5079 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
5081 PixelData: TglBitmapPixelData;
5083 TFormatDescriptor.Get(Format).PreparePixel(PixelData);
5084 with PixelData do begin
5085 Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
5086 Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
5087 Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
5088 Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
5090 AddFunc(glBitmapFillWithColorFunc, false, PtrInt(@PixelData));
5093 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5094 procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal);
5099 fFilterMin := GL_NEAREST;
5101 fFilterMin := GL_LINEAR;
5102 GL_NEAREST_MIPMAP_NEAREST:
5103 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
5104 GL_LINEAR_MIPMAP_NEAREST:
5105 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
5106 GL_NEAREST_MIPMAP_LINEAR:
5107 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
5108 GL_LINEAR_MIPMAP_LINEAR:
5109 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
5111 raise EglBitmapException.Create('SetFilter - Unknow MIN filter.');
5117 fFilterMag := GL_NEAREST;
5119 fFilterMag := GL_LINEAR;
5121 raise EglBitmapException.Create('SetFilter - Unknow MAG filter.');
5125 if (ID > 0) then begin
5127 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
5129 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
5131 GL_NEAREST, GL_LINEAR:
5132 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5133 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
5134 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5135 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
5136 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5139 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
5143 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5144 procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; const R: Cardinal);
5146 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
5150 aTarget := GL_CLAMP;
5153 aTarget := GL_REPEAT;
5155 GL_CLAMP_TO_EDGE: begin
5156 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
5157 aTarget := GL_CLAMP_TO_EDGE
5159 aTarget := GL_CLAMP;
5162 GL_CLAMP_TO_BORDER: begin
5163 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
5164 aTarget := GL_CLAMP_TO_BORDER
5166 aTarget := GL_CLAMP;
5169 GL_MIRRORED_REPEAT: begin
5170 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
5171 aTarget := GL_MIRRORED_REPEAT
5173 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
5176 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).');
5181 CheckAndSetWrap(S, fWrapS);
5182 CheckAndSetWrap(T, fWrapT);
5183 CheckAndSetWrap(R, fWrapR);
5185 if (ID > 0) then begin
5187 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
5188 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
5189 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
5193 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5194 procedure TglBitmap.GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData);
5197 if Assigned (fGetPixelFunc) then
5198 fGetPixelFunc(aPos, aPixel);
5202 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5203 procedure TglBitmap.SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData);
5206 if Assigned (fSetPixelFunc) then
5207 fSetPixelFuc(aPos, aPixel);
5211 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5212 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
5214 if aEnableTextureUnit then
5217 glBindTexture(Target, ID);
5220 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5221 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
5223 if aDisableTextureUnit then
5225 glBindTexture(Target, 0);
5228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5229 constructor TglBitmap.Create;
5231 {$IFNDEF GLB_NO_NATIVE_GL}
5232 ReadOpenGLExtensions;
5234 if (ClassType = TglBitmap) then
5235 raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
5239 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5240 constructor TglBitmap.Create(const aFileName: String);
5243 LoadFromFile(FileName);
5246 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5247 constructor TglBitmap.Create(const aStream: TStream);
5250 LoadFromStream(aStream);
5253 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5254 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
5260 TFormatDescriptor.Get(aFormat).GetSize(aSize);
5261 GetMem(Image, ImageSize);
5263 FillChar(Image^, ImageSize, #$FF);
5264 SetDataPointer(Image, aFormat, aSize.X, aSize.Y);
5271 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5272 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
5273 const aFunc: TglBitmapFunction; const aArgs: PtrInt);
5276 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
5280 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5281 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
5284 LoadFromResource(aInstance, aResource, aResType);
5287 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5288 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
5291 LoadFromResourceID(aInstance, aResourceID, aResType);
5295 {$IFDEF GLB_SUPPORT_PNG_READ}
5296 {$IF DEFINED(GLB_SDL_IMAGE)}
5297 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5298 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5299 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5300 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5302 Surface: PSDL_Surface;
5306 RWops := glBitmapCreateRWops(aStream);
5308 if IMG_isPNG(RWops) > 0 then begin
5309 Surface := IMG_LoadPNG_RW(RWops);
5311 AssignFromSurface(Surface);
5314 SDL_FreeSurface(Surface);
5322 {$ELSEIF DEFINED(GLB_LIB_PNG)}
5323 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5324 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5326 TStream(png_get_io_ptr(png)).Read(buffer^, size);
5329 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5330 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5333 signature: array [0..7] of byte;
5335 png_info: png_infop;
5337 TempHeight, TempWidth: Integer;
5338 Format: TglBitmapInternalFormat;
5341 png_rows: array of pByte;
5342 Row, LineSize: Integer;
5346 if not init_libPNG then
5347 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
5351 StreamPos := Stream.Position;
5352 Stream.Read(signature, 8);
5353 Stream.Position := StreamPos;
5355 if png_check_sig(@signature, 8) <> 0 then begin
5357 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5359 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
5362 png_info := png_create_info_struct(png);
5363 if png_info = nil then begin
5364 png_destroy_read_struct(@png, nil, nil);
5365 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
5368 // set read callback
5369 png_set_read_fn(png, stream, glBitmap_libPNG_read_func);
5371 // read informations
5372 png_read_info(png, png_info);
5375 TempHeight := png_get_image_height(png, png_info);
5376 TempWidth := png_get_image_width(png, png_info);
5379 case png_get_color_type(png, png_info) of
5380 PNG_COLOR_TYPE_GRAY:
5381 Format := tfLuminance8;
5382 PNG_COLOR_TYPE_GRAY_ALPHA:
5383 Format := tfLuminance8Alpha8;
5386 PNG_COLOR_TYPE_RGB_ALPHA:
5389 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5392 // cut upper 8 bit from 16 bit formats
5393 if png_get_bit_depth(png, png_info) > 8 then
5394 png_set_strip_16(png);
5396 // expand bitdepth smaller than 8
5397 if png_get_bit_depth(png, png_info) < 8 then
5398 png_set_expand(png);
5400 // allocating mem for scanlines
5401 LineSize := png_get_rowbytes(png, png_info);
5402 GetMem(png_data, TempHeight * LineSize);
5404 SetLength(png_rows, TempHeight);
5405 for Row := Low(png_rows) to High(png_rows) do begin
5406 png_rows[Row] := png_data;
5407 Inc(png_rows[Row], Row * LineSize);
5410 // read complete image into scanlines
5411 png_read_image(png, @png_rows[0]);
5414 png_read_end(png, png_info);
5416 // destroy read struct
5417 png_destroy_read_struct(@png, @png_info, nil);
5419 SetLength(png_rows, 0);
5422 SetDataPointer(png_data, Format, TempWidth, TempHeight);
5435 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5436 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5437 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
5441 Header: Array[0..7] of Byte;
5442 Row, Col, PixSize, LineSize: Integer;
5443 NewImage, pSource, pDest, pAlpha: pByte;
5444 Format: TglBitmapInternalFormat;
5447 PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10);
5452 StreamPos := Stream.Position;
5453 Stream.Read(Header[0], SizeOf(Header));
5454 Stream.Position := StreamPos;
5456 {Test if the header matches}
5457 if Header = PngHeader then begin
5458 Png := TPNGObject.Create;
5460 Png.LoadFromStream(Stream);
5462 case Png.Header.ColorType of
5464 Format := ifLuminance;
5465 COLOR_GRAYSCALEALPHA:
5466 Format := ifLuminanceAlpha;
5472 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5475 PixSize := Trunc(FormatGetSize(Format));
5476 LineSize := Integer(Png.Header.Width) * PixSize;
5478 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
5482 case Png.Header.ColorType of
5483 COLOR_RGB, COLOR_GRAYSCALE:
5485 for Row := 0 to Png.Height -1 do begin
5486 Move (Png.Scanline[Row]^, pDest^, LineSize);
5487 Inc(pDest, LineSize);
5490 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
5492 PixSize := PixSize -1;
5494 for Row := 0 to Png.Height -1 do begin
5495 pSource := Png.Scanline[Row];
5496 pAlpha := pByte(Png.AlphaScanline[Row]);
5498 for Col := 0 to Png.Width -1 do begin
5499 Move (pSource^, pDest^, PixSize);
5500 Inc(pSource, PixSize);
5501 Inc(pDest, PixSize);
5510 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
5513 SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height);
5528 {$IFDEF GLB_SUPPORT_PNG_WRITE}
5529 {$IFDEF GLB_LIB_PNG}
5530 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5531 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
5533 TStream(png_get_io_ptr(png)).Write(buffer^, size);
5537 {$IF DEFINED(GLB_LIB_PNG)}
5538 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5539 procedure TglBitmap.SavePNG(const aStream: TStream);
5542 png_info: png_infop;
5543 png_rows: array of pByte;
5548 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
5549 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5551 if not init_libPNG then
5552 raise Exception.Create('SavePNG - unable to initialize libPNG.');
5555 case FInternalFormat of
5556 ifAlpha, ifLuminance, ifDepth8:
5557 ColorType := PNG_COLOR_TYPE_GRAY;
5559 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
5561 ColorType := PNG_COLOR_TYPE_RGB;
5563 ColorType := PNG_COLOR_TYPE_RGBA;
5565 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5567 LineSize := Trunc(FormatGetSize(FInternalFormat) * Width);
5569 // creating array for scanline
5570 SetLength(png_rows, Height);
5572 for Row := 0 to Height - 1 do begin
5573 png_rows[Row] := Data;
5574 Inc(png_rows[Row], Row * LineSize)
5578 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
5580 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
5583 png_info := png_create_info_struct(png);
5584 if png_info = nil then begin
5585 png_destroy_write_struct(@png, nil);
5586 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
5589 // set read callback
5590 png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil);
5593 png_set_compression_level(png, 6);
5595 if InternalFormat in [ifBGR8, ifBGRA8] then
5598 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
5599 png_write_info(png, png_info);
5600 png_write_image(png, @png_rows[0]);
5601 png_write_end(png, png_info);
5602 png_destroy_write_struct(@png, @png_info);
5604 SetLength(png_rows, 0);
5611 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
5612 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5613 procedure TglBitmap.SavePNG(const aStream: TStream);
5617 pSource, pDest: pByte;
5618 X, Y, PixSize: Integer;
5619 ColorType: Cardinal;
5625 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
5626 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5628 case FInternalFormat of
5629 ifAlpha, ifLuminance, ifDepth8: begin
5630 ColorType := COLOR_GRAYSCALE;
5634 ifLuminanceAlpha: begin
5635 ColorType := COLOR_GRAYSCALEALPHA;
5639 ifBGR8, ifRGB8: begin
5640 ColorType := COLOR_RGB;
5644 ifBGRA8, ifRGBA8: begin
5645 ColorType := COLOR_RGBALPHA;
5650 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5653 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
5657 for Y := 0 to Height -1 do begin
5658 pDest := png.ScanLine[Y];
5659 for X := 0 to Width -1 do begin
5660 Move(pSource^, pDest^, PixSize);
5661 Inc(pDest, PixSize);
5662 Inc(pSource, PixSize);
5664 png.AlphaScanline[Y]^[X] := pSource^;
5669 // convert RGB line to BGR
5670 if InternalFormat in [ifRGB8, ifRGBA8] then begin
5671 pTemp := png.ScanLine[Y];
5672 for X := 0 to Width -1 do begin
5673 Temp := pByteArray(pTemp)^[0];
5674 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
5675 pByteArray(pTemp)^[2] := Temp;
5682 Png.CompressionLevel := 6;
5683 Png.SaveToStream(Stream);
5691 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5692 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5693 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5694 {$IFDEF GLB_LIB_JPEG}
5696 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
5697 glBitmap_libJPEG_source_mgr = record
5698 pub: jpeg_source_mgr;
5701 SrcBuffer: array [1..4096] of byte;
5704 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
5705 glBitmap_libJPEG_dest_mgr = record
5706 pub: jpeg_destination_mgr;
5708 DestStream: TStream;
5709 DestBuffer: array [1..4096] of byte;
5712 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5714 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
5718 SetLength(Msg, 256);
5719 cinfo^.err^.format_message(cinfo, pChar(Msg));
5720 Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
5721 cinfo^.global_state := 0;
5726 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5728 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
5732 SetLength(Msg, 256);
5733 cinfo^.err^.format_message(cinfo, pChar(Msg));
5734 Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
5735 cinfo^.global_state := 0;
5739 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5741 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
5746 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5747 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
5749 src: glBitmap_libJPEG_source_mgr_ptr;
5752 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5754 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
5755 if (bytes <= 0) then begin
5756 src^.SrcBuffer[1] := $FF;
5757 src^.SrcBuffer[2] := JPEG_EOI;
5761 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
5762 src^.pub.bytes_in_buffer := bytes;
5767 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5768 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
5770 src: glBitmap_libJPEG_source_mgr_ptr;
5772 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
5774 if num_bytes > 0 then begin
5775 // wanted byte isn't in buffer so set stream position and read buffer
5776 if num_bytes > src^.pub.bytes_in_buffer then begin
5777 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
5778 src^.pub.fill_input_buffer(cinfo);
5780 // wanted byte is in buffer so only skip
5781 inc(src^.pub.next_input_byte, num_bytes);
5782 dec(src^.pub.bytes_in_buffer, num_bytes);
5787 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5789 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
5794 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5796 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
5801 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5802 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
5804 dest: glBitmap_libJPEG_dest_mgr_ptr;
5806 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5808 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
5809 // write complete buffer
5810 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
5813 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
5814 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
5820 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5821 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
5824 dest: glBitmap_libJPEG_dest_mgr_ptr;
5826 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
5828 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
5829 // check for endblock
5830 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
5832 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
5837 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
5842 {$IFDEF GLB_SUPPORT_JPEG_READ}
5843 {$IF DEFINED(GLB_SDL_IMAGE)}
5844 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5845 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
5847 Surface: PSDL_Surface;
5852 RWops := glBitmapCreateRWops(Stream);
5854 if IMG_isJPG(RWops) > 0 then begin
5855 Surface := IMG_LoadJPG_RW(RWops);
5857 AssignFromSurface(Surface);
5860 SDL_FreeSurface(Surface);
5868 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
5869 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5870 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
5873 Temp: array[0..1]of Byte;
5875 jpeg: jpeg_decompress_struct;
5876 jpeg_err: jpeg_error_mgr;
5878 IntFormat: TglBitmapInternalFormat;
5880 TempHeight, TempWidth: Integer;
5887 if not init_libJPEG then
5888 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
5891 // reading first two bytes to test file and set cursor back to begin
5892 StreamPos := Stream.Position;
5893 Stream.Read(Temp[0], 2);
5894 Stream.Position := StreamPos;
5896 // if Bitmap then read file.
5897 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
5898 FillChar(jpeg, SizeOf(jpeg_decompress_struct), $00);
5899 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
5902 jpeg.err := jpeg_std_error(@jpeg_err);
5903 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
5904 jpeg_err.output_message := glBitmap_libJPEG_output_message;
5906 // decompression struct
5907 jpeg_create_decompress(@jpeg);
5909 // allocation space for streaming methods
5910 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
5912 // seeting up custom functions
5913 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
5914 pub.init_source := glBitmap_libJPEG_init_source;
5915 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
5916 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
5917 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
5918 pub.term_source := glBitmap_libJPEG_term_source;
5920 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
5921 pub.next_input_byte := nil; // until buffer loaded
5923 SrcStream := Stream;
5926 // set global decoding state
5927 jpeg.global_state := DSTATE_START;
5929 // read header of jpeg
5930 jpeg_read_header(@jpeg, false);
5932 // setting output parameter
5933 case jpeg.jpeg_color_space of
5936 jpeg.out_color_space := JCS_GRAYSCALE;
5937 IntFormat := ifLuminance;
5940 jpeg.out_color_space := JCS_RGB;
5941 IntFormat := ifRGB8;
5945 jpeg_start_decompress(@jpeg);
5947 TempHeight := jpeg.output_height;
5948 TempWidth := jpeg.output_width;
5950 // creating new image
5951 GetMem(pImage, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
5955 for Row := 0 to TempHeight -1 do begin
5956 jpeg_read_scanlines(@jpeg, @pTemp, 1);
5957 Inc(pTemp, Trunc(FormatGetSize(IntFormat) * TempWidth));
5960 // finish decompression
5961 jpeg_finish_decompress(@jpeg);
5963 // destroy decompression
5964 jpeg_destroy_decompress(@jpeg);
5966 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight);
5979 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
5980 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5981 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
5986 Temp: array[0..1]of Byte;
5990 // reading first two bytes to test file and set cursor back to begin
5991 StreamPos := Stream.Position;
5992 Stream.Read(Temp[0], 2);
5993 Stream.Position := StreamPos;
5995 // if Bitmap then read file.
5996 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
5997 bmp := TBitmap.Create;
5999 jpg := TJPEGImage.Create;
6001 jpg.LoadFromStream(Stream);
6003 result := AssignFromBitmap(bmp);
6015 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
6016 {$IF DEFEFINED(GLB_LIB_JPEG)}
6017 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6018 procedure TglBitmap.SaveJPEG(Stream: TStream);
6020 jpeg: jpeg_compress_struct;
6021 jpeg_err: jpeg_error_mgr;
6023 pTemp, pTemp2: pByte;
6025 procedure CopyRow(pDest, pSource: pByte);
6029 for X := 0 to Width - 1 do begin
6030 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
6031 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
6032 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
6039 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
6040 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
6042 if not init_libJPEG then
6043 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
6046 FillChar(jpeg, SizeOf(jpeg_compress_struct), $00);
6047 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
6050 jpeg.err := jpeg_std_error(@jpeg_err);
6051 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
6052 jpeg_err.output_message := glBitmap_libJPEG_output_message;
6054 // compression struct
6055 jpeg_create_compress(@jpeg);
6057 // allocation space for streaming methods
6058 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
6060 // seeting up custom functions
6061 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
6062 pub.init_destination := glBitmap_libJPEG_init_destination;
6063 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
6064 pub.term_destination := glBitmap_libJPEG_term_destination;
6066 pub.next_output_byte := @DestBuffer[1];
6067 pub.free_in_buffer := Length(DestBuffer);
6069 DestStream := Stream;
6072 // very important state
6073 jpeg.global_state := CSTATE_START;
6074 jpeg.image_width := Width;
6075 jpeg.image_height := Height;
6076 case InternalFormat of
6077 ifAlpha, ifLuminance, ifDepth8: begin
6078 jpeg.input_components := 1;
6079 jpeg.in_color_space := JCS_GRAYSCALE;
6081 ifRGB8, ifBGR8: begin
6082 jpeg.input_components := 3;
6083 jpeg.in_color_space := JCS_RGB;
6087 jpeg_set_defaults(@jpeg);
6088 jpeg_set_quality(@jpeg, 95, true);
6089 jpeg_start_compress(@jpeg, true);
6092 if InternalFormat = ifBGR8 then
6093 GetMem(pTemp2, fRowSize)
6098 for Row := 0 to jpeg.image_height -1 do begin
6100 if InternalFormat = ifBGR8 then
6101 CopyRow(pTemp2, pTemp)
6106 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
6107 inc(pTemp, fRowSize);
6111 if InternalFormat = ifBGR8 then
6114 jpeg_finish_compress(@jpeg);
6115 jpeg_destroy_compress(@jpeg);
6121 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
6122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6123 procedure TglBitmap.SaveJPEG(Stream: TStream);
6128 if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then
6129 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
6131 Bmp := TBitmap.Create;
6133 Jpg := TJPEGImage.Create;
6135 AssignToBitmap(Bmp);
6136 if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
6137 Jpg.Grayscale := true;
6138 Jpg.PixelFormat := jf8Bit;
6141 Jpg.SaveToStream(Stream);
6152 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6153 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6154 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6161 BMP_COMP_BITFIELDS = 3;
6164 TBMPHeader = packed record
6169 bfOffBits: Cardinal;
6172 TBMPInfo = packed record
6178 biCompression: Cardinal;
6179 biSizeImage: Cardinal;
6180 biXPelsPerMeter: Longint;
6181 biYPelsPerMeter: Longint;
6182 biClrUsed: Cardinal;
6183 biClrImportant: Cardinal;
6186 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6187 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
6189 //////////////////////////////////////////////////////////////////////////////////////////////////
6190 function ReadInfo(var aInfo: TBMPInfo; var aMask: TglBitmapColorRec): TglBitmapFormat;
6193 aStream.Read(aInfo, SizeOf(aInfo));
6194 FillChar(aMask, SizeOf(aMask), 0);
6197 case aInfo.biCompression of
6199 BMP_COMP_RLE8: begin
6200 raise EglBitmapException.Create('RLE compression is not supported');
6202 BMP_COMP_BITFIELDS: begin
6203 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
6204 aStream.Read(aMask.r, SizeOf(aMask.r));
6205 aStream.Read(aMask.g, SizeOf(aMask.g));
6206 aStream.Read(aMask.b, SizeOf(aMask.b));
6207 aStream.Read(aMask.a, SizeOf(aMask.a));
6209 raise EglBitmapException.Create('Bitfields are only supported for 16bit and 32bit formats');
6213 //get suitable format
6214 case aInfo.biBitCount of
6215 8: result := tfLuminance8;
6216 16: result := tfBGR5;
6217 24: result := tfBGR8;
6218 32: result := tfBGRA8;
6222 function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
6225 ColorTable: TbmpColorTable;
6228 if (aInfo.biBitCount >= 16) then
6230 aFormat := tfLuminance8;
6231 c := aInfo.biClrUsed;
6233 c := 1 shl aInfo.biBitCount;
6234 SetLength(ColorTable, c);
6235 for i := 0 to c-1 do begin
6236 aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
6237 if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
6241 result := TbmpColorTableFormat.Create;
6242 result.PixelSize := aInfo.biBitCount / 8;
6243 result.ColorTable := ColorTable;
6244 result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
6247 //////////////////////////////////////////////////////////////////////////////////////////////////
6248 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
6249 const aInfo: TBMPInfo): TbmpBitfieldFormat;
6251 TmpFormat: TglBitmapFormat;
6252 FormatDesc: TFormatDescriptor;
6255 if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
6256 for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
6257 FormatDesc := TFormatDescriptor.Get(TmpFormat);
6258 if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
6259 aFormat := FormatDesc.Format;
6264 if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
6265 aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
6266 if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
6267 aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
6269 result := TbmpBitfieldFormat.Create;
6270 result.PixelSize := aInfo.biBitCount / 8;
6271 result.RedMask := aMask.r;
6272 result.GreenMask := aMask.g;
6273 result.BlueMask := aMask.b;
6274 result.AlphaMask := aMask.a;
6281 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
6282 PaddingBuff: Cardinal;
6283 LineBuf, ImageData, TmpData: PByte;
6284 SourceMD, DestMD: Pointer;
6285 BmpFormat: TglBitmapFormat;
6286 ColorTable: TbmpColorTable;
6289 Mask: TglBitmapColorRec;
6294 SpecialFormat: TFormatDescriptor;
6295 FormatDesc: TFormatDescriptor;
6297 //////////////////////////////////////////////////////////////////////////////////////////////////
6298 procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
6301 Pixel: TglBitmapPixelData;
6303 aStream.Read(aLineBuf^, rbLineSize);
6304 SpecialFormat.PreparePixel(Pixel);
6305 for i := 0 to Info.biWidth-1 do begin
6306 SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
6307 with FormatDesc do begin
6308 //TODO: use convert function
6310 if (SpecialFormat.Range.arr[j] <> Range.arr[j]) then begin
6311 if (SpecialFormat.Range.arr[j] > 0) then
6312 Pixel.Data.arr[j] := Round(Pixel.Data.arr[j] / SpecialFormat.Range.arr[j] * Range.arr[j])
6314 Pixel.Data.arr[j] := 0;
6317 FormatDesc.Map(Pixel, aData, DestMD);
6323 BmpFormat := tfEmpty;
6324 SpecialFormat := nil;
6330 StartPos := aStream.Position;
6331 aStream.Read(Header, SizeOf(Header));
6333 if Header.bfType = BMP_MAGIC then begin
6335 BmpFormat := ReadInfo(Info, Mask);
6336 SpecialFormat := ReadColorTable(BmpFormat, Info);
6337 if not Assigned(SpecialFormat) then
6338 SpecialFormat := CheckBitfields(BmpFormat, Mask, Info);
6339 aStream.Position := StartPos + Header.bfOffBits;
6341 if (BmpFormat <> tfEmpty) then begin
6342 FormatDesc := TFormatDescriptor.Get(BmpFormat);
6343 rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
6344 wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
6345 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
6348 DestMD := FormatDesc.CreateMappingData;
6349 ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
6350 GetMem(ImageData, ImageSize);
6351 if Assigned(SpecialFormat) then begin
6352 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
6353 SourceMD := SpecialFormat.CreateMappingData;
6358 FillChar(ImageData^, ImageSize, $FF);
6359 TmpData := ImageData;
6360 if (Info.biHeight > 0) then
6361 Inc(TmpData, wbLineSize * (Info.biHeight-1));
6362 for i := 0 to Abs(Info.biHeight)-1 do begin
6363 if Assigned(SpecialFormat) then
6364 SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data
6366 aStream.Read(TmpData^, wbLineSize); //else only read data
6367 if (Info.biHeight > 0) then
6368 dec(TmpData, wbLineSize)
6370 inc(TmpData, wbLineSize);
6371 aStream.Read(PaddingBuff, Padding);
6373 SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight));
6376 if Assigned(LineBuf) then
6378 if Assigned(SourceMD) then
6379 SpecialFormat.FreeMappingData(SourceMD);
6380 FormatDesc.FreeMappingData(DestMD);
6387 raise EglBitmapException.Create('LoadBMP - No suitable format found');
6389 aStream.Position := StartPos;
6393 FreeAndNil(SpecialFormat);
6396 else aStream.Position := StartPos;
6399 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6400 procedure TglBitmap.SaveBMP(const aStream: TStream);
6404 Converter: TbmpColorTableFormat;
6405 FormatDesc: TFormatDescriptor;
6406 SourceFD, DestFD: Pointer;
6407 pData, srcData, dstData, ConvertBuffer: pByte;
6409 Pixel: TglBitmapPixelData;
6410 PixelFormat: TglBitmapPixelData;
6411 ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx, i: Integer;
6412 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
6414 PaddingBuff: Cardinal;
6416 function GetLineWidth : Integer;
6418 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
6422 if not (ftBMP in FormatGetSupportedFiles(Format)) then
6423 raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
6426 FormatDesc := TFormatDescriptor.Get(Format);
6427 ImageSize := FormatDesc.GetSize(Dimension);
6429 FillChar(Header, SizeOf(Header), 0);
6430 Header.bfType := BMP_MAGIC;
6431 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
6432 Header.bfReserved1 := 0;
6433 Header.bfReserved2 := 0;
6434 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
6436 FillChar(Info, SizeOf(Info), 0);
6437 Info.biSize := SizeOf(Info);
6438 Info.biWidth := Width;
6439 Info.biHeight := Height;
6441 Info.biCompression := BMP_COMP_RGB;
6442 Info.biSizeImage := ImageSize;
6447 Info.biBitCount := 4;
6448 Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal);
6449 Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
6450 Converter := TbmpColorTableFormat.Create;
6451 Converter.PixelSize := 0.5;
6452 Converter.Format := Format;
6453 Converter.Range := glBitmapColorRec($F, $F, $F, $0);
6454 Converter.CreateColorTable;
6457 tfR3G3B2, tfLuminance8: begin
6458 Info.biBitCount := 8;
6459 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
6460 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
6461 Converter := TbmpColorTableFormat.Create;
6462 Converter.PixelSize := 1;
6463 Converter.Format := Format;
6464 if (Format = tfR3G3B2) then begin
6465 Converter.Range := glBitmapColorRec($7, $7, $3, $0);
6466 Converter.Shift := glBitmapShiftRec(0, 3, 6, 0);
6468 Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0);
6469 Converter.CreateColorTable;
6472 tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
6473 tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
6474 Info.biBitCount := 16;
6475 Info.biCompression := BMP_COMP_BITFIELDS;
6478 tfBGR8, tfRGB8: begin
6479 Info.biBitCount := 24;
6482 tfRGB10, tfRGB10A2, tfRGBA8,
6483 tfBGR10, tfBGR10A2, tfBGRA8: begin
6484 Info.biBitCount := 32;
6485 Info.biCompression := BMP_COMP_BITFIELDS;
6488 raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
6490 Info.biXPelsPerMeter := 2835;
6491 Info.biYPelsPerMeter := 2835;
6494 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6495 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
6496 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
6498 RedMask := FormatDesc.RedMask;
6499 GreenMask := FormatDesc.GreenMask;
6500 BlueMask := FormatDesc.BlueMask;
6501 AlphaMask := FormatDesc.AlphaMask;
6505 aStream.Write(Header, SizeOf(Header));
6506 aStream.Write(Info, SizeOf(Info));
6509 if Assigned(Converter) then
6510 aStream.Write(Converter.ColorTable[0].b,
6511 SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable));
6514 if Info.biCompression = BMP_COMP_BITFIELDS then begin
6515 aStream.Write(RedMask, SizeOf(Cardinal));
6516 aStream.Write(GreenMask, SizeOf(Cardinal));
6517 aStream.Write(BlueMask, SizeOf(Cardinal));
6518 aStream.Write(AlphaMask, SizeOf(Cardinal));
6522 rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize);
6523 wbLineSize := Round(Info.biWidth * Info.biBitCount / 8);
6524 Padding := GetLineWidth - wbLineSize;
6528 inc(pData, (Height-1) * rbLineSize);
6530 // prepare row buffer. But only for RGB because RGBA supports color masks
6531 // so it's possible to change color within the image.
6532 if Assigned(Converter) then begin
6533 FormatDesc.PreparePixel(Pixel);
6534 GetMem(ConvertBuffer, wbLineSize);
6535 SourceFD := FormatDesc.CreateMappingData;
6536 DestFD := Converter.CreateMappingData;
6538 ConvertBuffer := nil;
6541 for LineIdx := 0 to Height - 1 do begin
6543 if Assigned(Converter) then begin
6545 dstData := ConvertBuffer;
6546 for PixelIdx := 0 to Info.biWidth-1 do begin
6547 FormatDesc.Unmap(srcData, Pixel, SourceFD);
6548 with FormatDesc do begin
6549 //TODO use convert function
6551 if (Converter.Range.arr[i] <> Range.arr[i]) then begin
6552 if (Range.arr[i] > 0) then
6553 Pixel.Data.arr[i] := Round(Pixel.Data.arr[i] / Range.arr[i] * Converter.Range.arr[i])
6555 Pixel.Data.arr[i] := 0;
6558 Converter.Map(Pixel, dstData, DestFD);
6560 aStream.Write(ConvertBuffer^, wbLineSize);
6562 aStream.Write(pData^, rbLineSize);
6564 dec(pData, rbLineSize);
6565 if (Padding > 0) then
6566 aStream.Write(PaddingBuff, Padding);
6569 // destroy row buffer
6570 if Assigned(ConvertBuffer) then begin
6571 FormatDesc.FreeMappingData(SourceFD);
6572 Converter.FreeMappingData(DestFD);
6573 FreeMem(ConvertBuffer);
6577 if Assigned(Converter) then
6582 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6583 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6584 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6586 TTGAHeader = packed record
6590 //ColorMapSpec: Array[0..4] of Byte;
6591 ColorMapStart: Word;
6592 ColorMapLength: Word;
6593 ColorMapEntrySize: Byte;
6603 TGA_UNCOMPRESSED_COLOR_TABLE = 1;
6604 TGA_UNCOMPRESSED_RGB = 2;
6605 TGA_UNCOMPRESSED_GRAY = 3;
6606 TGA_COMPRESSED_COLOR_TABLE = 9;
6607 TGA_COMPRESSED_RGB = 10;
6608 TGA_COMPRESSED_GRAY = 11;
6610 TGA_NONE_COLOR_TABLE = 0;
6611 TGA_COLOR_TABLE = 1;
6613 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6614 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
6618 StartPosition: Int64;
6619 PixelSize, LineSize: Integer;
6620 tgaFormat: TglBitmapFormat;
6621 FormatDesc: TFormatDescriptor;
6622 Counter: packed record
6624 low, high, dir: Integer;
6631 ////////////////////////////////////////////////////////////////////////////////////////
6632 procedure ReadUncompressed;
6635 buf, tmp1, tmp2: PByte;
6638 if (Counter.X.dir < 0) then
6639 buf := GetMem(LineSize);
6641 while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
6642 tmp1 := ImageData + (Counter.Y.low * LineSize); //pointer to LineStart
6643 if (Counter.X.dir < 0) then begin //flip X
6644 aStream.Read(buf^, LineSize);
6645 tmp2 := buf + LineSize - PixelSize; //pointer to last pixel in line
6646 for i := 0 to Header.Width-1 do begin //for all pixels in line
6647 for j := 0 to PixelSize-1 do begin //for all bytes in pixel
6652 dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward
6655 aStream.Read(tmp1^, LineSize);
6656 inc(Counter.Y.low, Counter.Y.dir); //move to next line index
6659 if Assigned(buf) then
6664 ////////////////////////////////////////////////////////////////////////////////////////
6665 procedure ReadCompressed;
6667 /////////////////////////////////////////////////////////////////
6670 LinePixelsRead: Integer;
6671 procedure CheckLine;
6673 if (LinePixelsRead >= Header.Width) then begin
6674 LinePixelsRead := 0;
6675 inc(Counter.Y.low, Counter.Y.dir); //next line index
6676 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6677 if (Counter.X.dir < 0) then //if x flipped then
6678 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6682 /////////////////////////////////////////////////////////////////
6685 CacheSize, CachePos: Integer;
6686 procedure CachedRead(out Buffer; Count: Integer);
6690 if (CachePos + Count > CacheSize) then begin
6691 //if buffer overflow save non read bytes
6693 if (CacheSize - CachePos > 0) then begin
6694 BytesRead := CacheSize - CachePos;
6695 Move(PByteArray(Cache)^[CachePos], Buffer, BytesRead);
6696 inc(CachePos, BytesRead);
6699 //load cache from file
6700 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
6701 aStream.Read(Cache^, CacheSize);
6704 //read rest of requested bytes
6705 if (Count - BytesRead > 0) then begin
6706 Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
6707 inc(CachePos, Count - BytesRead);
6710 //if no buffer overflow just read the data
6711 Move(PByteArray(Cache)^[CachePos], Buffer, Count);
6712 inc(CachePos, Count);
6716 procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
6721 inc(aBuffer, Counter.X.dir);
6724 PWord(aBuffer)^ := PWord(aData)^;
6725 inc(aBuffer, 2 * Counter.X.dir);
6728 PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
6729 PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
6730 PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
6731 inc(aBuffer, 3 * Counter.X.dir);
6734 PCardinal(aBuffer)^ := PCardinal(aData)^;
6735 inc(aBuffer, 4 * Counter.X.dir);
6741 TotalPixelsToRead, TotalPixelsRead: Integer;
6743 buf: array [0..3] of Byte; //1 pixel is max 32bit long
6744 PixelRepeat: Boolean;
6745 PixelsToRead, PixelCount: Integer;
6750 TotalPixelsToRead := Header.Width * Header.Height;
6751 TotalPixelsRead := 0;
6752 LinePixelsRead := 0;
6754 GetMem(Cache, CACHE_SIZE);
6756 TmpData := ImageData + Counter.Y.low * LineSize; //set line
6757 if (Counter.X.dir < 0) then //if x flipped then
6758 TmpData := TmpData + LineSize - PixelSize; //set last pixel
6762 CachedRead(Temp, 1);
6763 PixelRepeat := (Temp and $80) > 0;
6764 PixelsToRead := (Temp and $7F) + 1;
6765 inc(TotalPixelsRead, PixelsToRead);
6768 CachedRead(buf[0], PixelSize);
6769 while (PixelsToRead > 0) do begin
6771 PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
6772 while (PixelCount > 0) do begin
6773 if not PixelRepeat then
6774 CachedRead(buf[0], PixelSize);
6775 PixelToBuffer(@buf[0], TmpData);
6776 inc(LinePixelsRead);
6781 until (TotalPixelsRead >= TotalPixelsToRead);
6787 function IsGrayFormat: Boolean;
6789 result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
6795 // reading header to test file and set cursor back to begin
6796 StartPosition := aStream.Position;
6797 aStream.Read(Header, SizeOf(Header));
6799 // no colormapped files
6800 if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
6801 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
6804 if Header.ImageID <> 0 then // skip image ID
6805 aStream.Position := aStream.Position + Header.ImageID;
6808 8: if IsGrayFormat then case (Header.ImageDesc and $F) of
6809 0: tgaFormat := tfLuminance8;
6810 8: tgaFormat := tfAlpha8;
6813 16: if IsGrayFormat then case (Header.ImageDesc and $F) of
6814 0: tgaFormat := tfLuminance16;
6815 8: tgaFormat := tfLuminance8Alpha8;
6816 end else case (Header.ImageDesc and $F) of
6817 0: tgaFormat := tfBGR5;
6818 1: tgaFormat := tfBGR5A1;
6819 4: tgaFormat := tfBGRA4;
6822 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6823 0: tgaFormat := tfBGR8;
6826 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
6827 2: tgaFormat := tfBGR10A2;
6828 8: tgaFormat := tfBGRA8;
6832 if (tgaFormat = tfEmpty) then
6833 raise EglBitmapException.Create('LoadTga - unsupported format');
6835 FormatDesc := TFormatDescriptor.Get(tgaFormat);
6836 PixelSize := FormatDesc.GetSize(1, 1);
6837 LineSize := FormatDesc.GetSize(Header.Width, 1);
6839 GetMem(ImageData, LineSize * Header.Height);
6842 if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
6843 Counter.X.low := Header.Height-1;;
6844 Counter.X.high := 0;
6845 Counter.X.dir := -1;
6848 Counter.X.high := Header.Height-1;
6853 if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
6855 Counter.Y.high := Header.Height-1;
6858 Counter.Y.low := Header.Height-1;;
6859 Counter.Y.high := 0;
6860 Counter.Y.dir := -1;
6864 case Header.ImageType of
6865 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
6867 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
6871 SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height);
6878 aStream.Position := StartPosition;
6881 else aStream.Position := StartPosition;
6884 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6885 procedure TglBitmap.SaveTGA(const aStream: TStream);
6888 LineSize, Size, x, y: Integer;
6889 Pixel: TglBitmapPixelData;
6890 LineBuf, SourceData, DestData: PByte;
6891 SourceMD, DestMD: Pointer;
6892 FormatDesc: TFormatDescriptor;
6893 Converter: TFormatDescriptor;
6895 if not (ftTGA in FormatGetSupportedFiles(Format)) then
6896 raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT);
6899 FillChar(Header, SizeOf(Header), 0);
6902 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
6903 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
6904 Header.ImageType := TGA_UNCOMPRESSED_GRAY
6906 Header.ImageType := TGA_UNCOMPRESSED_RGB;
6909 if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
6911 else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
6912 tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
6914 else if (Format in [tfBGR8, tfRGB8]) then
6922 Header.ImageDesc := 1 and $F;
6923 tfRGB10A2, tfBGR10A2:
6924 Header.ImageDesc := 2 and $F;
6926 Header.ImageDesc := 4 and $F;
6927 tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
6928 Header.ImageDesc := 8 and $F;
6931 Header.Width := Width;
6932 Header.Height := Height;
6933 Header.ImageDesc := Header.ImageDesc or $20; //flip y
6934 aStream.Write(Header, SizeOf(Header));
6936 // convert RGB(A) to BGR(A)
6938 FormatDesc := TFormatDescriptor.Get(Format);
6939 Size := FormatDesc.GetSize(Dimension);
6940 if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
6941 if (FormatDesc.RGBInverted = tfEmpty) then
6942 raise EglBitmapException.Create('inverted RGB format is empty');
6943 Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
6944 if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
6945 (Converter.PixelSize <> FormatDesc.PixelSize) then
6946 raise EglBitmapException.Create('invalid inverted RGB format');
6949 if Assigned(Converter) then begin
6950 LineSize := FormatDesc.GetSize(Width, 1);
6951 LineBuf := GetMem(LineSize);
6952 SourceMD := FormatDesc.CreateMappingData;
6953 DestMD := Converter.CreateMappingData;
6956 for y := 0 to Height-1 do begin
6957 DestData := LineBuf;
6958 for x := 0 to Width-1 do begin
6959 FormatDesc.Unmap(SourceData, Pixel, SourceMD);
6960 Converter.Map(Pixel, DestData, DestMD);
6962 aStream.Write(LineBuf^, LineSize);
6966 FormatDesc.FreeMappingData(SourceMD);
6967 FormatDesc.FreeMappingData(DestMD);
6970 aStream.Write(Data^, Size);
6973 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6974 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6975 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6977 DDS_MAGIC = $20534444;
6979 // DDS_header.dwFlags
6980 DDSD_CAPS = $00000001;
6981 DDSD_HEIGHT = $00000002;
6982 DDSD_WIDTH = $00000004;
6983 DDSD_PITCH = $00000008;
6984 DDSD_PIXELFORMAT = $00001000;
6985 DDSD_MIPMAPCOUNT = $00020000;
6986 DDSD_LINEARSIZE = $00080000;
6987 DDSD_DEPTH = $00800000;
6989 // DDS_header.sPixelFormat.dwFlags
6990 DDPF_ALPHAPIXELS = $00000001;
6991 DDPF_FOURCC = $00000004;
6992 DDPF_INDEXED = $00000020;
6993 DDPF_RGB = $00000040;
6994 DDPF_LUMINANCE = $00020000;
6996 // DDS_header.sCaps.dwCaps1
6997 DDSCAPS_COMPLEX = $00000008;
6998 DDSCAPS_TEXTURE = $00001000;
6999 DDSCAPS_MIPMAP = $00400000;
7001 // DDS_header.sCaps.dwCaps2
7002 DDSCAPS2_CUBEMAP = $00000200;
7003 DDSCAPS2_CUBEMAP_POSITIVEX = $00000400;
7004 DDSCAPS2_CUBEMAP_NEGATIVEX = $00000800;
7005 DDSCAPS2_CUBEMAP_POSITIVEY = $00001000;
7006 DDSCAPS2_CUBEMAP_NEGATIVEY = $00002000;
7007 DDSCAPS2_CUBEMAP_POSITIVEZ = $00004000;
7008 DDSCAPS2_CUBEMAP_NEGATIVEZ = $00008000;
7009 DDSCAPS2_VOLUME = $00200000;
7011 D3DFMT_DXT1 = $31545844;
7012 D3DFMT_DXT3 = $33545844;
7013 D3DFMT_DXT5 = $35545844;
7016 TDDSPixelFormat = packed record
7020 dwRGBBitCount: Cardinal;
7021 dwRBitMask: Cardinal;
7022 dwGBitMask: Cardinal;
7023 dwBBitMask: Cardinal;
7024 dwABitMask: Cardinal;
7027 TDDSCaps = packed record
7031 dwReserved: Cardinal;
7034 TDDSHeader = packed record
7040 dwPitchOrLinearSize: Cardinal;
7042 dwMipMapCount: Cardinal;
7043 dwReserved: array[0..10] of Cardinal;
7044 PixelFormat: TDDSPixelFormat;
7046 dwReserved2: Cardinal;
7049 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7050 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
7054 function GetDDSFormat: TglBitmapFormat;
7057 with Header.PixelFormat do begin
7059 if ((dwFlags and DDPF_FOURCC) > 0) then begin
7060 case Header.PixelFormat.dwFourCC of
7061 D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
7062 D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
7063 D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
7068 if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7069 case dwRGBBitCount of
7071 if ((dwFlags and DDPF_ALPHAPIXELS) > 0) then
7073 else if ((dwFlags and DDPF_LUMINANCE) > 0) then
7074 result := tfLuminance8;
7078 if ((dwFlags and DDPF_ALPHAPIXELS) > 0) then begin
7079 case CountSetBits(dwRBitMask) of
7080 5: result := tfRGB5A1;
7081 4: result := tfRGBA4;
7083 result := tfLuminance8Alpha8;
7085 end else if (CountSetBits(dwGBitMask) = 6) then
7096 if CountSetBits(dwRBitMask) = 10 then
7103 if (dwRBitMask <> 0) and (dwBBitMask <> 0) and (dwRBitMask > dwBBitMask) then
7104 result := TFormatDescriptor.Get(result).RGBInverted;
7111 Y, LineSize: Cardinal;
7113 NewImage, TmpData: PByte;
7114 ddsFormat: TglBitmapFormat;
7115 FormatDesc: TFormatDescriptor;
7121 StreamPos := aStream.Position;
7122 aStream.Read(Header, sizeof(Header));
7124 if (Header.dwMagic <> DDS_MAGIC) or (Header.dwSize <> 124) or
7125 ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
7126 (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
7128 aStream.Position := StreamPos;
7132 if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
7133 raise EglBitmapException.Create('LoadDDS - CubeMaps are not supported');
7135 ddsFormat := GetDDSFormat;
7136 if (ddsFormat = tfEmpty) then
7137 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7139 FormatDesc := TFormatDescriptor.Get(ddsFormat);
7140 LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize);
7141 GetMem(NewImage, Header.dwHeight * LineSize);
7143 TmpData := NewImage;
7146 if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
7147 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
7148 for Y := 0 to Header.dwHeight-1 do begin
7149 aStream.Read(TmpData^, RowSize);
7150 Inc(TmpData, LineSize);
7155 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
7156 RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
7157 for Y := 0 to Header.dwHeight-1 do begin
7158 aStream.Read(TmpData^, RowSize);
7159 Inc(TmpData, LineSize);
7162 raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
7164 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
7172 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7173 procedure TglBitmap.SaveDDS(const aStream: TStream);
7176 Pix: TglBitmapPixelData;
7177 FormatDesc: TFormatDescriptor;
7179 //if not FormatIsUncompressed(InternalFormat) then
7180 // raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_FORMAT);
7182 (* TODO if Format = tfAlpha8 then
7183 FORMAT_DESCRIPTORS[tfLuminance8].PreparePixel(Pix);
7185 TFormatDescriptor.Get(Format).PreparePixel(Pix);
7188 FillChar(Header, SizeOf(Header), 0);
7189 Header.dwMagic := DDS_MAGIC;
7190 Header.dwSize := 124;
7191 Header.dwFlags := DDSD_PITCH or DDSD_CAPS or DDSD_PIXELFORMAT;
7193 if Width > 0 then begin
7194 Header.dwWidth := Width;
7195 Header.dwFlags := Header.dwFlags or DDSD_WIDTH;
7198 if Height > 0 then begin
7199 Header.dwHeight := Height;
7200 Header.dwFlags := Header.dwFlags or DDSD_HEIGHT;
7203 Header.dwPitchOrLinearSize := fRowSize;
7204 Header.dwMipMapCount := 1;
7207 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
7210 Header.PixelFormat.dwSize := Sizeof(Header.PixelFormat);
7211 Header.PixelFormat.dwFlags := DDPF_RGB;
7214 if FORMAT_DESCRIPTORS[Format].HasAlpha and (Format <> tfAlpha8) then
7215 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
7218 FormatDesc := TFormatDescriptor.Get(Format);
7219 Header.PixelFormat.dwRGBBitCount := Trunc(FormatDesc.PixelSize * 8);
7220 Header.PixelFormat.dwRBitMask := FormatDesc.RedMask;
7221 Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask;
7222 Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask;
7223 Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
7225 aStream.Write(Header, SizeOf(Header));
7226 aStream.Write(Data^, FormatDesc.GetSize(Dimension));
7229 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7230 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7231 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7232 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
7234 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
7235 result := fLines[aIndex]
7240 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7241 procedure TglBitmap2D.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
7242 const aWidth: Integer; const aHeight: Integer);
7244 Idx, LineWidth: Integer;
7246 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
7248 if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
7250 fGetPixelFunc := GetPixel2DUnmap;
7251 fSetPixelFunc := SetPixel2DUnmap;
7254 if Assigned(Data) then begin
7255 SetLength(fLines, GetHeight);
7256 LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
7258 for Idx := 0 to GetHeight -1 do begin
7259 fLines[Idx] := Data;
7260 Inc(fLines[Idx], Idx * LineWidth);
7263 else SetLength(fLines, 0);
7265 SetLength(fLines, 0);
7267 fSetPixelFunc := nil;
7271 fGetPixelFunc := GetPixel2DDXT1;
7273 fGetPixelFunc := GetPixel2DDXT3;
7275 fGetPixelFunc := GetPixel2DDXT5;
7277 fGetPixelFunc := nil;
7283 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7284 procedure TglBitmap2D.UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
7286 FormatDesc: TFormatDescriptor;
7288 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7290 FormatDesc := TFormatDescriptor.Get(Format);
7291 if FormatDesc.IsCompressed then begin
7292 glCompressedTexImage2D(Target, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
7293 end else if aBuildWithGlu then begin
7294 gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
7295 FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
7297 glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
7298 FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
7302 if (FreeDataAfterGenTexture) then
7306 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7307 procedure TglBitmap2D.AfterConstruction;
7310 Target := GL_TEXTURE_2D;
7313 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7314 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
7317 Size, w, h: Integer;
7318 FormatDesc: TFormatDescriptor;
7320 FormatDesc := TFormatDescriptor.Get(Format);
7321 if FormatDesc.IsCompressed then
7322 raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_FORMAT);
7324 w := aRight - aLeft;
7325 h := aBottom - aTop;
7326 Size := FormatDesc.GetSize(w, h);
7329 glPixelStorei(GL_PACK_ALIGNMENT, 1);
7330 glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
7331 SetDataPointer(Temp, Format, w, h);
7339 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7340 procedure TglBitmap2D.GetDataFromTexture;
7343 TempWidth, TempHeight: Integer;
7344 TempType, TempIntFormat: Cardinal;
7345 IntFormat, f: TglBitmapFormat;
7346 FormatDesc: TFormatDescriptor;
7351 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
7352 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
7353 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
7355 IntFormat := tfEmpty;
7356 for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do
7357 if (TFormatDescriptor.Get(f).glInternalFormat = TempIntFormat) then begin
7358 IntFormat := FormatDesc.Format;
7362 // Getting data from OpenGL
7363 FormatDesc := TFormatDescriptor.Get(IntFormat);
7364 GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
7366 if FormatDesc.IsCompressed then
7367 glGetCompressedTexImage(Target, 0, Temp)
7369 glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
7370 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
7377 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7378 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
7380 BuildWithGlu, PotTex, TexRec: Boolean;
7383 if Assigned(Data) then begin
7384 // Check Texture Size
7385 if (aTestTextureSize) then begin
7386 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7388 if ((Height > TexSize) or (Width > TexSize)) then
7389 raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7391 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
7392 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE_ARB);
7394 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7395 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7399 SetupParameters(BuildWithGlu);
7400 UploadData(Target, BuildWithGlu);
7401 glAreTexturesResident(1, @fID, @fIsResident);
7405 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7406 function TglBitmap2D.FlipHorz: Boolean;
7409 TempDestData, DestData, SourceData: PByte;
7412 result := inherited FlipHorz;
7413 if Assigned(Data) then begin
7415 ImgSize := Height * fRowSize;
7416 GetMem(DestData, ImgSize);
7418 TempDestData := DestData;
7419 Dec(TempDestData, fRowSize + fPixelSize);
7420 for Row := 0 to Height -1 do begin
7421 Inc(TempDestData, fRowSize * 2);
7422 for Col := 0 to Width -1 do begin
7423 Move(SourceData^, TempDestData^, fPixelSize);
7424 Inc(SourceData, fPixelSize);
7425 Dec(TempDestData, fPixelSize);
7428 SetDataPointer(DestData, Format);
7437 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7438 function TglBitmap2D.FlipVert: Boolean;
7441 TempDestData, DestData, SourceData: PByte;
7443 result := inherited FlipVert;
7444 if Assigned(Data) then begin
7446 GetMem(DestData, Height * fRowSize);
7448 TempDestData := DestData;
7449 Inc(TempDestData, Width * (Height -1) * fPixelSize);
7450 for Row := 0 to Height -1 do begin
7451 Move(SourceData^, TempDestData^, fRowSize);
7452 Dec(TempDestData, fRowSize);
7453 Inc(SourceData, fRowSize);
7455 SetDataPointer(DestData, Format);
7464 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7465 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7466 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7468 TMatrixItem = record
7473 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
7474 TglBitmapToNormalMapRec = Record
7476 Heights: array of Single;
7477 MatrixU : array of TMatrixItem;
7478 MatrixV : array of TMatrixItem;
7482 ONE_OVER_255 = 1 / 255;
7484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7485 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
7489 with FuncRec do begin
7491 Source.Data.r * LUMINANCE_WEIGHT_R +
7492 Source.Data.g * LUMINANCE_WEIGHT_G +
7493 Source.Data.b * LUMINANCE_WEIGHT_B;
7494 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
7498 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7499 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
7502 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
7505 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7506 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
7508 TVec = Array[0..2] of Single;
7515 function GetHeight(X, Y: Integer): Single;
7517 with FuncRec do begin
7518 X := Max(0, Min(Size.X -1, X));
7519 Y := Max(0, Min(Size.Y -1, Y));
7520 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
7525 with FuncRec do begin
7526 with PglBitmapToNormalMapRec(Args)^ do begin
7528 for Idx := Low(MatrixU) to High(MatrixU) do
7529 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
7532 for Idx := Low(MatrixU) to High(MatrixU) do
7533 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
7535 Vec[0] := -du * Scale;
7536 Vec[1] := -dv * Scale;
7541 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
7542 if Len <> 0 then begin
7543 Vec[0] := Vec[0] * Len;
7544 Vec[1] := Vec[1] * Len;
7545 Vec[2] := Vec[2] * Len;
7549 Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
7550 Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
7551 Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
7555 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7556 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
7558 Rec: TglBitmapToNormalMapRec;
7560 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
7562 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
7563 Matrix[Index].X := X;
7564 Matrix[Index].Y := Y;
7565 Matrix[Index].W := W;
7571 if not FormatIsUncompressed(InternalFormat) then
7572 raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_FORMAT);
7575 if aScale > 100 then
7577 else if aScale < -100 then
7580 Rec.Scale := aScale;
7582 SetLength(Rec.Heights, Width * Height);
7586 SetLength(Rec.MatrixU, 2);
7587 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
7588 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
7590 SetLength(Rec.MatrixV, 2);
7591 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
7592 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
7596 SetLength(Rec.MatrixU, 6);
7597 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
7598 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
7599 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
7600 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
7601 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
7602 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
7604 SetLength(Rec.MatrixV, 6);
7605 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
7606 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
7607 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
7608 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
7609 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
7610 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
7614 SetLength(Rec.MatrixU, 6);
7615 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
7616 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
7617 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
7618 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
7619 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
7620 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
7622 SetLength(Rec.MatrixV, 6);
7623 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
7624 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
7625 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
7626 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
7627 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
7628 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
7632 SetLength(Rec.MatrixU, 20);
7633 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
7634 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
7635 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
7636 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
7637 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
7638 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
7639 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
7640 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
7641 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
7642 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
7643 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
7644 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
7645 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
7646 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
7647 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
7648 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
7649 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
7650 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
7651 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
7652 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
7654 SetLength(Rec.MatrixV, 20);
7655 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
7656 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
7657 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
7658 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
7659 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
7660 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
7661 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
7662 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
7663 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
7664 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
7665 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
7666 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
7667 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
7668 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
7669 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
7670 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
7671 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
7672 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
7673 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
7674 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
7679 if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
7680 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, PtrInt(@Rec))
7682 AddFunc(glBitmapToNormalMapPrepareFunc, false, PtrInt(@Rec));
7683 AddFunc(glBitmapToNormalMapFunc, false, PtrInt(@Rec));
7685 SetLength(Rec.Heights, 0);
7698 procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
7703 if Height > 1 then begin
7704 // extract first line of the data
7705 Size := FormatGetImageSize(glBitmapPosition(Width), Format);
7706 GetMem(pTemp, Size);
7708 Move(Data^, pTemp^, Size);
7715 inherited SetDataPointer(pTemp, Format, Width);
7717 if FormatIsUncompressed(Format) then begin
7718 fUnmapFunc := FormatGetUnMapFunc(Format);
7719 fGetPixelFunc := GetPixel1DUnmap;
7724 procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
7729 Inc(pTemp, Pos.X * fPixelSize);
7731 fUnmapFunc(pTemp, Pixel);
7735 function TglBitmap1D.FlipHorz: Boolean;
7738 pTempDest, pDest, pSource: pByte;
7740 result := inherited FlipHorz;
7742 if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin
7745 GetMem(pDest, fRowSize);
7749 Inc(pTempDest, fRowSize);
7750 for Col := 0 to Width -1 do begin
7751 Move(pSource^, pTempDest^, fPixelSize);
7753 Inc(pSource, fPixelSize);
7754 Dec(pTempDest, fPixelSize);
7757 SetDataPointer(pDest, InternalFormat);
7767 procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
7770 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
7771 glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data)
7775 if BuildWithGlu then
7776 gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data)
7778 glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data);
7781 if (FreeDataAfterGenTexture) then
7786 procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean);
7788 BuildWithGlu, TexRec: Boolean;
7789 glFormat, glInternalFormat, glType: Cardinal;
7792 if Assigned(Data) then begin
7793 // Check Texture Size
7794 if (TestTextureSize) then begin
7795 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7797 if (Width > TexSize) then
7798 raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7800 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7801 (Target = GL_TEXTURE_RECTANGLE_ARB);
7803 if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7804 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7809 SetupParameters(BuildWithGlu);
7810 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
7812 UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
7815 glAreTexturesResident(1, @fID, @fIsResident);
7820 procedure TglBitmap1D.AfterConstruction;
7824 Target := GL_TEXTURE_1D;
7828 { TglBitmapCubeMap }
7830 procedure TglBitmapCubeMap.AfterConstruction;
7834 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
7835 raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
7837 SetWrap; // set all to GL_CLAMP_TO_EDGE
7838 Target := GL_TEXTURE_CUBE_MAP;
7839 fGenMode := GL_REFLECTION_MAP;
7843 procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean);
7845 inherited Bind (EnableTextureUnit);
7847 if EnableTexCoordsGen then begin
7848 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
7849 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
7850 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
7851 glEnable(GL_TEXTURE_GEN_S);
7852 glEnable(GL_TEXTURE_GEN_T);
7853 glEnable(GL_TEXTURE_GEN_R);
7858 procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean);
7860 glFormat, glInternalFormat, glType: Cardinal;
7861 BuildWithGlu: Boolean;
7864 // Check Texture Size
7865 if (TestTextureSize) then begin
7866 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
7868 if ((Height > TexSize) or (Width > TexSize)) then
7869 raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
7871 if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
7872 raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
7876 if ID = 0 then begin
7878 SetupParameters(BuildWithGlu);
7881 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
7883 UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu);
7887 procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean);
7889 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
7893 procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen,
7894 DisableTextureUnit: Boolean);
7896 inherited Unbind (DisableTextureUnit);
7898 if DisableTexCoordsGen then begin
7899 glDisable(GL_TEXTURE_GEN_S);
7900 glDisable(GL_TEXTURE_GEN_T);
7901 glDisable(GL_TEXTURE_GEN_R);
7906 { TglBitmapNormalMap }
7909 TVec = Array[0..2] of Single;
7910 TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7912 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
7913 TglBitmapNormalMapRec = record
7915 Func: TglBitmapNormalMapGetVectorFunc;
7919 procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7922 Vec[1] := - (Position.Y + 0.5 - HalfSize);
7923 Vec[2] := - (Position.X + 0.5 - HalfSize);
7927 procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7929 Vec[0] := - HalfSize;
7930 Vec[1] := - (Position.Y + 0.5 - HalfSize);
7931 Vec[2] := Position.X + 0.5 - HalfSize;
7935 procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7937 Vec[0] := Position.X + 0.5 - HalfSize;
7939 Vec[2] := Position.Y + 0.5 - HalfSize;
7943 procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7945 Vec[0] := Position.X + 0.5 - HalfSize;
7946 Vec[1] := - HalfSize;
7947 Vec[2] := - (Position.Y + 0.5 - HalfSize);
7951 procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7953 Vec[0] := Position.X + 0.5 - HalfSize;
7954 Vec[1] := - (Position.Y + 0.5 - HalfSize);
7959 procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7961 Vec[0] := - (Position.X + 0.5 - HalfSize);
7962 Vec[1] := - (Position.Y + 0.5 - HalfSize);
7963 Vec[2] := - HalfSize;
7967 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
7972 with FuncRec do begin
7973 with PglBitmapNormalMapRec (CustomData)^ do begin
7974 Func(Vec, Position, HalfSize);
7977 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
7978 if Len <> 0 then begin
7979 Vec[0] := Vec[0] * Len;
7980 Vec[1] := Vec[1] * Len;
7981 Vec[2] := Vec[2] * Len;
7984 // Scale Vector and AddVectro
7985 Vec[0] := Vec[0] * 0.5 + 0.5;
7986 Vec[1] := Vec[1] * 0.5 + 0.5;
7987 Vec[2] := Vec[2] * 0.5 + 0.5;
7991 Dest.Red := Round(Vec[0] * 255);
7992 Dest.Green := Round(Vec[1] * 255);
7993 Dest.Blue := Round(Vec[2] * 255);
7998 procedure TglBitmapNormalMap.AfterConstruction;
8002 fGenMode := GL_NORMAL_MAP;
8006 procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer;
8007 TestTextureSize: Boolean);
8009 Rec: TglBitmapNormalMapRec;
8010 SizeRec: TglBitmapPixelPosition;
8012 Rec.HalfSize := Size div 2;
8014 FreeDataAfterGenTexture := false;
8016 SizeRec.Fields := [ffX, ffY];
8021 Rec.Func := glBitmapNormalMapPosX;
8022 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8023 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize);
8026 Rec.Func := glBitmapNormalMapNegX;
8027 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8028 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize);
8031 Rec.Func := glBitmapNormalMapPosY;
8032 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8033 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize);
8036 Rec.Func := glBitmapNormalMapNegY;
8037 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8038 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize);
8041 Rec.Func := glBitmapNormalMapPosZ;
8042 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8043 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize);
8046 Rec.Func := glBitmapNormalMapNegZ;
8047 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
8048 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize);
8053 glBitmapSetDefaultFormat(tfEmpty);
8054 glBitmapSetDefaultMipmap(mmMipmap);
8055 glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
8056 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
8058 glBitmapSetDefaultFreeDataAfterGenTexture(true);
8059 glBitmapSetDefaultDeleteTextureOnFree (true);
8061 TFormatDescriptor.Init;
8064 TFormatDescriptor.Finalize;