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 ////////////////////////////////////////////////////////////////////////////////////////////////////
593 TglBitmapPixelDesc = packed record
596 GreenRange: Cardinal;
597 GreenShift: Shortint;
600 AlphaRange: Cardinal;
601 AlphaShift: Shortint;
603 PglBitmapPixelDesc = ^TglBitmapPixelDesc;
605 ////////////////////////////////////////////////////////////////////////////////////////////////////
606 TglBitmapPixelData = packed record
611 PixelDesc: TglBitmapPixelDesc;
614 ////////////////////////////////////////////////////////////////////////////////////////////////////
615 TglBitmapFormatDesc = packed record
617 InternalFormat: Cardinal;
621 ////////////////////////////////////////////////////////////////////////////////////////////////////
622 TglBitmapPixelPositionFields = set of (ffX, ffY);
623 TglBitmapPixelPosition = record
624 Fields : TglBitmapPixelPositionFields;
629 ////////////////////////////////////////////////////////////////////////////////////////////////////
631 TglBitmapFunctionRec = record
633 Size: TglBitmapPixelPosition;
634 Position: TglBitmapPixelPosition;
635 Source: TglBitmapPixelData;
636 Dest: TglBitmapPixelData;
639 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
641 ////////////////////////////////////////////////////////////////////////////////////////////////////
642 TglBitmapFileType = (
643 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
644 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
648 TglBitmapFileTypes = set of TglBitmapFileType;
655 TglBitmapNormalMapFunc = (
675 //tfLuminance6Alpha2,
677 //tfLuminance12Alpha4,
678 //tfLuminance12Alpha12,
679 //tfLuminance16Alpha16,
717 ////////////////////////////////////////////////////////////////////////////////////////////////////
718 TglBitmapGetPixel = procedure(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData) of object;
719 TglBitmapSetPixel = procedure(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData) of object;
721 TglBitmapMapFunc = procedure(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
722 TglBitmapUnMapFunc = procedure(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData);
724 ////////////////////////////////////////////////////////////////////////////////////////////////////
725 TglBitmapFormatDescriptor = class(TObject)
728 class function GetFormat: TglBitmapFormat; virtual; abstract;
729 class function GetPixelDesc: TglBitmapPixelDesc; virtual; abstract;
730 class function GetFormatDesc: TglBitmapFormatDesc; virtual; abstract;
732 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); virtual; abstract;
733 class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); virtual; abstract;
736 class function WithoutAlpha: TglBitmapFormat; virtual;
737 class function WithAlpha: TglBitmapFormat; virtual;
739 class function GetSize: Single; virtual; overload;
740 class function GetSize(const aSize: TglBitmapPixelPosition): Integer; virtual; overload;
741 class function GetColorCompCount: Integer; virtual;
743 class function IsEmpty: Boolean; virtual;
744 class function HasAlpha: Boolean; virtual;
745 class function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual;
747 class procedure PreparePixel(var aPixel: TglBitmapPixelData); virtual;
750 function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
751 function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
752 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
753 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
754 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
757 TglBitmapFormatDescClass = class of TglBitmapFormatDescriptor;
759 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
764 fAnisotropic: Integer;
765 fDeleteTextureOnFree: Boolean;
766 fFreeDataAfterGenTexture: Boolean;
768 fIsResident: Boolean;
769 fBorderColor: array[0..3] of Single;
771 fDimension: TglBitmapPixelPosition;
772 fMipMap: TglBitmapMipMap;
773 fFormat: TglBitmapFormat;
778 //TODO delete? fUnmapFunc: TglBitmapUnMapFunc;
779 //TODO delete? fMapFunc: TglBitmapMapFunc;
782 fFilterMin: Cardinal;
783 fFilterMag: Cardinal;
790 //TODO delete? fGetPixelFunc: TglBitmapGetPixel;
791 //TODO delete? fSetPixelFunc: TglBitmapSetPixel;
796 fCustomNameW: WideString;
797 fCustomData: Pointer;
800 function GetWidth: Integer; virtual;
801 function GetHeight: Integer; virtual;
803 function GetFileWidth: Integer; virtual;
804 function GetFileHeight: Integer; virtual;
807 procedure SetCustomData(const aValue: Pointer);
808 procedure SetCustomName(const aValue: String);
809 procedure SetCustomNameW(const aValue: WideString);
810 procedure SetDeleteTextureOnFree(const aValue: Boolean);
811 procedure SetFormat(const aValue: TglBitmapFormat);
812 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
813 procedure SetID(const aValue: Cardinal);
814 procedure SetMipMap(const aValue: TglBitmapMipMap);
815 procedure SetTarget(const aValue: Cardinal);
816 procedure SetAnisotropic(const aValue: Integer);
819 procedure SetupParameters(var aBuildWithGlu: Boolean);
820 procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
821 const aWidth: Integer = -1; const aHeight: Integer = -1); virtual;
822 procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
824 function FlipHorz: Boolean; virtual;
825 function FlipVert: Boolean; virtual;
827 property Width: Integer read GetWidth;
828 property Height: Integer read GetHeight;
830 property FileWidth: Integer read GetFileWidth;
831 property FileHeight: Integer read GetFileHeight;
834 property ID: Cardinal read fID write SetID;
835 property Target: Cardinal read fTarget write SetTarget;
836 property Format: TglBitmapFormat read fFormat write SetFormat;
837 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
838 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
840 property Filename: String read fFilename;
841 property CustomName: String read fCustomName write SetCustomName;
842 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
843 property CustomData: Pointer read fCustomData write SetCustomData;
845 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
846 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
848 property Dimension: TglBitmapPixelPosition read fDimension;
849 property Data: PByte read fData;
850 property IsResident: Boolean read fIsResident;
852 procedure AfterConstruction; override;
853 procedure BeforeDestruction; override;
856 procedure LoadFromFile(const aFilename: String);
857 procedure LoadFromStream(const aStream: TStream); virtual;
858 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
859 const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0);
861 procedure LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
862 procedure LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
866 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
867 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
870 function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt = 0): Boolean; overload;
871 function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
872 const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0): Boolean; overload;
876 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
877 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
878 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
879 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
880 const aArgs: PtrInt = 0): Boolean;
884 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
885 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
886 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
887 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
888 const aArgs: PtrInt = 0): Boolean;
889 function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil;
890 const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
891 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
892 const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
895 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0): Boolean; virtual;
896 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
897 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
898 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
900 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
901 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
902 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
904 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
905 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
906 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
908 function RemoveAlpha: Boolean; virtual;
911 function Clone: TglBitmap;
912 function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
913 procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
914 procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
918 procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
919 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
920 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
923 procedure SetFilter(const aMin, aMag: Cardinal);
925 const S: Cardinal = GL_CLAMP_TO_EDGE;
926 const T: Cardinal = GL_CLAMP_TO_EDGE;
927 const R: Cardinal = GL_CLAMP_TO_EDGE);
929 procedure GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData); virtual;
930 procedure SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData); virtual;
932 procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
933 procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
936 constructor Create; overload;
937 constructor Create(const aFileName: String); overload;
938 constructor Create(const aStream: TStream); overload;
939 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload;
940 constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0); overload;
942 constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
943 constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
946 {$IFDEF GLB_SUPPORT_PNG_READ}
947 function LoadPNG(const aStream: TStream): Boolean; virtual;
948 procedure SavePNG(const aStream: TStream); virtual;
950 {$IFDEF GLB_SUPPORT_JPEG_READ}
951 function LoadJPEG(const aStream: TStream): Boolean; virtual;
952 procedure SaveJPEG(const aStream: TStream); virtual;
954 function LoadBMP(const aStream: TStream): Boolean; virtual;
955 procedure SaveBMP(const aStream: TStream); virtual;
957 function LoadTGA(const aStream: TStream): Boolean; virtual;
958 procedure SaveTGA(const aStream: TStream); virtual;
960 function LoadDDS(const aStream: TStream): Boolean; virtual;
961 procedure SaveDDS(const aStream: TStream); virtual;
964 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
965 TglBitmap2D = class(TglBitmap)
968 fLines: array of PByte;
971 procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
972 procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
973 procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
974 procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
975 procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
976 procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
979 function GetScanline(const aIndex: Integer): Pointer;
980 procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
981 const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
982 procedure UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
986 property Scanline[const aIndex: Integer]: Pointer read GetScanline;
988 procedure AfterConstruction; override;
990 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
991 procedure GetDataFromTexture;
992 procedure GenTexture(const aTestTextureSize: Boolean = true); override;
994 function FlipHorz: Boolean; override;
995 function FlipVert: Boolean; override;
997 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
998 const aScale: Single = 2; const aUseAlpha: Boolean = false);
1002 TglBitmapCubeMap = class(TglBitmap2D)
1007 procedure GenTexture(TestTextureSize: Boolean = true); reintroduce;
1009 procedure AfterConstruction; override;
1011 procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true);
1013 procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = true); reintroduce; virtual;
1014 procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = true); reintroduce; virtual;
1018 TglBitmapNormalMap = class(TglBitmapCubeMap)
1020 procedure AfterConstruction; override;
1022 procedure GenerateNormalMap(Size: Integer = 32; TestTextureSize: Boolean = true);
1026 TglBitmap1D = class(TglBitmap)
1028 procedure GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1030 procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override;
1031 procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
1036 procedure AfterConstruction; override;
1039 function FlipHorz: Boolean; override;
1042 procedure GenTexture(TestTextureSize: Boolean = true); override;
1047 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1049 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1050 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1051 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1052 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1053 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1054 procedure glBitmapSetDefaultWrap(
1055 const S: Cardinal = GL_CLAMP_TO_EDGE;
1056 const T: Cardinal = GL_CLAMP_TO_EDGE;
1057 const R: Cardinal = GL_CLAMP_TO_EDGE);
1059 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1060 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1061 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1062 function glBitmapGetDefaultFormat: TglBitmapFormat;
1063 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1064 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1066 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1069 glBitmapDefaultDeleteTextureOnFree: Boolean;
1070 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1071 glBitmapDefaultFormat: TglBitmapFormat;
1072 glBitmapDefaultMipmap: TglBitmapMipMap;
1073 glBitmapDefaultFilterMin: Cardinal;
1074 glBitmapDefaultFilterMag: Cardinal;
1075 glBitmapDefaultWrapS: Cardinal;
1076 glBitmapDefaultWrapT: Cardinal;
1077 glBitmapDefaultWrapR: Cardinal;
1080 function CreateGrayPalette: HPALETTE;
1089 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1090 TBitfieldFormat = class(TObject)
1092 fRedShift: ShortInt;
1093 fGreenShift: ShortInt;
1094 fBlueShift: ShortInt;
1095 fAlphaShift: ShortInt;
1097 fRedRange: Cardinal;
1098 fGreenRange: Cardinal;
1099 fBlueRange: Cardinal;
1100 fAlphaRange: Cardinal;
1106 function GetSize: Integer;
1107 procedure SetAlphaMask(aValue: UInt64);
1108 procedure SetAlphaRange(aValue: Cardinal);
1109 procedure SetAlphaShift(aValue: ShortInt);
1110 procedure SetBlueMask(aValue: UInt64);
1111 procedure SetBlueRange(aValue: Cardinal);
1112 procedure SetBlueShift(aValue: ShortInt);
1113 procedure SetGreenMask(aValue: UInt64);
1114 procedure SetGreenRange(aValue: Cardinal);
1115 procedure SetGreenShift(aValue: ShortInt);
1116 procedure SetRedMask(aValue: UInt64);
1117 procedure SetRedRange(aValue: Cardinal);
1118 procedure SetRedShift(aValue: ShortInt);
1120 procedure CalcShiftAndRange(aMask: UInt64; out aRange: Cardinal; out aShift: ShortInt);
1122 property RedShift: ShortInt read fRedShift write SetRedShift;
1123 property GreenShift: ShortInt read fGreenShift write SetGreenShift;
1124 property BlueShift: ShortInt read fBlueShift write SetBlueShift;
1125 property AlphaShift: ShortInt read fAlphaShift write SetAlphaShift;
1127 property RedRange: Cardinal read fRedRange write SetRedRange;
1128 property GreenRange: Cardinal read fGreenRange write SetGreenRange;
1129 property BlueRange: Cardinal read fBlueRange write SetBlueRange;
1130 property AlphaRange: Cardinal read fAlphaRange write SetAlphaRange;
1132 property RedMask: UInt64 read fRedMask write SetRedMask;
1133 property GreenMask: UInt64 read fGreenMask write SetGreenMask;
1134 property BlueMask: UInt64 read fBlueMask write SetBlueMask;
1135 property AlphaMask: UInt64 read fAlphaMask write SetAlphaMask;
1137 property Size: Integer read GetSize;
1139 procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte);
1140 procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); overload;
1141 procedure Unmap(const aData: UInt64; var aPixel: TglBitmapPixelData); overload;
1144 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1145 TfdEmpty = class(TglBitmapFormatDescriptor)
1147 class function GetFormat: TglBitmapFormat; override;
1148 class function GetPixelDesc: TglBitmapPixelDesc; override;
1149 class function GetFormatDesc: TglBitmapFormatDesc; override;
1151 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override;
1152 class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override;
1155 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1156 TfdLuminance8 = class(TglBitmapFormatDescriptor)
1158 class function GetFormat: TglBitmapFormat; override;
1159 class function GetPixelDesc: TglBitmapPixelDesc; override;
1160 class function GetFormatDesc: TglBitmapFormatDesc; override;
1161 class function WithAlpha: TglBitmapFormat; override;
1163 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override;
1164 class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override;
1167 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1168 TfdLuminance8Alpha8 = class(TglBitmapFormatDescriptor)
1170 class function GetFormat: TglBitmapFormat; override;
1171 class function GetPixelDesc: TglBitmapPixelDesc; override;
1172 class function GetFormatDesc: TglBitmapFormatDesc; override;
1173 class function WithoutAlpha: TglBitmapFormat; override;
1175 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override;
1176 class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override;
1179 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1180 TfdRGB5 = class(TglBitmapFormatDescriptor)
1182 class function GetFormat: TglBitmapFormat; override;
1183 class function GetPixelDesc: TglBitmapPixelDesc; override;
1184 class function GetFormatDesc: TglBitmapFormatDesc; override;
1185 class function WithAlpha: TglBitmapFormat; override;
1187 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override;
1188 class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override;
1191 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1192 TfdRGB8 = class(TglBitmapFormatDescriptor)
1194 class function GetFormat: TglBitmapFormat; override;
1195 class function GetPixelDesc: TglBitmapPixelDesc; override;
1196 class function GetFormatDesc: TglBitmapFormatDesc; override;
1197 class function WithAlpha: TglBitmapFormat; override;
1199 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override;
1200 class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override;
1203 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1204 TfdRGB5A1 = class(TglBitmapFormatDescriptor)
1206 class function GetFormat: TglBitmapFormat; override;
1207 class function GetPixelDesc: TglBitmapPixelDesc; override;
1208 class function GetFormatDesc: TglBitmapFormatDesc; override;
1209 class function WithoutAlpha: TglBitmapFormat; override;
1211 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override;
1212 class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override;
1215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1216 TfdRGBA8 = class(TglBitmapFormatDescriptor)
1218 class function GetFormat: TglBitmapFormat; override;
1219 class function GetPixelDesc: TglBitmapPixelDesc; override;
1220 class function GetFormatDesc: TglBitmapFormatDesc; override;
1221 class function WithoutAlpha: TglBitmapFormat; override;
1223 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override;
1224 class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override;
1227 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1228 TfdBGR8 = class(TglBitmapFormatDescriptor)
1230 class function GetFormat: TglBitmapFormat; override;
1231 class function GetPixelDesc: TglBitmapPixelDesc; override;
1232 class function GetFormatDesc: TglBitmapFormatDesc; override;
1233 class function WithAlpha: TglBitmapFormat; override;
1235 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override;
1236 class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override;
1239 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1240 TfdBGRA8 = class(TglBitmapFormatDescriptor)
1242 class function GetFormat: TglBitmapFormat; override;
1243 class function GetPixelDesc: TglBitmapPixelDesc; override;
1244 class function GetFormatDesc: TglBitmapFormatDesc; override;
1245 class function WithoutAlpha: TglBitmapFormat; override;
1247 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override;
1248 class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override;
1252 LUMINANCE_WEIGHT_R = 0.30;
1253 LUMINANCE_WEIGHT_G = 0.59;
1254 LUMINANCE_WEIGHT_B = 0.11;
1256 ALPHA_WEIGHT_R = 0.30;
1257 ALPHA_WEIGHT_G = 0.59;
1258 ALPHA_WEIGHT_B = 0.11;
1260 UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
1262 FORMAT_DESCRIPTORS: array[TglBitmapFormat] of TglBitmapFormatDescClass = (
1266 TfdLuminance8Alpha8,
1279 {$REGION Private Helper}
1280 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1281 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1283 result.Fields := [];
1286 result.Fields := result.Fields + [ffX];
1288 result.Fields := result.Fields + [ffY];
1290 result.X := Max(0, X);
1291 result.Y := Max(0, Y);
1294 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1295 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1297 //TODO Supported File Formats!
1298 result := [ftDDS, ftTGA, ftBMP];
1300 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1302 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1303 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1304 tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
1305 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1306 tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
1307 tfDepth16, tfDepth24, tfDepth32]
1309 result := result + [ftPNG];
1312 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1314 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1315 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1316 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1317 tfDepth16, tfDepth24, tfDepth32]
1319 result := result + [ftJPEG];
1323 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1324 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1325 tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
1326 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1327 tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
1328 tfDepth16, tfDepth24, tfDepth32]
1330 result := result + [ftDDS, ftTGA, ftBMP];
1334 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1335 function IsPowerOfTwo(aNumber: Integer): Boolean;
1337 while (aNumber and 1) = 0 do
1338 aNumber := aNumber shr 1;
1339 result := aNumber = 1;
1342 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1343 function GetTopMostBit(aBitSet: UInt64): Integer;
1346 while aBitSet > 0 do begin
1348 aBitSet := aBitSet shr 1;
1352 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1353 function CountSetBits(aBitSet: UInt64): Integer;
1356 while aBitSet > 0 do begin
1357 if (aBitSet and 1) = 1 then
1359 aBitSet := aBitSet shr 1;
1364 //TODO check _ARB functions and constants
1367 {$IFNDEF GLB_NO_NATIVE_GL}
1368 procedure ReadOpenGLExtensions;
1374 MajorVersion, MinorVersion: Integer;
1377 procedure TrimVersionString(Buffer: AnsiString; var Major, Minor: Integer);
1384 Separator := Pos(AnsiString('.'), Buffer);
1386 if (Separator > 1) and (Separator < Length(Buffer)) and
1387 (Buffer[Separator - 1] in ['0'..'9']) and
1388 (Buffer[Separator + 1] in ['0'..'9']) then begin
1391 while (Separator > 0) and (Buffer[Separator] in ['0'..'9']) do
1394 Delete(Buffer, 1, Separator);
1395 Separator := Pos(AnsiString('.'), Buffer) + 1;
1397 while (Separator <= Length(Buffer)) and (AnsiChar(Buffer[Separator]) in ['0'..'9']) do
1400 Delete(Buffer, Separator, 255);
1401 Separator := Pos(AnsiString('.'), Buffer);
1403 Major := StrToInt(Copy(String(Buffer), 1, Separator - 1));
1404 Minor := StrToInt(Copy(String(Buffer), Separator + 1, 1));
1409 function CheckExtension(const Extension: AnsiString): Boolean;
1413 ExtPos := Pos(Extension, Buffer);
1414 result := ExtPos > 0;
1417 result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
1421 function glLoad (aFunc: pAnsiChar): pointer;
1424 result := glXGetProcAddress(aFunc);
1426 result := wglGetProcAddress(aFunc);
1433 Context := wglGetCurrentContext;
1435 if Context <> gLastContext then begin
1436 gLastContext := Context;
1440 Buffer := glGetString(GL_VERSION);
1441 TrimVersionString(Buffer, MajorVersion, MinorVersion);
1443 GL_VERSION_1_2 := false;
1444 GL_VERSION_1_3 := false;
1445 GL_VERSION_1_4 := false;
1446 GL_VERSION_2_0 := false;
1448 if MajorVersion = 1 then begin
1449 if MinorVersion >= 1 then begin
1450 if MinorVersion >= 2 then
1451 GL_VERSION_1_2 := true;
1453 if MinorVersion >= 3 then
1454 GL_VERSION_1_3 := true;
1456 if MinorVersion >= 4 then
1457 GL_VERSION_1_4 := true;
1461 if MajorVersion >= 2 then begin
1462 GL_VERSION_1_2 := true;
1463 GL_VERSION_1_3 := true;
1464 GL_VERSION_1_4 := true;
1465 GL_VERSION_2_0 := true;
1469 Buffer := glGetString(GL_EXTENSIONS);
1470 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
1471 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
1472 GL_ARB_texture_compression := CheckExtension('GL_ARB_texture_compression');
1473 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
1474 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
1475 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
1476 GL_EXT_bgra := CheckExtension('GL_EXT_bgra');
1477 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
1478 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
1479 GL_EXT_texture_compression_s3tc := CheckExtension('GL_EXT_texture_compression_s3tc');
1480 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
1481 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
1482 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
1483 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
1484 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
1487 if GL_VERSION_1_3 then begin
1489 glCompressedTexImage1D := glLoad('glCompressedTexImage1D');
1490 glCompressedTexImage2D := glLoad('glCompressedTexImage2D');
1491 glGetCompressedTexImage := glLoad('glGetCompressedTexImage');
1495 // Try loading Extension
1496 glCompressedTexImage1D := glLoad('glCompressedTexImage1DARB');
1497 glCompressedTexImage2D := glLoad('glCompressedTexImage2DARB');
1498 glGetCompressedTexImage := glLoad('glGetCompressedTexImageARB');
1509 function CreateGrayPalette: HPALETTE;
1514 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
1516 Pal.palVersion := $300;
1517 Pal.palNumEntries := 256;
1520 {$DEFINE GLB_TEMPRANGECHECK}
1524 for Idx := 0 to 256 - 1 do begin
1525 Pal.palPalEntry[Idx].peRed := Idx;
1526 Pal.palPalEntry[Idx].peGreen := Idx;
1527 Pal.palPalEntry[Idx].peBlue := Idx;
1528 Pal.palPalEntry[Idx].peFlags := 0;
1531 {$IFDEF GLB_TEMPRANGECHECK}
1532 {$UNDEF GLB_TEMPRANGECHECK}
1536 result := CreatePalette(Pal^);
1543 (* TODO GLB_SDL_IMAGE
1544 {$IFDEF GLB_SDL_IMAGE}
1545 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
1547 result := TStream(context^.unknown.data1).Seek(offset, whence);
1550 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
1552 result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
1555 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
1557 result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
1560 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
1565 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
1567 result := SDL_AllocRW;
1569 if result = nil then
1570 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
1572 result^.seek := glBitmapRWseek;
1573 result^.read := glBitmapRWread;
1574 result^.write := glBitmapRWwrite;
1575 result^.close := glBitmapRWclose;
1576 result^.unknown.data1 := Stream;
1582 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
1584 glBitmap: TglBitmap2D;
1590 if Instance = 0 then
1591 Instance := HInstance;
1593 if (LoadFromRes) then
1594 glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName)
1597 glBitmap := TglBitmap2D.Create(FileName);
1600 glBitmap.DeleteTextureOnFree := false;
1601 glBitmap.FreeDataAfterGenTexture := false;
1602 glBitmap.GenTexture(true);
1603 if (glBitmap.ID > 0) then begin
1604 Texture := glBitmap.ID;
1612 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
1614 CM: TglBitmapCubeMap;
1619 if Instance = 0 then
1620 Instance := HInstance;
1623 CM := TglBitmapCubeMap.Create;
1625 CM.DeleteTextureOnFree := false;
1629 if (LoadFromRes) then
1630 CM.LoadFromResource(Instance, PositiveX)
1633 CM.LoadFromFile(PositiveX);
1634 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
1637 if (LoadFromRes) then
1638 CM.LoadFromResource(Instance, NegativeX)
1641 CM.LoadFromFile(NegativeX);
1642 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
1645 if (LoadFromRes) then
1646 CM.LoadFromResource(Instance, PositiveY)
1649 CM.LoadFromFile(PositiveY);
1650 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
1653 if (LoadFromRes) then
1654 CM.LoadFromResource(Instance, NegativeY)
1657 CM.LoadFromFile(NegativeY);
1658 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
1661 if (LoadFromRes) then
1662 CM.LoadFromResource(Instance, PositiveZ)
1665 CM.LoadFromFile(PositiveZ);
1666 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
1669 if (LoadFromRes) then
1670 CM.LoadFromResource(Instance, NegativeZ)
1673 CM.LoadFromFile(NegativeZ);
1674 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
1683 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
1685 NM: TglBitmapNormalMap;
1689 NM := TglBitmapNormalMap.Create;
1691 NM.DeleteTextureOnFree := false;
1692 NM.GenerateNormalMap(Size);
1702 {$REGION default Setter and Gettter}
1703 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1704 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1706 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
1709 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1710 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1712 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
1715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1716 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1718 glBitmapDefaultMipmap := aValue;
1721 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1722 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1724 glBitmapDefaultFormat := aFormat;
1727 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1728 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1730 glBitmapDefaultFilterMin := aMin;
1731 glBitmapDefaultFilterMag := aMag;
1734 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1735 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
1737 glBitmapDefaultWrapS := S;
1738 glBitmapDefaultWrapT := T;
1739 glBitmapDefaultWrapR := R;
1742 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1743 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1745 result := glBitmapDefaultDeleteTextureOnFree;
1748 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1749 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1751 result := glBitmapDefaultFreeDataAfterGenTextures;
1754 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1755 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1757 result := glBitmapDefaultMipmap;
1760 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1761 function glBitmapGetDefaultFormat: TglBitmapFormat;
1763 result := glBitmapDefaultFormat;
1766 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1767 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1769 aMin := glBitmapDefaultFilterMin;
1770 aMag := glBitmapDefaultFilterMag;
1773 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1774 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1776 S := glBitmapDefaultWrapS;
1777 T := glBitmapDefaultWrapT;
1778 R := glBitmapDefaultWrapR;
1782 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1783 //TCustomFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1784 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1785 procedure TBitfieldFormat.SetAlphaMask(aValue: UInt64);
1787 if fAlphaMask = aValue then Exit;
1788 fAlphaMask := aValue;
1789 CalcShiftAndRange(fAlphaMask, fAlphaRange, fAlphaShift);
1792 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1793 function TBitfieldFormat.GetSize: Integer;
1798 (fRedRange shl fRedShift) or
1799 (fGreenRange shl fGreenShift) or
1800 (fBlueRange shl fBlueShift) or
1801 (fAlphaRange shl fAlphaShift);
1802 result := Trunc(GetTopMostBit(tmp) / 8);
1805 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1806 procedure TBitfieldFormat.SetAlphaRange(aValue: Cardinal);
1808 if fAlphaRange = aValue then Exit;
1809 fAlphaRange := aValue;
1810 fAlphaMask := fAlphaRange shl fAlphaShift;
1813 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1814 procedure TBitfieldFormat.SetAlphaShift(aValue: ShortInt);
1816 if fAlphaShift = aValue then Exit;
1817 fAlphaShift := aValue;
1818 fAlphaMask := fAlphaRange shl fAlphaShift;
1821 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1822 procedure TBitfieldFormat.SetBlueMask(aValue: UInt64);
1824 if fBlueMask = aValue then Exit;
1825 fBlueMask := aValue;
1826 CalcShiftAndRange(fBlueMask, fBlueRange, fBlueShift);
1829 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1830 procedure TBitfieldFormat.SetBlueRange(aValue: Cardinal);
1832 if fBlueRange = aValue then Exit;
1833 fBlueRange := aValue;
1834 fBlueMask := fBlueRange shl fBlueShift;
1837 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1838 procedure TBitfieldFormat.SetBlueShift(aValue: ShortInt);
1840 if fBlueShift = aValue then Exit;
1841 fBlueShift := aValue;
1842 fBlueMask := fBlueRange shl fBlueShift;
1845 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1846 procedure TBitfieldFormat.SetGreenMask(aValue: UInt64);
1848 if fGreenMask = aValue then Exit;
1849 fGreenMask := aValue;
1850 CalcShiftAndRange(fGreenMask, fGreenRange, fGreenShift);
1853 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1854 procedure TBitfieldFormat.SetGreenRange(aValue: Cardinal);
1856 if fGreenRange = aValue then Exit;
1857 fGreenRange := aValue;
1858 fGreenMask := fGreenRange shl fGreenShift;
1861 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1862 procedure TBitfieldFormat.SetGreenShift(aValue: ShortInt);
1864 if fGreenShift = aValue then Exit;
1865 fGreenShift := aValue;
1866 fGreenMask := fGreenRange shl fGreenShift;
1869 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1870 procedure TBitfieldFormat.SetRedMask(aValue: UInt64);
1872 if fRedMask = aValue then Exit;
1874 CalcShiftAndRange(fRedMask, fRedRange, fRedShift);
1877 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1878 procedure TBitfieldFormat.SetRedRange(aValue: Cardinal);
1880 if fRedRange = aValue then Exit;
1881 fRedRange := aValue;
1882 fRedMask := fRedRange shl fRedShift;
1885 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1886 procedure TBitfieldFormat.SetRedShift(aValue: ShortInt);
1888 if fRedShift = aValue then Exit;
1889 fRedShift := aValue;
1890 fRedMask := fRedRange shl fRedShift;
1893 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1894 procedure TBitfieldFormat.CalcShiftAndRange(aMask: UInt64; out aRange: Cardinal;
1895 out aShift: ShortInt);
1901 while (aMask > 0) and ((aMask and 1) = 0) do begin
1903 aMask := aMask shr 1;
1906 while (aMask > 0) do begin
1907 aRange := aRange shl 1;
1908 aMask := aMask shr 1;
1913 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1914 procedure TBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte);
1922 ((aPixel.Red and fRedRange) shl fRedShift) or
1923 ((aPixel.Green and fGreenRange) shl fGreenShift) or
1924 ((aPixel.Blue and fBlueRange) shl fBlueShift) or
1925 ((aPixel.Alpha and fAlphaRange) shl fAlphaShift);
1929 2: PWord(aData)^ := data;
1930 4: PCardinal(aData)^ := data;
1931 8: PUInt64(aData)^ := data;
1936 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1937 procedure TBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData);
1947 2: data := PWord(aData)^;
1948 4: data := PCardinal(aData)^;
1949 8: data := PUInt64(aData)^;
1951 Unmap(data, aPixel);
1955 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1956 procedure TBitfieldFormat.Unmap(const aData: UInt64; var aPixel: TglBitmapPixelData);
1958 aPixel.Red := (aData shr fRedShift) and fRedRange;
1959 aPixel.Green := (aData shr fGreenShift) and fGreenRange;
1960 aPixel.Blue := (aData shr fBlueShift) and fBlueRange;
1961 aPixel.Alpha := (aData shr fAlphaShift) and fAlphaRange;
1964 {$REGION TglBitmapFormatDescriptor}
1965 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1966 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1967 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1968 class function TglBitmapFormatDescriptor.WithoutAlpha: TglBitmapFormat;
1970 if not HasAlpha then
1976 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1977 class function TglBitmapFormatDescriptor.WithAlpha: TglBitmapFormat;
1985 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1986 class function TglBitmapFormatDescriptor.GetSize: Single;
1990 with GetPixelDesc do begin
1992 (RedRange shl RedShift) or
1993 (GreenRange shl GreenShift) or
1994 (BlueRange shl BlueShift) or
1995 (AlphaRange shl AlphaShift);
1997 result := Trunc(GetTopMostBit(tmp) / 4) / 2;
2000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2001 class function TglBitmapFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
2005 if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
2006 w := Max(1, aSize.X);
2007 h := Max(1, aSize.Y);
2008 result := Ceil(w * h * GetSize);
2013 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2014 class function TglBitmapFormatDescriptor.GetColorCompCount: Integer;
2017 with GetPixelDesc do begin
2018 if (RedRange > 0) then
2020 if (GreenRange > 0) then
2022 if (BlueRange > 0) then
2024 if (AlphaRange > 0) then
2029 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2030 class function TglBitmapFormatDescriptor.IsEmpty: Boolean;
2032 result := (GetFormat = tfEmpty);
2035 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2036 class function TglBitmapFormatDescriptor.HasAlpha: Boolean;
2038 result := (GetPixelDesc.AlphaRange > 0);
2041 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2042 class function TglBitmapFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean;
2044 PixelDesc: TglBitmapPixelDesc;
2048 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
2049 raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
2051 PixelDesc := GetPixelDesc;
2052 with PixelDesc do begin
2053 if (aRedMask <> 0) and (aRedMask <> (RedRange shl RedShift)) then
2055 if (aGreenMask <> 0) and (aGreenMask <> (GreenRange shl GreenShift)) then
2057 if (aBlueMask <> 0) and (aBlueMask <> (BlueRange shl BlueShift)) then
2059 if (aAlphaMask <> 0) and (aAlphaMask <> (AlphaRange shl AlphaShift)) then
2065 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2066 class procedure TglBitmapFormatDescriptor.PreparePixel(var aPixel: TglBitmapPixelData);
2068 FillChar(aPixel, SizeOf(aPixel), 0);
2069 aPixel.PixelDesc := GetPixelDesc;
2070 with aPixel.PixelDesc do begin
2071 aPixel.Red := RedRange;
2072 aPixel.Green := GreenRange;
2073 aPixel.Blue := BlueRange;
2074 aPixel.Alpha := AlphaRange;
2080 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2081 //TfdEmpty////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2082 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2083 class function TfdEmpty.GetFormat: TglBitmapFormat;
2088 class function TfdEmpty.GetPixelDesc: TglBitmapPixelDesc;
2090 with result do begin
2091 RedRange := $00000000; RedShift := 0;
2092 GreenRange := $00000000; GreenShift := 0;
2093 BlueRange := $00000000; BlueShift := 0;
2094 AlphaRange := $00000000; AlphaShift := 0;
2098 class function TfdEmpty.GetFormatDesc: TglBitmapFormatDesc;
2100 with result do begin
2102 InternalFormat := 0;
2107 class procedure TfdEmpty.Map(const aPixel: TglBitmapPixelData; var aData: PByte );
2109 raise EglBitmapException.Create('format does not support mapping');
2112 class procedure TfdEmpty.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData);
2114 raise EglBitmapException.Create('format does not support unmapping');
2118 {$REGION TfdLuminance8}
2119 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2120 //TfdLuminance8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2121 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2122 class function TfdLuminance8.GetFormat: TglBitmapFormat;
2127 class function TfdLuminance8.GetPixelDesc: TglBitmapPixelDesc;
2129 with result do begin
2130 RedRange := $000000FF; RedShift := 0;
2131 GreenRange := $000000FF; GreenShift := 0;
2132 BlueRange := $000000FF; BlueShift := 0;
2133 AlphaRange := $00000000; AlphaShift := 0;
2137 class function TfdLuminance8.GetFormatDesc: TglBitmapFormatDesc;
2139 with result do begin
2140 Format := GL_LUMINANCE;
2141 InternalFormat := GL_LUMINANCE8;
2142 DataType := GL_UNSIGNED_BYTE;
2146 class function TfdLuminance8.WithAlpha: TglBitmapFormat;
2148 result := tfLuminance8Alpha8;
2151 class procedure TfdLuminance8.Map(const aPixel: TglBitmapPixelData; var aData: PByte);
2154 aPixel.Red * LUMINANCE_WEIGHT_R +
2155 aPixel.Green * LUMINANCE_WEIGHT_G +
2156 aPixel.Blue * LUMINANCE_WEIGHT_B);
2160 class procedure TfdLuminance8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData);
2162 aPixel.Red := aData^;
2163 aPixel.Green := aData^;
2164 aPixel.Blue := aData^;
2170 {$REGION TfdLuminance8Alpha8}
2171 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2172 //TfdLuminance8Alpha8/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2173 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2174 class function TfdLuminance8Alpha8.GetFormat: TglBitmapFormat;
2176 result := tfLuminance8Alpha8;
2179 class function TfdLuminance8Alpha8.GetPixelDesc: TglBitmapPixelDesc;
2181 with result do begin
2182 RedRange := $000000FF; RedShift := 0;
2183 GreenRange := $000000FF; GreenShift := 0;
2184 BlueRange := $000000FF; BlueShift := 0;
2185 AlphaRange := $000000FF; AlphaShift := 8;
2189 class function TfdLuminance8Alpha8.GetFormatDesc: TglBitmapFormatDesc;
2191 with result do begin
2192 Format := GL_LUMINANCE_ALPHA;
2193 InternalFormat := GL_LUMINANCE8_ALPHA8;
2194 DataType := GL_UNSIGNED_BYTE;
2198 class function TfdLuminance8Alpha8.WithoutAlpha: TglBitmapFormat;
2200 result := tfLuminance8;
2203 class procedure TfdLuminance8Alpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte);
2206 aPixel.Red * LUMINANCE_WEIGHT_R +
2207 aPixel.Green * LUMINANCE_WEIGHT_G +
2208 aPixel.Blue * LUMINANCE_WEIGHT_B);
2211 aData^ := aPixel.Alpha;
2215 class procedure TfdLuminance8Alpha8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData);
2217 aPixel.Red := aData^;
2218 aPixel.Green := aData^;
2219 aPixel.Blue := aData^;
2222 aPixel.Alpha := aData^;
2227 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2228 //TfdRGB5/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2229 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2230 class function TfdRGB5.GetFormat: TglBitmapFormat;
2235 class function TfdRGB5.GetPixelDesc: TglBitmapPixelDesc;
2237 with result do begin
2238 RedRange := $0000001F; RedShift := 0;
2239 GreenRange := $0000001F; GreenShift := 5;
2240 BlueRange := $0000001F; BlueShift := 10;
2241 AlphaRange := $00000000; AlphaShift := 0;
2245 class function TfdRGB5.GetFormatDesc: TglBitmapFormatDesc;
2247 with result do begin
2249 InternalFormat := GL_RGB5;
2250 DataType := GL_UNSIGNED_SHORT_5_5_5_1;
2254 class function TfdRGB5.WithAlpha: TglBitmapFormat;
2259 class procedure TfdRGB5.Map(const aPixel: TglBitmapPixelData; var aData: PByte);
2262 ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
2263 ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
2264 ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift);
2268 class procedure TfdRGB5.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData);
2270 aPixel.Red := (PWord(aData)^ shr aPixel.PixelDesc.RedShift) and aPixel.PixelDesc.RedRange;
2271 aPixel.Green := (PWord(aData)^ shr aPixel.PixelDesc.GreenShift) and aPixel.PixelDesc.GreenRange;
2272 aPixel.Blue := (PWord(aData)^ shr aPixel.PixelDesc.BlueShift) and aPixel.PixelDesc.BlueRange;
2278 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2279 //TfdRGB8/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2280 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2281 class function TfdRGB8.GetFormat: TglBitmapFormat;
2286 class function TfdRGB8.GetPixelDesc: TglBitmapPixelDesc;
2288 with result do begin
2289 RedRange := $000000FF; RedShift := 0;
2290 GreenRange := $000000FF; GreenShift := 8;
2291 BlueRange := $000000FF; BlueShift := 16;
2292 AlphaRange := $00000000; AlphaShift := 0;
2296 class function TfdRGB8.GetFormatDesc: TglBitmapFormatDesc;
2298 with result do begin
2299 Format := GL_LUMINANCE;
2300 InternalFormat := GL_LUMINANCE8;
2301 DataType := GL_UNSIGNED_BYTE;
2305 class function TfdRGB8.WithAlpha: TglBitmapFormat;
2310 class procedure TfdRGB8.Map(const aPixel: TglBitmapPixelData; var aData: PByte);
2312 aData^ := aPixel.Red;
2314 aData^ := aPixel.Green;
2316 aData^ := aPixel.Blue;
2320 class procedure TfdRGB8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData);
2322 aPixel.Red := aData^;
2324 aPixel.Green := aData^;
2326 aPixel.Blue := aData^;
2332 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2333 //TfdRGB5A1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2334 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2335 class function TfdRGB5A1.GetFormat: TglBitmapFormat;
2340 class function TfdRGB5A1.GetPixelDesc: TglBitmapPixelDesc;
2342 with result do begin
2343 RedRange := $0000001F; RedShift := 0;
2344 GreenRange := $0000001F; GreenShift := 5;
2345 BlueRange := $0000001F; BlueShift := 10;
2346 AlphaRange := $00000001; AlphaShift := 15;
2350 class function TfdRGB5A1.GetFormatDesc: TglBitmapFormatDesc;
2352 with result do begin
2354 InternalFormat := GL_RGB5_A1;
2355 DataType := GL_UNSIGNED_SHORT_5_5_5_1;
2359 class function TfdRGB5A1.WithoutAlpha: TglBitmapFormat;
2361 //TODO result := tfRGB5;
2364 class procedure TfdRGB5A1.Map(const aPixel: TglBitmapPixelData; var aData: PByte);
2367 ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
2368 ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
2369 ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or
2370 ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift);
2374 class procedure TfdRGB5A1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData);
2376 aPixel.Red := (PWord(aData)^ shr aPixel.PixelDesc.RedShift) and aPixel.PixelDesc.RedRange;
2377 aPixel.Green := (PWord(aData)^ shr aPixel.PixelDesc.GreenShift) and aPixel.PixelDesc.GreenRange;
2378 aPixel.Blue := (PWord(aData)^ shr aPixel.PixelDesc.BlueShift) and aPixel.PixelDesc.BlueRange;
2379 aPixel.Alpha := (PWord(aData)^ shr aPixel.PixelDesc.AlphaShift) and aPixel.PixelDesc.AlphaRange;
2384 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2385 //TfdRGBA8////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2386 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2387 class function TfdRGBA8.GetFormat: TglBitmapFormat;
2392 class function TfdRGBA8.GetPixelDesc: TglBitmapPixelDesc;
2394 with result do begin
2395 RedRange := $000000FF; RedShift := 0;
2396 GreenRange := $000000FF; GreenShift := 8;
2397 BlueRange := $000000FF; BlueShift := 16;
2398 AlphaRange := $000000FF; AlphaShift := 24;
2402 class function TfdRGBA8.GetFormatDesc: TglBitmapFormatDesc;
2404 with result do begin
2406 InternalFormat := GL_RGB8;
2407 DataType := GL_UNSIGNED_BYTE;
2411 class function TfdRGBA8.WithoutAlpha: TglBitmapFormat;
2416 class procedure TfdRGBA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte);
2418 aData^ := aPixel.Red;
2420 aData^ := aPixel.Green;
2422 aData^ := aPixel.Blue;
2424 aData^ := aPixel.Alpha;
2428 class procedure TfdRGBA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData);
2430 aPixel.Red := aData^;
2432 aPixel.Green := aData^;
2434 aPixel.Blue := aData^;
2436 aPixel.Alpha := aData^;
2442 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2443 //TfdBGR8/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2444 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2445 class function TfdBGR8.GetFormat: TglBitmapFormat;
2450 class function TfdBGR8.GetPixelDesc: TglBitmapPixelDesc;
2452 with result do begin
2453 RedRange := $000000FF; RedShift := 16;
2454 GreenRange := $000000FF; GreenShift := 8;
2455 BlueRange := $000000FF; BlueShift := 0;
2456 AlphaRange := $00000000; AlphaShift := 0;
2460 class function TfdBGR8.GetFormatDesc: TglBitmapFormatDesc;
2462 with result do begin
2464 InternalFormat := GL_RGB8;
2465 DataType := GL_UNSIGNED_BYTE;
2469 class function TfdBGR8.WithAlpha: TglBitmapFormat;
2474 class procedure TfdBGR8.Map(const aPixel: TglBitmapPixelData; var aData: PByte);
2476 aData^ := aPixel.Blue;
2478 aData^ := aPixel.Green;
2480 aData^ := aPixel.Red;
2484 class procedure TfdBGR8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData);
2486 aPixel.Blue := aData^;
2488 aPixel.Green := aData^;
2490 aPixel.Red := aData^;
2496 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2497 //TfdBGRA8////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2498 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2499 class function TfdBGRA8.GetFormat: TglBitmapFormat;
2504 class function TfdBGRA8.GetPixelDesc: TglBitmapPixelDesc;
2506 with result do begin
2507 RedRange := $000000FF; RedShift := 16;
2508 GreenRange := $000000FF; GreenShift := 8;
2509 BlueRange := $000000FF; BlueShift := 0;
2510 AlphaRange := $000000FF; AlphaShift := 24;
2514 class function TfdBGRA8.GetFormatDesc: TglBitmapFormatDesc;
2516 with result do begin
2518 InternalFormat := GL_RGBA8;
2519 DataType := GL_UNSIGNED_BYTE;
2523 class function TfdBGRA8.WithoutAlpha: TglBitmapFormat;
2528 class procedure TfdBGRA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte);
2530 aData^ := aPixel.Blue;
2532 aData^ := aPixel.Green;
2534 aData^ := aPixel.Red;
2536 aData^ := aPixel.Alpha;
2540 class procedure TfdBGRA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData);
2542 aPixel.Blue := aData^;
2544 aPixel.Green := aData^;
2546 aPixel.Red := aData^;
2548 aPixel.Alpha := aData^;
2554 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2555 //TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2556 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2557 procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
2559 with aFuncRec do begin
2560 if (Source.PixelDesc.RedRange > 0) then
2561 Dest.Red := Source.Red;
2562 if (Source.PixelDesc.GreenRange > 0) then
2563 Dest.Green := Source.Green;
2564 if (Source.PixelDesc.BlueRange > 0) then
2565 Dest.Blue := Source.Blue;
2566 if (Source.PixelDesc.AlphaRange > 0) then
2567 Dest.Alpha := Source.Alpha;
2571 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2572 procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
2574 with aFuncRec do begin
2575 if (Source.PixelDesc.RedRange > 0) then
2576 Dest.Red := Round(Dest.PixelDesc.RedRange * Source.Red / Source.PixelDesc.RedRange);
2577 if (Source.PixelDesc.GreenRange > 0) then
2578 Dest.Green := Round(Dest.PixelDesc.GreenRange * Source.Green / Source.PixelDesc.GreenRange);
2579 if (Source.PixelDesc.BlueRange > 0) then
2580 Dest.Blue := Round(Dest.PixelDesc.BlueRange * Source.Blue / Source.PixelDesc.BlueRange);
2581 if (Source.PixelDesc.AlphaRange > 0) then
2582 Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Source.Alpha / Source.PixelDesc.AlphaRange);
2586 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2587 procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
2590 with PglBitmapPixelDesc(Args)^ do begin
2591 if (Source.PixelDesc.RedRange > 0) then
2592 Dest.Red := Source.Red shr RedShift;
2593 if (Source.PixelDesc.GreenRange > 0) then
2594 Dest.Green := Source.Green shr GreenShift;
2595 if (Source.PixelDesc.BlueRange > 0) then
2596 Dest.Blue := Source.Blue shr BlueShift;
2597 if (Source.PixelDesc.AlphaRange > 0) then
2598 Dest.Alpha := Source.Alpha shr AlphaShift;
2602 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2603 procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
2605 with aFuncRec do begin
2606 Dest.Red := Source.Red;
2607 Dest.Green := Source.Green;
2608 Dest.Blue := Source.Blue;
2609 Dest.Alpha := Source.Alpha;
2610 if (Args and $1 > 0) then begin
2611 Dest.Red := Dest.Red xor Dest.PixelDesc.RedRange;
2612 Dest.Green := Dest.Green xor Dest.PixelDesc.GreenRange;
2613 Dest.Blue := Dest.Blue xor Dest.PixelDesc.BlueRange;
2615 if (Args and $2 > 0) then begin
2616 Dest.Alpha := Dest.Alpha xor Dest.PixelDesc.AlphaRange;
2621 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2622 procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
2624 PglBitmapPixelData = ^TglBitmapPixelData;
2626 with aFuncRec do begin
2627 Dest.Red := PglBitmapPixelData(Args)^.Red;
2628 Dest.Green := PglBitmapPixelData(Args)^.Green;
2629 Dest.Blue := PglBitmapPixelData(Args)^.Blue;
2630 Dest.Alpha := PglBitmapPixelData(Args)^.Alpha;
2634 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2635 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
2639 with FuncRec do begin
2640 if (FuncRec.Args = 0) then begin //source has no alpha
2642 Source.Red / Source.PixelDesc.RedRange * ALPHA_WEIGHT_R +
2643 Source.Green / Source.PixelDesc.GreenRange * ALPHA_WEIGHT_G +
2644 Source.Blue / Source.PixelDesc.BlueRange * ALPHA_WEIGHT_B;
2645 Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Temp);
2647 Dest.Alpha := Round(Source.Alpha / Source.PixelDesc.AlphaRange * Dest.PixelDesc.AlphaRange);
2651 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2652 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
2654 PglBitmapPixelData = ^TglBitmapPixelData;
2656 with FuncRec do begin
2657 Dest.Red := Source.Red;
2658 Dest.Green := Source.Green;
2659 Dest.Blue := Source.Blue;
2661 with PglBitmapPixelData(Args)^ do
2662 if ((Dest.Red <= Red ) and (Dest.Red >= PixelDesc.RedRange ) and
2663 (Dest.Green <= Green) and (Dest.Green >= PixelDesc.GreenRange) and
2664 (Dest.Blue <= Blue ) and (Dest.Blue >= PixelDesc.BlueRange )) then
2667 Dest.Alpha := Dest.PixelDesc.AlphaRange;
2671 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2672 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
2674 PglBitmapPixelData = ^TglBitmapPixelData;
2676 with FuncRec do begin
2677 Dest.Red := Source.Red;
2678 Dest.Green := Source.Green;
2679 Dest.Blue := Source.Blue;
2680 with PglBitmapPixelData(Args)^ do
2681 Dest.Alpha := Alpha;
2685 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2686 procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
2689 TRGBPix = array [0..2] of byte;
2693 while aWidth > 0 do begin
2694 Temp := PRGBPix(aData)^[0];
2695 PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
2696 PRGBPix(aData)^[2] := Temp;
2706 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2707 //TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2708 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2710 function TglBitmap.GetWidth: Integer;
2712 if (ffX in fDimension.Fields) then
2713 result := fDimension.X
2718 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2719 function TglBitmap.GetHeight: Integer;
2721 if (ffY in fDimension.Fields) then
2722 result := fDimension.Y
2727 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2728 function TglBitmap.GetFileWidth: Integer;
2730 result := Max(1, Width);
2733 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2734 function TglBitmap.GetFileHeight: Integer;
2736 result := Max(1, Height);
2741 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2742 procedure TglBitmap.SetCustomData(const aValue: Pointer);
2744 if fCustomData = aValue then
2746 fCustomData := aValue;
2749 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2750 procedure TglBitmap.SetCustomName(const aValue: String);
2752 if fCustomName = aValue then
2754 fCustomName := aValue;
2757 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2758 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
2760 if fCustomNameW = aValue then
2762 fCustomNameW := aValue;
2765 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2766 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
2768 if fDeleteTextureOnFree = aValue then
2770 fDeleteTextureOnFree := aValue;
2773 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2774 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
2776 if fFormat = aValue then
2778 if (FORMAT_DESCRIPTORS[Format].GetSize <> FORMAT_DESCRIPTORS[aValue].GetSize) then
2779 raise EglBitmapUnsupportedFormatFormat.Create('SetInternalFormat - ' + UNSUPPORTED_FORMAT);
2780 SetDataPointer(Data, aValue, Width, Height);
2783 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2784 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
2786 if fFreeDataAfterGenTexture = aValue then
2788 fFreeDataAfterGenTexture := aValue;
2791 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2792 procedure TglBitmap.SetID(const aValue: Cardinal);
2794 if fID = aValue then
2799 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2800 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
2802 if fMipMap = aValue then
2807 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2808 procedure TglBitmap.SetTarget(const aValue: Cardinal);
2810 if fTarget = aValue then
2815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2816 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
2818 MaxAnisotropic: Integer;
2820 fAnisotropic := aValue;
2821 if (ID > 0) then begin
2822 if GL_EXT_texture_filter_anisotropic then begin
2823 if fAnisotropic > 0 then begin
2825 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
2826 if aValue > MaxAnisotropic then
2827 fAnisotropic := MaxAnisotropic;
2828 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
2837 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2838 procedure TglBitmap.CreateID;
2841 glDeleteTextures(1, @fID);
2842 glGenTextures(1, @fID);
2846 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2847 procedure TglBitmap.SetupParameters(var aBuildWithGlu: Boolean);
2849 // Set Up Parameters
2850 SetWrap(fWrapS, fWrapT, fWrapR);
2851 SetFilter(fFilterMin, fFilterMag);
2852 SetAnisotropic(fAnisotropic);
2853 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
2855 // Mip Maps Generation Mode
2856 aBuildWithGlu := false;
2857 if (MipMap = mmMipmap) then begin
2858 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
2859 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
2861 aBuildWithGlu := true;
2862 end else if (MipMap = mmMipmapGlu) then
2863 aBuildWithGlu := true;
2866 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2867 procedure TglBitmap.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
2868 const aWidth: Integer; const aHeight: Integer);
2872 if (Data <> aData) then begin
2873 if (Assigned(Data)) then
2878 FillChar(fDimension, SizeOf(fDimension), 0);
2879 if not Assigned(fData) then begin
2884 if aWidth <> -1 then begin
2885 fDimension.Fields := fDimension.Fields + [ffX];
2886 fDimension.X := aWidth;
2889 if aHeight <> -1 then begin
2890 fDimension.Fields := fDimension.Fields + [ffY];
2891 fDimension.Y := aHeight;
2894 s := FORMAT_DESCRIPTORS[aFormat].GetSize;
2896 fPixelSize := Ceil(s);
2897 fRowSize := Ceil(s * aWidth);
2901 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2902 function TglBitmap.FlipHorz: Boolean;
2907 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2908 function TglBitmap.FlipVert: Boolean;
2913 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2914 //TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2916 procedure TglBitmap.AfterConstruction;
2918 inherited AfterConstruction;
2922 fIsResident := false;
2924 fFormat := glBitmapGetDefaultFormat;
2925 fMipMap := glBitmapDefaultMipmap;
2926 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
2927 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
2929 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
2930 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
2933 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2934 procedure TglBitmap.BeforeDestruction;
2936 SetDataPointer(nil, tfEmpty);
2937 if (fID > 0) and fDeleteTextureOnFree then
2938 glDeleteTextures(1, @fID);
2939 inherited BeforeDestruction;
2942 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2943 procedure TglBitmap.LoadFromFile(const aFilename: String);
2947 fFilename := aFilename;
2948 fs := TFileStream.Create(fFilename, fmOpenRead);
2957 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2958 procedure TglBitmap.LoadFromStream(const aStream: TStream);
2960 {$IFDEF GLB_SUPPORT_PNG_READ}
2961 if not LoadPNG(aStream) then
2963 {$IFDEF GLB_SUPPORT_JPEG_READ}
2964 if not LoadJPEG(aStream) then
2966 if not LoadDDS(aStream) then
2967 if not LoadTGA(aStream) then
2968 if not LoadBMP(aStream) then
2969 raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
2972 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2973 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
2974 const aFormat: TglBitmapFormat; const aArgs: PtrInt);
2979 size := FORMAT_DESCRIPTORS[aFormat].GetSize(aSize);
2980 GetMem(tmpData, size);
2982 FillChar(tmpData^, size, #$FF);
2983 SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y);
2988 AddFunc(Self, aFunc, false, Format, aArgs);
2992 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2993 procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
2995 rs: TResourceStream;
3000 if not Assigned(ResType) then begin
3001 TempPos := Pos('.', Resource);
3002 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
3003 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
3004 TempResType := PChar(ResTypeStr);
3006 TempResType := ResType
3008 rs := TResourceStream.Create(Instance, Resource, TempResType);
3016 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3017 procedure TglBitmap.LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
3019 rs: TResourceStream;
3021 rs := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
3030 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3031 procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
3035 fs := TFileStream.Create(aFileName, fmCreate);
3038 SaveToStream(fs, aFileType);
3044 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3045 procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
3048 {$IFDEF GLB_SUPPORT_PNG_WRITE}
3049 ftPNG: SavePng(aStream);
3051 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
3052 ftJPEG: SaveJPEG(aStream);
3054 ftDDS: SaveDDS(aStream);
3055 ftTGA: SaveTGA(aStream);
3056 ftBMP: SaveBMP(aStream);
3060 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3061 function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt): Boolean;
3063 result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
3066 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3067 function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
3068 const aFormat: TglBitmapFormat; const aArgs: PtrInt): Boolean;
3070 DestData, TmpData, SourceData: pByte;
3071 TempHeight, TempWidth: Integer;
3072 SourceFD, DestFD: TglBitmapFormatDescClass;
3074 FuncRec: TglBitmapFunctionRec;
3076 Assert(Assigned(Data));
3077 Assert(Assigned(aSource));
3078 Assert(Assigned(aSource.Data));
3081 if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
3082 SourceFD := FORMAT_DESCRIPTORS[aSource.Format];
3083 DestFD := FORMAT_DESCRIPTORS[aFormat];
3085 // inkompatible Formats so CreateTemp
3086 if (SourceFD.GetSize <> DestFD.GetSize) then
3087 aCreateTemp := true;
3090 TempHeight := Max(1, aSource.Height);
3091 TempWidth := Max(1, aSource.Width);
3093 FuncRec.Sender := Self;
3094 FuncRec.Args := aArgs;
3097 if aCreateTemp then begin
3098 GetMem(TmpData, Ceil(FORMAT_DESCRIPTORS[aFormat].GetSize * TempHeight * TempWidth));
3099 DestData := TmpData;
3104 SourceFD.PreparePixel(FuncRec.Source);
3105 DestFD.PreparePixel (FuncRec.Dest);
3107 FuncRec.Size := aSource.Dimension;
3108 FuncRec.Position.Fields := FuncRec.Size.Fields;
3110 if {FormatIsUncompressed(Source.InternalFormat)} true then begin
3111 SourceData := aSource.Data;
3112 FuncRec.Position.Y := 0;
3113 while FuncRec.Position.Y < TempHeight do begin
3114 FuncRec.Position.X := 0;
3115 while FuncRec.Position.X < TempWidth do begin
3116 SourceFD.Unmap(SourceData, FuncRec.Source);
3118 DestFD.Map(FuncRec.Dest, DestData);
3119 inc(FuncRec.Position.X);
3121 inc(FuncRec.Position.Y);
3125 // Compressed Images
3126 FuncRec.Position.Y := 0;
3127 while FuncRec.Position.Y < TempHeight do begin
3128 FuncRec.Position.X := 0;
3129 while FuncRec.Position.X < TempWidth do begin
3131 fGetPixelFunc(FuncRec.Position, FuncRec.Source);
3135 MapFunc(FuncRec.Dest, dest);
3136 Inc(FuncRec.Position.X);
3138 Inc(FuncRec.Position.Y);
3143 // Updating Image or InternalFormat
3145 SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height)
3146 else if (aFormat <> fFormat) then
3159 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3160 function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
3162 Row, RowSize: Integer;
3163 SourceData, TmpData: PByte;
3165 Pix: TglBitmapPixelData;
3166 FormatDesc: TglBitmapFormatDescriptor;
3168 function GetRowPointer(Row: Integer): pByte;
3170 result := Surface.pixels;
3171 Inc(result, Row * RowSize);
3178 if not FormatIsUncompressed(InternalFormat) then
3179 raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
3182 FormatDesc := FORMAT_DESCRIPTORS[Format];
3183 if Assigned(Data) then begin
3184 case Trunc(FormatDesc.GetSize) of
3190 raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
3192 FormatDesc.PreparePixel(Pix);
3193 with Pix.PixelDesc do
3194 Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
3195 RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift);
3198 RowSize := Ceil(FileWidth * FormatDesc.GetSize);
3200 for Row := 0 to FileHeight -1 do begin
3201 TmpData := GetRowPointer(Row);
3202 if Assigned(TmpData) then begin
3203 Move(SourceData^, TmpData^, RowSize);
3204 inc(SourceData, RowSize);
3211 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3212 function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
3214 pSource, pData, pTempData: PByte;
3215 Row, RowSize, TempWidth, TempHeight: Integer;
3216 IntFormat, f: TglBitmapInternalFormat;
3217 FormatDesc: TglBitmapFormatDescriptor;
3219 function GetRowPointer(Row: Integer): pByte;
3221 result := Surface^.pixels;
3222 Inc(result, Row * RowSize);
3227 if (Assigned(Surface)) then begin
3228 with Surface^.format^ do begin
3229 IntFormat := tfEmpty;
3230 for f := Low(f) to High(f) do begin
3231 if FORMAT_DESCRIPTORS[f].MaskMatch(RMask, GMask, BMask, AMask) then begin
3236 if (IntFormat = tfEmpty) then
3237 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
3240 FormatDesc := FORMAT_DESCRIPTORS[IntFormat];
3241 TempWidth := Surface^.w;
3242 TempHeight := Surface^.h;
3243 RowSize := Trunc(TempWidth * FormatDesc.GetSize);
3244 GetMem(pData, TempHeight * RowSize);
3247 for Row := 0 to TempHeight -1 do begin
3248 pSource := GetRowPointer(Row);
3249 if (Assigned(pSource)) then begin
3250 Move(pSource^, pTempData^, RowSize);
3251 Inc(pTempData, RowSize);
3254 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
3263 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3264 function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
3266 Row, Col, AlphaInterleave: Integer;
3267 pSource, pDest: PByte;
3269 function GetRowPointer(Row: Integer): pByte;
3271 result := aSurface.pixels;
3272 Inc(result, Row * Width);
3277 if Assigned(Data) then begin
3278 if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
3279 aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
3281 AlphaInterleave := 0;
3284 AlphaInterleave := 1;
3286 AlphaInterleave := 3;
3290 for Row := 0 to Height -1 do begin
3291 pDest := GetRowPointer(Row);
3292 if Assigned(pDest) then begin
3293 for Col := 0 to Width -1 do begin
3294 Inc(pSource, AlphaInterleave);
3306 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3307 function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
3311 bmp := TglBitmap2D.Create;
3313 bmp.AssignFromSurface(Surface);
3314 result := AddAlphaFromGlBitmap(bmp, Func, CustomData);
3322 //TODO rework & test
3323 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3324 function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
3327 pSource, pData: PByte;
3330 if Assigned(Data) then begin
3331 if Assigned(aBitmap) then begin
3332 aBitmap.Width := Width;
3333 aBitmap.Height := Height;
3336 tfAlpha8, ifLuminance, ifDepth8:
3338 Bitmap.PixelFormat := pf8bit;
3339 Bitmap.Palette := CreateGrayPalette;
3342 Bitmap.PixelFormat := pf15bit;
3344 Bitmap.PixelFormat := pf16bit;
3346 Bitmap.PixelFormat := pf24bit;
3348 Bitmap.PixelFormat := pf32bit;
3350 raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
3354 for Row := 0 to FileHeight -1 do begin
3355 pData := Bitmap.Scanline[Row];
3357 Move(pSource^, pData^, fRowSize);
3358 Inc(pSource, fRowSize);
3360 // swap RGB(A) to BGR(A)
3361 if InternalFormat in [ifRGB8, ifRGBA8] then
3362 SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8);
3370 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3371 function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
3373 pSource, pData, pTempData: PByte;
3374 Row, RowSize, TempWidth, TempHeight: Integer;
3375 IntFormat: TglBitmapInternalFormat;
3379 if (Assigned(Bitmap)) then begin
3380 case Bitmap.PixelFormat of
3382 IntFormat := ifLuminance;
3384 IntFormat := ifRGB5A1;
3386 IntFormat := ifR5G6B5;
3388 IntFormat := ifBGR8;
3390 IntFormat := ifBGRA8;
3392 raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
3395 TempWidth := Bitmap.Width;
3396 TempHeight := Bitmap.Height;
3398 RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
3400 GetMem(pData, TempHeight * RowSize);
3404 for Row := 0 to TempHeight -1 do begin
3405 pSource := Bitmap.Scanline[Row];
3407 if (Assigned(pSource)) then begin
3408 Move(pSource^, pTempData^, RowSize);
3409 Inc(pTempData, RowSize);
3413 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
3423 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3424 function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
3426 Row, Col, AlphaInterleave: Integer;
3427 pSource, pDest: PByte;
3431 if Assigned(Data) then begin
3432 if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin
3433 if Assigned(Bitmap) then begin
3434 Bitmap.PixelFormat := pf8bit;
3435 Bitmap.Palette := CreateGrayPalette;
3436 Bitmap.Width := Width;
3437 Bitmap.Height := Height;
3439 case InternalFormat of
3441 AlphaInterleave := 1;
3443 AlphaInterleave := 3;
3445 AlphaInterleave := 0;
3451 for Row := 0 to Height -1 do begin
3452 pDest := Bitmap.Scanline[Row];
3454 if Assigned(pDest) then begin
3455 for Col := 0 to Width -1 do begin
3456 Inc(pSource, AlphaInterleave);
3470 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3471 function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
3475 tex := TglBitmap2D.Create;
3477 tex.AssignFromBitmap(Bitmap);
3478 result := AddAlphaFromglBitmap(tex, Func, CustomData);
3484 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3485 function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar;
3486 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
3488 RS: TResourceStream;
3493 if Assigned(ResType) then
3494 TempResType := ResType
3497 TempPos := Pos('.', Resource);
3498 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
3499 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
3500 TempResType := PChar(ResTypeStr);
3503 RS := TResourceStream.Create(Instance, Resource, TempResType);
3505 result := AddAlphaFromStream(RS, Func, CustomData);
3511 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3512 function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
3513 const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
3515 RS: TResourceStream;
3517 RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
3519 result := AddAlphaFromStream(RS, Func, CustomData);
3526 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3527 function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
3530 if not FormatIsUncompressed(InternalFormat) then
3531 raise EglBitmapUnsupportedFormatFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_FORMAT);
3533 result := AddFunc(Self, aFunc, false, FORMAT_DESCRIPTORS[Format].WithAlpha, aArgs);
3536 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3537 function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
3541 FS := TFileStream.Create(FileName, fmOpenRead);
3543 result := AddAlphaFromStream(FS, aFunc, aArgs);
3549 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3550 function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
3554 tex := TglBitmap2D.Create(aStream);
3556 result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
3562 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3563 function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
3565 DestData, DestData2, SourceData: pByte;
3566 TempHeight, TempWidth: Integer;
3567 SourceFD, DestFD: TglBitmapFormatDescClass;
3569 FuncRec: TglBitmapFunctionRec;
3573 Assert(Assigned(Data));
3574 Assert(Assigned(aBitmap));
3575 Assert(Assigned(aBitmap.Data));
3577 if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
3578 result := ConvertTo(FORMAT_DESCRIPTORS[Format].WithAlpha);
3579 if not Assigned(aFunc) then
3580 aFunc := glBitmapAlphaFunc;
3582 SourceFD := FORMAT_DESCRIPTORS[aBitmap.Format];
3583 DestFD := FORMAT_DESCRIPTORS[Format];
3586 TempHeight := aBitmap.FileHeight;
3587 TempWidth := aBitmap.FileWidth;
3589 FuncRec.Sender := Self;
3590 FuncRec.Args := aArgs;
3591 FuncRec.Size := Dimension;
3592 FuncRec.Position.Fields := FuncRec.Size.Fields;
3593 FuncRec.Args := PtrInt(SourceFD.HasAlpha) and 1;
3597 SourceData := aBitmap.Data;
3600 SourceFD.PreparePixel(FuncRec.Source);
3601 DestFD.PreparePixel (FuncRec.Dest);
3603 FuncRec.Position.Y := 0;
3604 while FuncRec.Position.Y < TempHeight do begin
3605 FuncRec.Position.X := 0;
3606 while FuncRec.Position.X < TempWidth do begin
3607 SourceFD.Unmap(SourceData, FuncRec.Source);
3608 DestFD.Unmap (DestData, FuncRec.Dest);
3610 DestFD.Map(FuncRec.Dest, DestData2);
3611 inc(FuncRec.Position.X);
3613 inc(FuncRec.Position.Y);
3619 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3620 function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
3622 result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
3625 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3626 function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
3628 PixelData: TglBitmapPixelData;
3630 FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData);
3631 result := AddAlphaFromColorKeyFloat(
3632 aRed / PixelData.PixelDesc.RedRange,
3633 aGreen / PixelData.PixelDesc.GreenRange,
3634 aBlue / PixelData.PixelDesc.BlueRange,
3635 aDeviation / Max(PixelData.PixelDesc.RedRange, Max(PixelData.PixelDesc.GreenRange, PixelData.PixelDesc.BlueRange)));
3638 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3639 function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
3641 TempR, TempG, TempB: Cardinal;
3642 PixelData: TglBitmapPixelData;
3644 FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData);
3645 with PixelData.PixelDesc do begin
3646 TempR := Trunc(RedRange * aDeviation);
3647 TempG := Trunc(GreenRange * aDeviation);
3648 TempB := Trunc(BlueRange * aDeviation);
3650 PixelData.Red := Min(RedRange, Trunc(RedRange * aRed) + TempR);
3651 RedRange := Max(0, Trunc(RedRange * aRed) - TempR);
3652 PixelData.Green := Min(GreenRange, Trunc(GreenRange * aGreen) + TempG);
3653 GreenRange := Max(0, Trunc(GreenRange * aGreen) - TempG);
3654 PixelData.Blue := Min(BlueRange, Trunc(BlueRange * aBlue) + TempB);
3655 BlueRange := Max(0, Trunc(BlueRange * aBlue) - TempB);
3656 PixelData.Alpha := 0;
3659 result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, PtrInt(@PixelData));
3662 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3663 function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
3665 result := AddAlphaFromValueFloat(aAlpha / $FF);
3668 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3669 function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
3671 PixelData: TglBitmapPixelData;
3673 FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData);
3674 result := AddAlphaFromValueFloat(aAlpha / PixelData.PixelDesc.AlphaRange);
3677 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3678 function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
3680 PixelData: TglBitmapPixelData;
3682 FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData);
3683 with PixelData.PixelDesc do
3684 PixelData.Alpha := Min(AlphaRange, Max(0, Round(AlphaRange * aAlpha)));
3685 result := AddAlphaFromFunc(glBitmapValueAlphaFunc, PtrInt(@PixelData));
3688 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3689 function TglBitmap.RemoveAlpha: Boolean;
3691 FormatDesc: TglBitmapFormatDescClass;
3694 FormatDesc := FORMAT_DESCRIPTORS[Format];
3695 if Assigned(Data) then begin
3696 if not ({FormatDesc.IsUncompressed or }FormatDesc.HasAlpha) then
3697 raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_FORMAT);
3698 result := ConvertTo(FormatDesc.WithoutAlpha);
3702 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3703 function TglBitmap.Clone: TglBitmap;
3710 Temp := (ClassType.Create as TglBitmap);
3712 // copy texture data if assigned
3713 if Assigned(Data) then begin
3714 Size := FORMAT_DESCRIPTORS[Format].GetSize(fDimension);
3715 GetMem(TempPtr, Size);
3717 Move(Data^, TempPtr^, Size);
3718 Temp.SetDataPointer(TempPtr, Format, Width, Height);
3724 Temp.SetDataPointer(nil, Format, Width, Height);
3728 Temp.fTarget := Target;
3729 Temp.fFormat := Format;
3730 Temp.fMipMap := MipMap;
3731 Temp.fAnisotropic := Anisotropic;
3732 Temp.fBorderColor := fBorderColor;
3733 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
3734 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
3735 Temp.fFilterMin := fFilterMin;
3736 Temp.fFilterMag := fFilterMag;
3737 Temp.fWrapS := fWrapS;
3738 Temp.fWrapT := fWrapT;
3739 Temp.fWrapR := fWrapR;
3740 Temp.fFilename := fFilename;
3741 Temp.fCustomName := fCustomName;
3742 Temp.fCustomNameW := fCustomNameW;
3743 Temp.fCustomData := fCustomData;
3752 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3753 function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
3755 SourceFD, DestFD: TglBitmapFormatDescClass;
3756 SourcePD, DestPD: TglBitmapPixelData;
3757 PixelDesc: TglBitmapPixelDesc;
3759 function CanCopyDirect: Boolean;
3762 ((SourcePD.PixelDesc.RedRange = DestPD.PixelDesc.RedRange) or (SourcePD.PixelDesc.RedRange = 0) or (DestPD.PixelDesc.RedRange = 0)) and
3763 ((SourcePD.PixelDesc.GreenRange = DestPD.PixelDesc.GreenRange) or (SourcePD.PixelDesc.GreenRange = 0) or (DestPD.PixelDesc.GreenRange = 0)) and
3764 ((SourcePD.PixelDesc.BlueRange = DestPD.PixelDesc.BlueRange) or (SourcePD.PixelDesc.BlueRange = 0) or (DestPD.PixelDesc.BlueRange = 0)) and
3765 ((SourcePD.PixelDesc.AlphaRange = DestPD.PixelDesc.AlphaRange) or (SourcePD.PixelDesc.AlphaRange = 0) or (DestPD.PixelDesc.AlphaRange = 0));
3768 function CanShift: Boolean;
3771 ((SourcePD.PixelDesc.RedRange >= DestPD.PixelDesc.RedRange ) or (SourcePD.PixelDesc.RedRange = 0) or (DestPD.PixelDesc.RedRange = 0)) and
3772 ((SourcePD.PixelDesc.GreenRange >= DestPD.PixelDesc.GreenRange) or (SourcePD.PixelDesc.GreenRange = 0) or (DestPD.PixelDesc.GreenRange = 0)) and
3773 ((SourcePD.PixelDesc.BlueRange >= DestPD.PixelDesc.BlueRange ) or (SourcePD.PixelDesc.BlueRange = 0) or (DestPD.PixelDesc.BlueRange = 0)) and
3774 ((SourcePD.PixelDesc.AlphaRange >= DestPD.PixelDesc.AlphaRange) or (SourcePD.PixelDesc.AlphaRange = 0) or (DestPD.PixelDesc.AlphaRange = 0));
3777 function GetShift(aSource, aDest: Cardinal) : ShortInt;
3780 while (aSource > aDest) and (aSource > 0) do begin
3782 aSource := aSource shr 1;
3787 if aFormat <> fFormat then begin
3788 SourceFD := FORMAT_DESCRIPTORS[Format];
3789 DestFD := FORMAT_DESCRIPTORS[aFormat];
3791 SourceFD.PreparePixel(SourcePD);
3792 DestFD.PreparePixel (DestPD);
3794 if CanCopyDirect then
3795 result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
3796 else if CanShift then begin
3797 PixelDesc.RedShift := GetShift(SourcePD.PixelDesc.RedRange, DestPD.PixelDesc.RedRange);
3798 PixelDesc.GreenShift := GetShift(SourcePD.PixelDesc.GreenRange, DestPD.PixelDesc.GreenRange);
3799 PixelDesc.BlueShift := GetShift(SourcePD.PixelDesc.BlueRange, DestPD.PixelDesc.BlueRange);
3800 PixelDesc.AlphaShift := GetShift(SourcePD.PixelDesc.AlphaRange, DestPD.PixelDesc.AlphaRange);
3801 result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, PtrInt(@PixelDesc));
3803 result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
3808 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3809 procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
3811 if aUseRGB or aUseAlpha then
3812 AddFunc(glBitmapInvertFunc, false, ((PtrInt(aUseAlpha) and 1) shl 1) or (PtrInt(aUseRGB) and 1));
3815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3816 procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
3818 fBorderColor[0] := aRed;
3819 fBorderColor[1] := aGreen;
3820 fBorderColor[2] := aBlue;
3821 fBorderColor[3] := aAlpha;
3822 if (ID > 0) then begin
3824 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
3828 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3829 procedure TglBitmap.FreeData;
3831 SetDataPointer(nil, tfEmpty);
3834 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3835 procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
3836 const aAlpha: Byte);
3838 FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
3841 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3842 procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
3844 PixelData: TglBitmapPixelData;
3846 FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData);
3848 aRed / PixelData.PixelDesc.RedRange,
3849 aGreen / PixelData.PixelDesc.GreenRange,
3850 aBlue / PixelData.PixelDesc.BlueRange,
3851 aAlpha / PixelData.PixelDesc.AlphaRange);
3854 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3855 procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
3857 PixelData: TglBitmapPixelData;
3859 FORMAT_DESCRIPTORS[Format].PreparePixel(PixelData);
3860 PixelData.Red := Max(0, Min(PixelData.PixelDesc.RedRange, Trunc(PixelData.PixelDesc.RedRange * aRed)));
3861 PixelData.Green := Max(0, Min(PixelData.PixelDesc.GreenRange, Trunc(PixelData.PixelDesc.GreenRange * aGreen)));
3862 PixelData.Blue := Max(0, Min(PixelData.PixelDesc.BlueRange, Trunc(PixelData.PixelDesc.BlueRange * aBlue)));
3863 PixelData.Alpha := Max(0, Min(PixelData.PixelDesc.AlphaRange, Trunc(PixelData.PixelDesc.AlphaRange * aAlpha)));
3864 AddFunc(glBitmapFillWithColorFunc, false, PtrInt(@PixelData));
3867 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3868 procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal);
3873 fFilterMin := GL_NEAREST;
3875 fFilterMin := GL_LINEAR;
3876 GL_NEAREST_MIPMAP_NEAREST:
3877 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
3878 GL_LINEAR_MIPMAP_NEAREST:
3879 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
3880 GL_NEAREST_MIPMAP_LINEAR:
3881 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
3882 GL_LINEAR_MIPMAP_LINEAR:
3883 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
3885 raise EglBitmapException.Create('SetFilter - Unknow MIN filter.');
3891 fFilterMag := GL_NEAREST;
3893 fFilterMag := GL_LINEAR;
3895 raise EglBitmapException.Create('SetFilter - Unknow MAG filter.');
3899 if (ID > 0) then begin
3901 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
3903 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
3905 GL_NEAREST, GL_LINEAR:
3906 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
3907 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
3908 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3909 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
3910 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3913 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
3917 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3918 procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; const R: Cardinal);
3920 procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
3924 aTarget := GL_CLAMP;
3927 aTarget := GL_REPEAT;
3929 GL_CLAMP_TO_EDGE: begin
3930 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
3931 aTarget := GL_CLAMP_TO_EDGE
3933 aTarget := GL_CLAMP;
3936 GL_CLAMP_TO_BORDER: begin
3937 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
3938 aTarget := GL_CLAMP_TO_BORDER
3940 aTarget := GL_CLAMP;
3943 GL_MIRRORED_REPEAT: begin
3944 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
3945 aTarget := GL_MIRRORED_REPEAT
3947 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
3950 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).');
3955 CheckAndSetWrap(S, fWrapS);
3956 CheckAndSetWrap(T, fWrapT);
3957 CheckAndSetWrap(R, fWrapR);
3959 if (ID > 0) then begin
3961 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
3962 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
3963 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
3967 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3968 procedure TglBitmap.GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData);
3971 if Assigned (fGetPixelFunc) then
3972 fGetPixelFunc(aPos, aPixel);
3976 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3977 procedure TglBitmap.SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData);
3980 if Assigned (fSetPixelFunc) then
3981 fSetPixelFuc(aPos, aPixel);
3985 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3986 procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
3988 if aEnableTextureUnit then
3991 glBindTexture(Target, ID);
3994 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3995 procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
3997 if aDisableTextureUnit then
3999 glBindTexture(Target, 0);
4002 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4003 constructor TglBitmap.Create;
4005 {$IFNDEF GLB_NO_NATIVE_GL}
4006 ReadOpenGLExtensions;
4008 if (ClassType = TglBitmap) then
4009 raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
4013 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4014 constructor TglBitmap.Create(const aFileName: String);
4017 LoadFromFile(FileName);
4020 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4021 constructor TglBitmap.Create(const aStream: TStream);
4024 LoadFromStream(aStream);
4027 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4028 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
4034 ImageSize := FORMAT_DESCRIPTORS[aFormat].GetSize(aSize);
4035 GetMem(Image, ImageSize);
4037 FillChar(Image^, ImageSize, #$FF);
4038 SetDataPointer(Image, aFormat, aSize.X, aSize.Y);
4045 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4046 constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
4047 const aFunc: TglBitmapFunction; const aArgs: PtrInt);
4050 LoadFromFunc(aSize, aFunc, aFormat, aArgs);
4054 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4055 constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
4058 LoadFromResource(aInstance, aResource, aResType);
4061 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4062 constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
4065 LoadFromResourceID(aInstance, aResourceID, aResType);
4069 {$IFDEF GLB_SUPPORT_PNG_READ}
4070 {$IF DEFINED(GLB_SDL_IMAGE)}
4071 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4072 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4073 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4074 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
4076 Surface: PSDL_Surface;
4080 RWops := glBitmapCreateRWops(aStream);
4082 if IMG_isPNG(RWops) > 0 then begin
4083 Surface := IMG_LoadPNG_RW(RWops);
4085 AssignFromSurface(Surface);
4088 SDL_FreeSurface(Surface);
4096 {$ELSEIF DEFINED(GLB_LIB_PNG)}
4097 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4098 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
4100 TStream(png_get_io_ptr(png)).Read(buffer^, size);
4103 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4104 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
4107 signature: array [0..7] of byte;
4109 png_info: png_infop;
4111 TempHeight, TempWidth: Integer;
4112 Format: TglBitmapInternalFormat;
4115 png_rows: array of pByte;
4116 Row, LineSize: Integer;
4120 if not init_libPNG then
4121 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
4125 StreamPos := Stream.Position;
4126 Stream.Read(signature, 8);
4127 Stream.Position := StreamPos;
4129 if png_check_sig(@signature, 8) <> 0 then begin
4131 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
4133 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
4136 png_info := png_create_info_struct(png);
4137 if png_info = nil then begin
4138 png_destroy_read_struct(@png, nil, nil);
4139 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
4142 // set read callback
4143 png_set_read_fn(png, stream, glBitmap_libPNG_read_func);
4145 // read informations
4146 png_read_info(png, png_info);
4149 TempHeight := png_get_image_height(png, png_info);
4150 TempWidth := png_get_image_width(png, png_info);
4153 case png_get_color_type(png, png_info) of
4154 PNG_COLOR_TYPE_GRAY:
4155 Format := tfLuminance8;
4156 PNG_COLOR_TYPE_GRAY_ALPHA:
4157 Format := tfLuminance8Alpha8;
4160 PNG_COLOR_TYPE_RGB_ALPHA:
4163 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
4166 // cut upper 8 bit from 16 bit formats
4167 if png_get_bit_depth(png, png_info) > 8 then
4168 png_set_strip_16(png);
4170 // expand bitdepth smaller than 8
4171 if png_get_bit_depth(png, png_info) < 8 then
4172 png_set_expand(png);
4174 // allocating mem for scanlines
4175 LineSize := png_get_rowbytes(png, png_info);
4176 GetMem(png_data, TempHeight * LineSize);
4178 SetLength(png_rows, TempHeight);
4179 for Row := Low(png_rows) to High(png_rows) do begin
4180 png_rows[Row] := png_data;
4181 Inc(png_rows[Row], Row * LineSize);
4184 // read complete image into scanlines
4185 png_read_image(png, @png_rows[0]);
4188 png_read_end(png, png_info);
4190 // destroy read struct
4191 png_destroy_read_struct(@png, @png_info, nil);
4193 SetLength(png_rows, 0);
4196 SetDataPointer(png_data, Format, TempWidth, TempHeight);
4209 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
4210 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4211 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
4215 Header: Array[0..7] of Byte;
4216 Row, Col, PixSize, LineSize: Integer;
4217 NewImage, pSource, pDest, pAlpha: pByte;
4218 Format: TglBitmapInternalFormat;
4221 PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10);
4226 StreamPos := Stream.Position;
4227 Stream.Read(Header[0], SizeOf(Header));
4228 Stream.Position := StreamPos;
4230 {Test if the header matches}
4231 if Header = PngHeader then begin
4232 Png := TPNGObject.Create;
4234 Png.LoadFromStream(Stream);
4236 case Png.Header.ColorType of
4238 Format := ifLuminance;
4239 COLOR_GRAYSCALEALPHA:
4240 Format := ifLuminanceAlpha;
4246 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
4249 PixSize := Trunc(FormatGetSize(Format));
4250 LineSize := Integer(Png.Header.Width) * PixSize;
4252 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
4256 case Png.Header.ColorType of
4257 COLOR_RGB, COLOR_GRAYSCALE:
4259 for Row := 0 to Png.Height -1 do begin
4260 Move (Png.Scanline[Row]^, pDest^, LineSize);
4261 Inc(pDest, LineSize);
4264 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
4266 PixSize := PixSize -1;
4268 for Row := 0 to Png.Height -1 do begin
4269 pSource := Png.Scanline[Row];
4270 pAlpha := pByte(Png.AlphaScanline[Row]);
4272 for Col := 0 to Png.Width -1 do begin
4273 Move (pSource^, pDest^, PixSize);
4274 Inc(pSource, PixSize);
4275 Inc(pDest, PixSize);
4284 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
4287 SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height);
4302 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4303 {$IFDEF GLB_LIB_PNG}
4304 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4305 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
4307 TStream(png_get_io_ptr(png)).Write(buffer^, size);
4311 {$IF DEFINED(GLB_LIB_PNG)}
4312 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4313 procedure TglBitmap.SavePNG(const aStream: TStream);
4316 png_info: png_infop;
4317 png_rows: array of pByte;
4322 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
4323 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
4325 if not init_libPNG then
4326 raise Exception.Create('SavePNG - unable to initialize libPNG.');
4329 case FInternalFormat of
4330 ifAlpha, ifLuminance, ifDepth8:
4331 ColorType := PNG_COLOR_TYPE_GRAY;
4333 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
4335 ColorType := PNG_COLOR_TYPE_RGB;
4337 ColorType := PNG_COLOR_TYPE_RGBA;
4339 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
4341 LineSize := Trunc(FormatGetSize(FInternalFormat) * Width);
4343 // creating array for scanline
4344 SetLength(png_rows, Height);
4346 for Row := 0 to Height - 1 do begin
4347 png_rows[Row] := Data;
4348 Inc(png_rows[Row], Row * LineSize)
4352 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
4354 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
4357 png_info := png_create_info_struct(png);
4358 if png_info = nil then begin
4359 png_destroy_write_struct(@png, nil);
4360 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
4363 // set read callback
4364 png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil);
4367 png_set_compression_level(png, 6);
4369 if InternalFormat in [ifBGR8, ifBGRA8] then
4372 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
4373 png_write_info(png, png_info);
4374 png_write_image(png, @png_rows[0]);
4375 png_write_end(png, png_info);
4376 png_destroy_write_struct(@png, @png_info);
4378 SetLength(png_rows, 0);
4385 {$ELSEIF DEFINED(GLB_PNGIMAGE)}
4386 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4387 procedure TglBitmap.SavePNG(const aStream: TStream);
4391 pSource, pDest: pByte;
4392 X, Y, PixSize: Integer;
4393 ColorType: Cardinal;
4399 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
4400 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
4402 case FInternalFormat of
4403 ifAlpha, ifLuminance, ifDepth8: begin
4404 ColorType := COLOR_GRAYSCALE;
4408 ifLuminanceAlpha: begin
4409 ColorType := COLOR_GRAYSCALEALPHA;
4413 ifBGR8, ifRGB8: begin
4414 ColorType := COLOR_RGB;
4418 ifBGRA8, ifRGBA8: begin
4419 ColorType := COLOR_RGBALPHA;
4424 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
4427 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
4431 for Y := 0 to Height -1 do begin
4432 pDest := png.ScanLine[Y];
4433 for X := 0 to Width -1 do begin
4434 Move(pSource^, pDest^, PixSize);
4435 Inc(pDest, PixSize);
4436 Inc(pSource, PixSize);
4438 png.AlphaScanline[Y]^[X] := pSource^;
4443 // convert RGB line to BGR
4444 if InternalFormat in [ifRGB8, ifRGBA8] then begin
4445 pTemp := png.ScanLine[Y];
4446 for X := 0 to Width -1 do begin
4447 Temp := pByteArray(pTemp)^[0];
4448 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
4449 pByteArray(pTemp)^[2] := Temp;
4456 Png.CompressionLevel := 6;
4457 Png.SaveToStream(Stream);
4465 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4466 //JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4467 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4468 {$IFDEF GLB_LIB_JPEG}
4470 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
4471 glBitmap_libJPEG_source_mgr = record
4472 pub: jpeg_source_mgr;
4475 SrcBuffer: array [1..4096] of byte;
4478 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
4479 glBitmap_libJPEG_dest_mgr = record
4480 pub: jpeg_destination_mgr;
4482 DestStream: TStream;
4483 DestBuffer: array [1..4096] of byte;
4486 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4488 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
4492 SetLength(Msg, 256);
4493 cinfo^.err^.format_message(cinfo, pChar(Msg));
4494 Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
4495 cinfo^.global_state := 0;
4500 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4502 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
4506 SetLength(Msg, 256);
4507 cinfo^.err^.format_message(cinfo, pChar(Msg));
4508 Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
4509 cinfo^.global_state := 0;
4513 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4515 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
4520 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4521 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
4523 src: glBitmap_libJPEG_source_mgr_ptr;
4526 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
4528 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
4529 if (bytes <= 0) then begin
4530 src^.SrcBuffer[1] := $FF;
4531 src^.SrcBuffer[2] := JPEG_EOI;
4535 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
4536 src^.pub.bytes_in_buffer := bytes;
4541 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4542 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
4544 src: glBitmap_libJPEG_source_mgr_ptr;
4546 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
4548 if num_bytes > 0 then begin
4549 // wanted byte isn't in buffer so set stream position and read buffer
4550 if num_bytes > src^.pub.bytes_in_buffer then begin
4551 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
4552 src^.pub.fill_input_buffer(cinfo);
4554 // wanted byte is in buffer so only skip
4555 inc(src^.pub.next_input_byte, num_bytes);
4556 dec(src^.pub.bytes_in_buffer, num_bytes);
4561 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4563 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
4568 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4570 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
4575 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4576 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
4578 dest: glBitmap_libJPEG_dest_mgr_ptr;
4580 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
4582 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
4583 // write complete buffer
4584 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
4587 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
4588 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
4594 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4595 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
4598 dest: glBitmap_libJPEG_dest_mgr_ptr;
4600 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
4602 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
4603 // check for endblock
4604 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
4606 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
4611 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
4616 {$IFDEF GLB_SUPPORT_JPEG_READ}
4617 {$IF DEFINED(GLB_SDL_IMAGE)}
4618 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4619 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
4621 Surface: PSDL_Surface;
4626 RWops := glBitmapCreateRWops(Stream);
4628 if IMG_isJPG(RWops) > 0 then begin
4629 Surface := IMG_LoadJPG_RW(RWops);
4631 AssignFromSurface(Surface);
4634 SDL_FreeSurface(Surface);
4642 {$ELSEIF DEFINED(GLB_LIB_JPEG)}
4643 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4644 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
4647 Temp: array[0..1]of Byte;
4649 jpeg: jpeg_decompress_struct;
4650 jpeg_err: jpeg_error_mgr;
4652 IntFormat: TglBitmapInternalFormat;
4654 TempHeight, TempWidth: Integer;
4661 if not init_libJPEG then
4662 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
4665 // reading first two bytes to test file and set cursor back to begin
4666 StreamPos := Stream.Position;
4667 Stream.Read(Temp[0], 2);
4668 Stream.Position := StreamPos;
4670 // if Bitmap then read file.
4671 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
4672 FillChar(jpeg, SizeOf(jpeg_decompress_struct), $00);
4673 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
4676 jpeg.err := jpeg_std_error(@jpeg_err);
4677 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
4678 jpeg_err.output_message := glBitmap_libJPEG_output_message;
4680 // decompression struct
4681 jpeg_create_decompress(@jpeg);
4683 // allocation space for streaming methods
4684 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
4686 // seeting up custom functions
4687 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
4688 pub.init_source := glBitmap_libJPEG_init_source;
4689 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
4690 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
4691 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
4692 pub.term_source := glBitmap_libJPEG_term_source;
4694 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
4695 pub.next_input_byte := nil; // until buffer loaded
4697 SrcStream := Stream;
4700 // set global decoding state
4701 jpeg.global_state := DSTATE_START;
4703 // read header of jpeg
4704 jpeg_read_header(@jpeg, false);
4706 // setting output parameter
4707 case jpeg.jpeg_color_space of
4710 jpeg.out_color_space := JCS_GRAYSCALE;
4711 IntFormat := ifLuminance;
4714 jpeg.out_color_space := JCS_RGB;
4715 IntFormat := ifRGB8;
4719 jpeg_start_decompress(@jpeg);
4721 TempHeight := jpeg.output_height;
4722 TempWidth := jpeg.output_width;
4724 // creating new image
4725 GetMem(pImage, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
4729 for Row := 0 to TempHeight -1 do begin
4730 jpeg_read_scanlines(@jpeg, @pTemp, 1);
4731 Inc(pTemp, Trunc(FormatGetSize(IntFormat) * TempWidth));
4734 // finish decompression
4735 jpeg_finish_decompress(@jpeg);
4737 // destroy decompression
4738 jpeg_destroy_decompress(@jpeg);
4740 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight);
4753 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
4754 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4755 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
4760 Temp: array[0..1]of Byte;
4764 // reading first two bytes to test file and set cursor back to begin
4765 StreamPos := Stream.Position;
4766 Stream.Read(Temp[0], 2);
4767 Stream.Position := StreamPos;
4769 // if Bitmap then read file.
4770 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
4771 bmp := TBitmap.Create;
4773 jpg := TJPEGImage.Create;
4775 jpg.LoadFromStream(Stream);
4777 result := AssignFromBitmap(bmp);
4789 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
4790 {$IF DEFEFINED(GLB_LIB_JPEG)}
4791 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4792 procedure TglBitmap.SaveJPEG(Stream: TStream);
4794 jpeg: jpeg_compress_struct;
4795 jpeg_err: jpeg_error_mgr;
4797 pTemp, pTemp2: pByte;
4799 procedure CopyRow(pDest, pSource: pByte);
4803 for X := 0 to Width - 1 do begin
4804 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
4805 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
4806 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
4813 if not (ftJPEG in FormatGetSupportedFiles(Format)) then
4814 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
4816 if not init_libJPEG then
4817 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
4820 FillChar(jpeg, SizeOf(jpeg_compress_struct), $00);
4821 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
4824 jpeg.err := jpeg_std_error(@jpeg_err);
4825 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
4826 jpeg_err.output_message := glBitmap_libJPEG_output_message;
4828 // compression struct
4829 jpeg_create_compress(@jpeg);
4831 // allocation space for streaming methods
4832 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
4834 // seeting up custom functions
4835 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
4836 pub.init_destination := glBitmap_libJPEG_init_destination;
4837 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
4838 pub.term_destination := glBitmap_libJPEG_term_destination;
4840 pub.next_output_byte := @DestBuffer[1];
4841 pub.free_in_buffer := Length(DestBuffer);
4843 DestStream := Stream;
4846 // very important state
4847 jpeg.global_state := CSTATE_START;
4848 jpeg.image_width := Width;
4849 jpeg.image_height := Height;
4850 case InternalFormat of
4851 ifAlpha, ifLuminance, ifDepth8: begin
4852 jpeg.input_components := 1;
4853 jpeg.in_color_space := JCS_GRAYSCALE;
4855 ifRGB8, ifBGR8: begin
4856 jpeg.input_components := 3;
4857 jpeg.in_color_space := JCS_RGB;
4861 jpeg_set_defaults(@jpeg);
4862 jpeg_set_quality(@jpeg, 95, true);
4863 jpeg_start_compress(@jpeg, true);
4866 if InternalFormat = ifBGR8 then
4867 GetMem(pTemp2, fRowSize)
4872 for Row := 0 to jpeg.image_height -1 do begin
4874 if InternalFormat = ifBGR8 then
4875 CopyRow(pTemp2, pTemp)
4880 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
4881 inc(pTemp, fRowSize);
4885 if InternalFormat = ifBGR8 then
4888 jpeg_finish_compress(@jpeg);
4889 jpeg_destroy_compress(@jpeg);
4895 {$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
4896 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4897 procedure TglBitmap.SaveJPEG(Stream: TStream);
4902 if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then
4903 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
4905 Bmp := TBitmap.Create;
4907 Jpg := TJPEGImage.Create;
4909 AssignToBitmap(Bmp);
4910 if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
4911 Jpg.Grayscale := true;
4912 Jpg.PixelFormat := jf8Bit;
4915 Jpg.SaveToStream(Stream);
4926 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4927 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4928 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4935 BMP_COMP_BITFIELDS = 3;
4938 TBMPHeader = packed record
4943 bfOffBits: Cardinal;
4946 TBMPInfo = packed record
4952 biCompression: Cardinal;
4953 biSizeImage: Cardinal;
4954 biXPelsPerMeter: Longint;
4955 biYPelsPerMeter: Longint;
4956 biClrUsed: Cardinal;
4957 biClrImportant: Cardinal;
4960 TBMPInfoOS = packed record
4968 // TBMPPalette = record
4970 // true : (Colors: array[Byte] of TRGBQUAD);
4971 // false: (redMask, greenMask, blueMask: Cardinal);
4974 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4975 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
4977 TMaskValues = packed record
4987 //////////////////////////////////////////////////////////////////////////////////////////////////
4988 function ReadInfo(var aInfo: TBMPInfo; var aMask: TMaskValues): TglBitmapFormat;
4991 aStream.Read(aInfo, SizeOf(aInfo));
4992 FillChar(aMask, SizeOf(aMask), 0);
4995 if aInfo.biCompression <> BMP_COMP_RGB then begin
4996 if aInfo.biCompression = BMP_COMP_BITFIELDS then begin
4997 // Read Bitmasks for 16 or 32 Bit (24 Bit dosn't support Bitmasks!)
4998 if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
4999 aStream.Read(aMask.Red, SizeOf(Cardinal));
5000 aStream.Read(aMask.Green, SizeOf(Cardinal));
5001 aStream.Read(aMask.Blue, SizeOf(Cardinal));
5002 aStream.Read(aMask.Alpha, SizeOf(Cardinal));
5004 raise EglBitmapException.Create('Bitmask is not supported for 24bit formats');
5006 aStream.Position := StartPos;
5007 raise EglBitmapException.Create('RLE compression is not supported');
5011 //get suitable format
5012 case aInfo.biBitCount of
5013 8: result := tfLuminance8;
5014 16: result := tfRGB5A1;
5015 24: result := tfBGR8;
5016 32: result := tfBGRA8;
5020 //////////////////////////////////////////////////////////////////////////////////////////////////
5021 function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TMaskValues): TBitfieldFormat;
5023 TmpFormat: TglBitmapFormat;
5024 FormatDesc: TglBitmapFormatDescClass;
5027 if (aMask.Red <> 0) or (aMask.Green <> 0) or (aMask.Blue <> 0) or (aMask.Alpha <> 0) then begin
5028 for TmpFormat := High(FORMAT_DESCRIPTORS) downto Low(FORMAT_DESCRIPTORS) do begin
5029 FormatDesc := FORMAT_DESCRIPTORS[TmpFormat];
5030 if FormatDesc.MaskMatch(aMask.Red, aMask.Green, aMask.Blue, aMask.Alpha) then begin
5031 aFormat := FormatDesc.GetFormat;
5036 if (aMask.Alpha = 0) then
5037 aFormat := FORMAT_DESCRIPTORS[aFormat].WithoutAlpha;
5039 result := TBitfieldFormat.Create;
5040 result.RedMask := aMask.Red;
5041 result.GreenMask := aMask.Green;
5042 result.BlueMask := aMask.Blue;
5043 result.AlphaMask := aMask.Alpha;
5049 ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
5050 PaddingBuff: Cardinal;
5051 LineBuf, ImageData, TmpData: PByte;
5052 BmpFormat: TglBitmapFormat;
5060 BitfieldFormat: TBitfieldFormat;
5061 FormatDesc: TglBitmapFormatDescClass;
5068 ImageData, pData, pTmp, LineBuf, TmpData: PByte;
5070 BmpFormat: TglBitmapFormat;
5071 LineSize, Padding, LineIdx, PixelIdx: Integer;
5072 RedMask, GreenMask, BlueMask, AlphaMask, FormatSize: Cardinal;
5075 Pixel: TglBitmapPixelData;
5076 PaddingBuff: Cardinal;
5082 //////////////////////////////////////////////////////////////////////////////////////////////////
5083 procedure ReadBitfieldLine(aData: PByte; aLineBuf: PByte);
5086 Pixel: TglBitmapPixelData;
5088 ////////////////////////////////////////////////////////////////////////////////////////////////
5089 procedure ChangeRange(var aValue: Cardinal; const aOldRange, aNewRange: Cardinal);
5091 if (aOldRange = aNewRange) then
5093 if (aOldRange > 0) then
5094 aValue := Round(aValue / aOldRange * aNewRange)
5100 aStream.Read(aLineBuf^, rbLineSize);
5101 for i := 0 to Info.biWidth-1 do begin
5102 BitfieldFormat.Unmap(PCardinal(aLineBuf)^, Pixel); //if is 16bit Bitfield only 2 last significant Bytes are taken from Cardinal
5103 inc(aLineBuf, Info.biBitCount shr 3);
5104 with FormatDesc.GetPixelDesc do begin
5105 ChangeRange(Pixel.Red, BitfieldFormat.RedRange, RedRange);
5106 ChangeRange(Pixel.Green, BitfieldFormat.GreenRange, GreenRange);
5107 ChangeRange(Pixel.Blue, BitfieldFormat.BlueRange, BlueRange);
5108 ChangeRange(Pixel.Alpha, BitfieldFormat.AlphaRange, AlphaRange);
5110 FormatDesc.Map(Pixel, aData);
5116 BmpFormat := tfEmpty;
5117 BitfieldFormat := nil;
5121 StartPos := aStream.Position;
5122 aStream.Read(Header, SizeOf(Header));
5124 if Header.bfType = BMP_MAGIC then begin
5125 BmpFormat := ReadInfo(Info, Mask);
5126 BitfieldFormat := CheckBitfields(BmpFormat, Mask);
5128 if (Info.biBitCount < 16) then
5129 aStream.Position := aStream.Position + Info.biClrUsed * 4;
5130 aStream.Position := StartPos + Header.bfOffBits;
5132 if (BmpFormat <> tfEmpty) then begin
5133 FormatDesc := FORMAT_DESCRIPTORS[BmpFormat];
5134 rbLineSize := Info.biWidth * (Info.biBitCount shr 3); //ReadBuffer LineSize
5135 wbLineSize := Trunc(Info.biWidth * FormatDesc.GetSize);
5136 Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
5139 ImageSize := FormatDesc.GetSize(glBitmapPosition(Info.biWidth, Info.biHeight));
5140 GetMem(ImageData, ImageSize);
5141 if Assigned(BitfieldFormat) then
5142 GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
5146 FillChar(ImageData^, ImageSize, $FF);
5147 TmpData := ImageData;
5148 Inc(TmpData, wbLineSize * (Info.biHeight -1));
5149 for i := 0 to Info.biHeight-1 do begin
5150 if Assigned(BitfieldFormat) then
5151 ReadBitfieldLine(TmpData, LineBuf) //if is bitfield format read and convert data
5153 aStream.Read(TmpData^, wbLineSize); //else only read data
5154 Dec(TmpData, wbLineSize);
5155 aStream.Read(PaddingBuff, Padding);
5157 SetDataPointer(ImageData, BmpFormat, Info.biWidth, Info.biHeight);
5160 if Assigned(LineBuf) then
5168 raise EglBitmapException.Create('LoadBMP - No suitable format found');
5170 FreeAndNil(BitfieldFormat);
5173 else aStream.Position := StartPos;
5176 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5177 procedure TglBitmap.SaveBMP(const aStream: TStream);
5181 pData, pTemp: pByte;
5183 PixelFormat: TglBitmapPixelData;
5184 ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer;
5185 Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
5187 PaddingBuff: Cardinal;
5189 function GetLineWidth : Integer;
5191 result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
5195 if not (ftBMP in FormatGetSupportedFiles(Format)) then
5196 raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
5198 ImageSize := FORMAT_DESCRIPTORS[Format].GetSize(Dimension);
5200 Header.bfType := BMP_MAGIC;
5201 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
5202 Header.bfReserved1 := 0;
5203 Header.bfReserved2 := 0;
5204 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
5206 FillChar(Info, SizeOf(Info), 0);
5207 Info.biSize := SizeOf(Info);
5208 Info.biWidth := Width;
5209 Info.biHeight := Height;
5211 Info.biCompression := BMP_COMP_RGB;
5212 Info.biSizeImage := ImageSize;
5214 //TODO tfAlpha8, ifLuminance8, ifDepth8:
5217 Info.biBitCount := 8;
5219 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
5220 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal);
5222 Info.biClrUsed := 256;
5223 Info.biClrImportant := 256;
5225 //TODO ifLuminance8Alpha8, tfRGBA4, ifR5G6B5, tfRGB5A1:
5226 tfLuminance8Alpha8, tfRGB5A1:
5228 Info.biBitCount := 16;
5229 Info.biCompression := BMP_COMP_BITFIELDS;
5232 Info.biBitCount := 24;
5233 //TODO tfBGRA8, tfRGBA8, tfRGB10A2:
5236 Info.biBitCount := 32;
5237 Info.biCompression := BMP_COMP_BITFIELDS;
5240 raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
5242 Info.biXPelsPerMeter := 2835;
5243 Info.biYPelsPerMeter := 2835;
5246 if Info.biCompression = BMP_COMP_BITFIELDS then begin
5247 Info.biSize := Info.biSize + 4 * SizeOf(Cardinal);
5248 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
5249 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
5251 FORMAT_DESCRIPTORS[Format].PreparePixel(PixelFormat);
5252 with PixelFormat.PixelDesc do begin
5253 RedMask := RedRange shl RedShift;
5254 GreenMask := GreenRange shl GreenShift;
5255 BlueMask := BlueRange shl BlueShift;
5256 AlphaMask := AlphaRange shl AlphaShift;
5261 aStream.Write(Header, SizeOf(Header));
5262 aStream.Write(Info, SizeOf(Info));
5265 if Info.biBitCount = 8 then begin
5267 for ColorIdx := Low(Byte) to High(Byte) do begin
5268 aStream.Write(Temp, 4);
5269 Temp := Temp + $00010101;
5274 if Info.biCompression = BMP_COMP_BITFIELDS then begin
5275 aStream.Write(RedMask, SizeOf(Cardinal));
5276 aStream.Write(GreenMask, SizeOf(Cardinal));
5277 aStream.Write(BlueMask, SizeOf(Cardinal));
5278 aStream.Write(AlphaMask, SizeOf(Cardinal));
5282 LineSize := Trunc(Width * FORMAT_DESCRIPTORS[Format].GetSize);
5283 Padding := GetLineWidth - LineSize;
5287 Inc(pData, (Height -1) * LineSize);
5289 // prepare row buffer. But only for RGB because RGBA supports color masks
5290 // so it's possible to change color within the image.
5291 if (Format = tfRGB8) then
5292 GetMem(pTemp, fRowSize)
5298 for LineIdx := 0 to Height - 1 do begin
5300 if Format = tfRGB8 then begin
5301 Move(pData^, pTemp^, fRowSize);
5302 SwapRGB(pTemp, Width, false);
5305 aStream.Write(pTemp^, LineSize);
5306 Dec(pData, LineSize);
5308 aStream.Write(PaddingBuff, Padding);
5311 // destroy row buffer
5312 if Format = tfRGB8 then
5317 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5318 //TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5319 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5321 TTGAHeader = packed record
5325 ColorMapSpec: Array[0..4] of Byte;
5335 TGA_UNCOMPRESSED_RGB = 2;
5336 TGA_UNCOMPRESSED_GRAY = 3;
5337 TGA_COMPRESSED_RGB = 10;
5338 TGA_COMPRESSED_GRAY = 11;
5340 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5341 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
5344 NewImage, pData: PByte;
5346 PixelSize, LineSize, YStart, YEnd, YInc: Integer;
5347 Format: TglBitmapFormat;
5352 ////////////////////////////////////////////////////////////////////////////////////////
5353 procedure ReadUncompressed;
5357 RowSize := Header.Width * PixelSize;
5358 // copy line by line
5359 while YStart <> YEnd + YInc do begin
5361 Inc(pData, YStart * LineSize);
5362 aStream.Read(pData^, RowSize);
5367 ////////////////////////////////////////////////////////////////////////////////////////
5368 procedure ReadCompressed;
5370 HeaderWidth, HeaderHeight: Integer;
5371 LinePixelsRead, ImgPixelsRead, ImgPixelsToRead: Integer;
5374 CacheSize, CachePos: Integer;
5377 TempBuf: Array [0..15] of Byte;
5379 PixelRepeat: Boolean;
5380 PixelToRead, TempPixels: Integer;
5382 /////////////////////////////////////////////////////////////////
5383 procedure CheckLine;
5385 if LinePixelsRead >= HeaderWidth then begin
5386 LinePixelsRead := 0;
5389 Inc(pData, YStart * LineSize);
5393 /////////////////////////////////////////////////////////////////
5394 procedure CachedRead(out Buffer; Count: Integer);
5398 if (CachePos + Count) > CacheSize then begin
5402 if CacheSize - CachePos > 0 then begin
5403 BytesRead := CacheSize - CachePos;
5404 Move(pByteArray(Cache)^[CachePos], Buffer, BytesRead);
5405 Inc(CachePos, BytesRead);
5409 CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
5410 aStream.Read(Cache^, CacheSize);
5414 if Count - BytesRead > 0 then begin
5415 Move(pByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
5416 Inc(CachePos, Count - BytesRead);
5419 Move(pByteArray(Cache)^[CachePos], Buffer, Count);
5420 Inc(CachePos, Count);
5428 HeaderWidth := Header.Width;
5429 HeaderHeight := Header.Height;
5431 GetMem(Cache, CACHE_SIZE); // 16K Buffer
5433 ImgPixelsToRead := HeaderWidth * HeaderHeight;
5435 LinePixelsRead := 0;
5438 Inc(pData, YStart * LineSize);
5440 // Read until all Pixels
5442 CachedRead(Temp, 1);
5444 PixelRepeat := Temp and $80 > 0;
5445 PixelToRead := (Temp and $7F) + 1;
5447 Inc(ImgPixelsRead, PixelToRead);
5449 if PixelRepeat then begin
5450 // repeat one pixel x times
5451 CachedRead(TempBuf[0], PixelSize);
5454 while PixelToRead > 0 do begin
5457 TempPixels := HeaderWidth - LinePixelsRead;
5458 if PixelToRead < TempPixels then
5459 TempPixels := PixelToRead;
5461 Inc(LinePixelsRead, TempPixels);
5462 Dec(PixelToRead, TempPixels);
5464 while TempPixels > 0 do begin
5467 pData^ := TempBuf[0];
5471 pWord(pData)^ := pWord(@TempBuf[0])^;
5475 pWord(pData)^ := pWord(@TempBuf[0])^;
5477 pData^ := TempBuf[2];
5481 pDWord(pData)^ := pDWord(@TempBuf[0])^;
5490 while PixelToRead > 0 do begin
5492 TempPixels := HeaderWidth - LinePixelsRead;
5493 if PixelToRead < TempPixels then
5494 TempPixels := PixelToRead;
5495 CachedRead(pData^, PixelSize * TempPixels);
5496 Inc(pData, PixelSize * TempPixels);
5497 Inc(LinePixelsRead, TempPixels);
5498 Dec(PixelToRead, TempPixels);
5501 until ImgPixelsRead >= ImgPixelsToRead;
5510 // reading header to test file and set cursor back to begin
5511 StreamPos := aStream.Position;
5512 aStream.Read(Header, SizeOf(Header));
5514 // no colormapped files
5515 if (Header.ColorMapType = 0) then begin
5516 if Header.ImageType in [TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY] then begin
5518 //TODO 8: Format := tfAlpha8;
5519 16: Format := tfLuminance8Alpha8;
5520 24: Format := tfBGR8;
5521 32: Format := tfBGRA8;
5523 raise EglBitmapException.Create('LoadTga - unsupported BitsPerPixel found.');
5527 if Header.ImageID <> 0 then
5528 aStream.Position := aStream.Position + Header.ImageID;
5530 PixelSize := Trunc(FORMAT_DESCRIPTORS[Format].GetSize);
5531 LineSize := Trunc(Header.Width * PixelSize);
5533 GetMem(NewImage, LineSize * Header.Height);
5536 if (Header.ImageDes and $20 > 0) then begin
5538 YEnd := Header.Height -1;
5541 YStart := Header.Height -1;
5547 case Header.ImageType of
5548 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
5550 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
5554 SetDataPointer(NewImage, Format, Header.Width, Header.Height);
5561 else aStream.Position := StreamPos;
5563 else aStream.Position := StreamPos;
5566 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5567 procedure TglBitmap.SaveTGA(const aStream: TStream);
5572 FormatDesc: TglBitmapFormatDescClass;
5574 procedure ConvertData(pTemp: pByte);
5576 Idx, PixelSize: Integer;
5579 PixelSize := fPixelSize;
5580 for Idx := 1 to Height * Width do begin
5581 Temp := pByteArray(pTemp)^[2];
5582 pByteArray(pTemp)^[2] := pByteArray(pTemp)^[0];
5583 pByteArray(pTemp)^[0] := Temp;
5584 Inc(pTemp, PixelSize);
5589 if not (ftTGA in FormatGetSupportedFiles(Format)) then
5590 raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT);
5592 FillChar(Header, SizeOf(Header), 0);
5594 //TODO ifAlpha8, ifLuminance8, ifDepth8: begin
5596 Header.ImageType := TGA_UNCOMPRESSED_GRAY;
5599 tfLuminance8Alpha8: begin
5600 Header.ImageType := TGA_UNCOMPRESSED_GRAY;
5603 tfRGB8, tfBGR8: begin
5604 Header.ImageType := TGA_UNCOMPRESSED_RGB;
5607 tfRGBA8, tfBGRA8: begin
5608 Header.ImageType := TGA_UNCOMPRESSED_RGB;
5612 raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT);
5615 Header.Width := Width;
5616 Header.Height := Height;
5617 Header.ImageDes := $20;
5618 FormatDesc := FORMAT_DESCRIPTORS[Format];
5620 if FormatDesc.HasAlpha then
5621 Header.ImageDes := Header.ImageDes or $08;
5622 aStream.Write(Header, SizeOf(Header));
5624 // convert RGB(A) to BGR(A)
5625 Size := FormatDesc.GetSize(Dimension);
5626 if Format in [tfRGB8, tfRGBA8] then begin
5627 GetMem(pTemp, Size);
5633 if Format in [tfRGB8, tfRGBA8] then begin
5634 Move(Data^, pTemp^, Size);
5639 aStream.Write(pTemp^, Size);
5642 if Format in [tfRGB8, tfRGBA8] then
5647 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5648 //DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5649 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5651 DDS_MAGIC = $20534444;
5653 // DDS_header.dwFlags
5654 DDSD_CAPS = $00000001;
5655 DDSD_HEIGHT = $00000002;
5656 DDSD_WIDTH = $00000004;
5657 DDSD_PITCH = $00000008;
5658 DDSD_PIXELFORMAT = $00001000;
5659 DDSD_MIPMAPCOUNT = $00020000;
5660 DDSD_LINEARSIZE = $00080000;
5661 DDSD_DEPTH = $00800000;
5663 // DDS_header.sPixelFormat.dwFlags
5664 DDPF_ALPHAPIXELS = $00000001;
5665 DDPF_FOURCC = $00000004;
5666 DDPF_INDEXED = $00000020;
5667 DDPF_RGB = $00000040;
5669 // DDS_header.sCaps.dwCaps1
5670 DDSCAPS_COMPLEX = $00000008;
5671 DDSCAPS_TEXTURE = $00001000;
5672 DDSCAPS_MIPMAP = $00400000;
5674 // DDS_header.sCaps.dwCaps2
5675 DDSCAPS2_CUBEMAP = $00000200;
5676 DDSCAPS2_CUBEMAP_POSITIVEX = $00000400;
5677 DDSCAPS2_CUBEMAP_NEGATIVEX = $00000800;
5678 DDSCAPS2_CUBEMAP_POSITIVEY = $00001000;
5679 DDSCAPS2_CUBEMAP_NEGATIVEY = $00002000;
5680 DDSCAPS2_CUBEMAP_POSITIVEZ = $00004000;
5681 DDSCAPS2_CUBEMAP_NEGATIVEZ = $00008000;
5682 DDSCAPS2_VOLUME = $00200000;
5684 D3DFMT_DXT1 = $31545844;
5685 D3DFMT_DXT3 = $33545844;
5686 D3DFMT_DXT5 = $35545844;
5689 TDDSPixelFormat = packed record
5693 dwRGBBitCount: Cardinal;
5694 dwRBitMask: Cardinal;
5695 dwGBitMask: Cardinal;
5696 dwBBitMask: Cardinal;
5697 dwAlphaBitMask: Cardinal;
5700 TDDSCaps = packed record
5704 dwReserved: Cardinal;
5707 TDDSHeader = packed record
5713 dwPitchOrLinearSize: Cardinal;
5715 dwMipMapCount: Cardinal;
5716 dwReserved: array[0..10] of Cardinal;
5717 PixelFormat: TDDSPixelFormat;
5719 dwReserved2: Cardinal;
5722 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5723 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
5727 Y, LineSize: Cardinal;
5729 NewImage, pData: pByte;
5730 ddsFormat: TglBitmapFormat;
5732 function RaiseEx : Exception;
5734 result := EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
5737 function GetDDSFormat: TglBitmapFormat;
5739 with Header.PixelFormat do begin
5741 if (dwFlags and DDPF_FOURCC) > 0 then begin
5743 case Header.PixelFormat.dwFourCC of
5744 D3DFMT_DXT1: result := ifDXT1;
5745 D3DFMT_DXT3: result := ifDXT3;
5746 D3DFMT_DXT5: result := ifDXT5;
5755 if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
5756 case dwRGBBitCount of
5758 (* TODO if dwFlags and DDPF_ALPHAPIXELS > 0 then
5762 result := tfLuminance8;
5765 if dwFlags and DDPF_ALPHAPIXELS > 0 then begin
5767 case CountSetBits(dwRBitMask) of
5768 5: result := tfRGB5A1;
5769 //TODO 4: result := tfRGBA4;
5771 result := tfLuminance8Alpha8;
5775 //TODO result := ifR5G6B5;
5780 if dwRBitMask > dwBBitMask then
5786 if CountSetBits(dwRBitMask) = 10 then
5787 //TODO result := tfRGB10A2
5791 if dwRBitMask > dwBBitMask then
5808 StreamPos := aStream.Position;
5809 aStream.Read(Header, sizeof(Header));
5811 if ((Header.dwMagic <> DDS_MAGIC) or (Header.dwSize <> 124) or
5812 ((Header.dwFlags and DDSD_PIXELFORMAT) = 0) or ((Header.dwFlags and DDSD_CAPS) = 0)) then begin
5813 aStream.Position := StreamPos;
5817 ddsFormat := GetDDSFormat;
5818 LineSize := Trunc(Header.dwWidth * FORMAT_DESCRIPTORS[ddsFormat].GetSize);
5819 GetMem(NewImage, Header.dwHeight * LineSize);
5824 if (Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0 then begin
5825 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
5826 for Y := 0 to Header.dwHeight -1 do begin
5827 aStream.Read(pData^, RowSize);
5828 Inc(pData, LineSize);
5833 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
5834 RowSize := Header.dwPitchOrLinearSize;
5836 for Y := 0 to Header.dwHeight -1 do begin
5837 aStream.Read(pData^, RowSize);
5838 Inc(pData, LineSize);
5843 SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
5851 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5852 procedure TglBitmap.SaveDDS(const aStream: TStream);
5855 Pix: TglBitmapPixelData;
5857 //if not FormatIsUncompressed(InternalFormat) then
5858 // raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_FORMAT);
5860 (* TODO if Format = tfAlpha8 then
5861 FORMAT_DESCRIPTORS[tfLuminance8].PreparePixel(Pix);
5863 FORMAT_DESCRIPTORS[Format].PreparePixel(Pix);
5866 FillChar(Header, SizeOf(Header), 0);
5867 Header.dwMagic := DDS_MAGIC;
5868 Header.dwSize := 124;
5869 Header.dwFlags := DDSD_PITCH or DDSD_CAPS or DDSD_PIXELFORMAT;
5871 if Width > 0 then begin
5872 Header.dwWidth := Width;
5873 Header.dwFlags := Header.dwFlags or DDSD_WIDTH;
5876 if Height > 0 then begin
5877 Header.dwHeight := Height;
5878 Header.dwFlags := Header.dwFlags or DDSD_HEIGHT;
5881 Header.dwPitchOrLinearSize := fRowSize;
5882 Header.dwMipMapCount := 1;
5885 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
5888 Header.PixelFormat.dwSize := Sizeof(Header.PixelFormat);
5889 Header.PixelFormat.dwFlags := DDPF_RGB;
5892 if FORMAT_DESCRIPTORS[Format].HasAlpha and (Format <> tfAlpha8) then
5893 Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
5896 Header.PixelFormat.dwRGBBitCount := Trunc(FORMAT_DESCRIPTORS[Format].GetSize * 8);
5897 Header.PixelFormat.dwRBitMask := Pix.PixelDesc.RedRange shl Pix.PixelDesc.RedShift;
5898 Header.PixelFormat.dwGBitMask := Pix.PixelDesc.GreenRange shl Pix.PixelDesc.GreenShift;
5899 Header.PixelFormat.dwBBitMask := Pix.PixelDesc.BlueRange shl Pix.PixelDesc.BlueShift;
5900 Header.PixelFormat.dwAlphaBitMask := Pix.PixelDesc.AlphaRange shl Pix.PixelDesc.AlphaShift;
5902 aStream.Write(Header, SizeOf(Header));
5903 aStream.Write(Data^, FORMAT_DESCRIPTORS[Format].GetSize(Dimension));
5907 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5908 //TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5909 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5910 function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
5912 if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
5913 result := fLines[aIndex]
5918 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5919 procedure TglBitmap2D.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
5920 const aWidth: Integer; const aHeight: Integer);
5922 Idx, LineWidth: Integer;
5924 inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
5927 if {FormatIsUncompressed(Format)} true then begin
5929 fGetPixelFunc := GetPixel2DUnmap;
5930 fSetPixelFunc := SetPixel2DUnmap;
5933 if Assigned(Data) then begin
5934 SetLength(fLines, GetHeight);
5935 LineWidth := Trunc(GetWidth * FORMAT_DESCRIPTORS[Format].GetSize);
5937 for Idx := 0 to GetHeight -1 do begin
5938 fLines[Idx] := Data;
5939 Inc(fLines[Idx], Idx * LineWidth);
5942 else SetLength(fLines, 0);
5945 SetLength(fLines, 0);
5947 fSetPixelFunc := nil;
5951 fGetPixelFunc := GetPixel2DDXT1;
5953 fGetPixelFunc := GetPixel2DDXT3;
5955 fGetPixelFunc := GetPixel2DDXT5;
5957 fGetPixelFunc := nil;
5963 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5964 procedure TglBitmap2D.UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
5966 FormatDescriptor: TglBitmapFormatDescClass;
5967 FormatDesc: TglBitmapFormatDesc;
5969 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
5972 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
5973 glCompressedTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Trunc(Width * Height * FormatGetSize(Self.InternalFormat)), Data)
5977 FormatDescriptor := FORMAT_DESCRIPTORS[Format];
5978 FormatDesc := FormatDescriptor.GetFormatDesc;
5979 if aBuildWithGlu then
5980 gluBuild2DMipmaps(aTarget, FormatDescriptor.GetColorCompCount, Width, Height,
5981 FormatDesc.Format, FormatDesc.DataType, Data)
5983 glTexImage2D(aTarget, 0, FormatDesc.InternalFormat, Width, Height, 0,
5984 FormatDesc.Format, FormatDesc.DataType, Data);
5987 if (FreeDataAfterGenTexture) then
5991 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5992 procedure TglBitmap2D.AfterConstruction;
5995 Target := GL_TEXTURE_2D;
5998 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5999 procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
6002 Size, w, h: Integer;
6003 FormatDesc: TglBitmapFormatDescClass;
6004 glFormatDesc: TglBitmapFormatDesc;
6007 if not FormatIsUncompressed(Format) then
6008 raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_FORMAT);
6011 w := aRight - aLeft;
6012 h := aBottom - aTop;
6013 FormatDesc := FORMAT_DESCRIPTORS[Format];
6014 glFormatDesc := FormatDesc.GetFormatDesc;
6015 Size := FormatDesc.GetSize(glBitmapPosition(w, h));
6018 glPixelStorei(GL_PACK_ALIGNMENT, 1);
6019 glReadPixels(aLeft, aTop, w, h, glFormatDesc.Format, glFormatDesc.DataType, Temp);
6020 SetDataPointer(Temp, Format, w, h);
6028 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6029 procedure TglBitmap2D.GetDataFromTexture;
6032 TempWidth, TempHeight, RedSize, GreenSize, BlueSize, AlphaSize, LumSize: Integer;
6033 TempType, TempIntFormat: Cardinal;
6034 IntFormat: TglBitmapFormat;
6035 FormatDesc: TglBitmapFormatDescClass;
6040 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
6041 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
6042 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
6044 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_RED_SIZE, @RedSize);
6045 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_GREEN_SIZE, @GreenSize);
6046 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_BLUE_SIZE, @BlueSize);
6047 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_ALPHA_SIZE, @AlphaSize);
6048 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_LUMINANCE_SIZE, @LumSize);
6050 IntFormat := tfEmpty;
6051 for FormatDesc in FORMAT_DESCRIPTORS do
6052 if (FormatDesc.GetFormatDesc.InternalFormat = TempIntFormat) then begin
6053 IntFormat := FormatDesc.GetFormat;
6057 // Getting data from OpenGL
6058 GetMem(Temp, FormatDesc.GetSize(glBitmapPosition(TempWidth, TempHeight)));
6061 if FormatIsCompressed(IntFormat) and (GL_VERSION_1_3 or GL_ARB_texture_compression) then
6062 glGetCompressedTexImage(Target, 0, Temp)
6065 with FormatDesc.GetFormatDesc do
6066 glGetTexImage(Target, 0, InternalFormat, DataType, Temp);
6067 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
6074 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6075 procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
6077 BuildWithGlu, PotTex, TexRec: Boolean;
6080 if Assigned(Data) then begin
6081 // Check Texture Size
6082 if (aTestTextureSize) then begin
6083 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
6085 if ((Height > TexSize) or (Width > TexSize)) then
6086 raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
6088 PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
6089 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE_ARB);
6091 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
6092 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
6096 SetupParameters(BuildWithGlu);
6097 UploadData(Target, BuildWithGlu);
6098 glAreTexturesResident(1, @fID, @fIsResident);
6102 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6103 function TglBitmap2D.FlipHorz: Boolean;
6106 TempDestData, DestData, SourceData: PByte;
6109 result := inherited FlipHorz;
6110 if Assigned(Data) then begin
6112 ImgSize := Height * fRowSize;
6113 GetMem(DestData, ImgSize);
6115 TempDestData := DestData;
6116 Dec(TempDestData, fRowSize + fPixelSize);
6117 for Row := 0 to Height -1 do begin
6118 Inc(TempDestData, fRowSize * 2);
6119 for Col := 0 to Width -1 do begin
6120 Move(SourceData^, TempDestData^, fPixelSize);
6121 Inc(SourceData, fPixelSize);
6122 Dec(TempDestData, fPixelSize);
6125 SetDataPointer(DestData, Format);
6134 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6135 function TglBitmap2D.FlipVert: Boolean;
6138 TempDestData, DestData, SourceData: PByte;
6140 result := inherited FlipVert;
6141 if Assigned(Data) then begin
6143 GetMem(DestData, Height * fRowSize);
6145 TempDestData := DestData;
6146 Inc(TempDestData, Width * (Height -1) * fPixelSize);
6147 for Row := 0 to Height -1 do begin
6148 Move(SourceData^, TempDestData^, fRowSize);
6149 Dec(TempDestData, fRowSize);
6150 Inc(SourceData, fRowSize);
6152 SetDataPointer(DestData, Format);
6161 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6162 //TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6163 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6165 TMatrixItem = record
6170 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
6171 TglBitmapToNormalMapRec = Record
6173 Heights: array of Single;
6174 MatrixU : array of TMatrixItem;
6175 MatrixV : array of TMatrixItem;
6179 oneover255 = 1 / 255;
6181 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6182 procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
6186 with FuncRec do begin
6187 Val := Source.Red * 0.3 + Source.Green * 0.59 + Source.Blue * 0.11;
6188 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * oneover255;
6192 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6193 procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
6196 PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Alpha * oneover255;
6199 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6200 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
6202 TVec = Array[0..2] of Single;
6209 function GetHeight(X, Y: Integer): Single;
6211 with FuncRec do begin
6212 X := Max(0, Min(Size.X -1, X));
6213 Y := Max(0, Min(Size.Y -1, Y));
6214 result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
6219 with FuncRec do begin
6220 with PglBitmapToNormalMapRec(Args)^ do begin
6222 for Idx := Low(MatrixU) to High(MatrixU) do
6223 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
6226 for Idx := Low(MatrixU) to High(MatrixU) do
6227 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
6229 Vec[0] := -du * Scale;
6230 Vec[1] := -dv * Scale;
6235 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
6236 if Len <> 0 then begin
6237 Vec[0] := Vec[0] * Len;
6238 Vec[1] := Vec[1] * Len;
6239 Vec[2] := Vec[2] * Len;
6243 Dest.Red := Trunc((Vec[0] + 1) * 127.5);
6244 Dest.Green := Trunc((Vec[1] + 1) * 127.5);
6245 Dest.Blue := Trunc((Vec[2] + 1) * 127.5);
6249 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
6250 procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
6252 Rec: TglBitmapToNormalMapRec;
6254 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
6256 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
6257 Matrix[Index].X := X;
6258 Matrix[Index].Y := Y;
6259 Matrix[Index].W := W;
6265 if not FormatIsUncompressed(InternalFormat) then
6266 raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_FORMAT);
6269 if aScale > 100 then
6271 else if aScale < -100 then
6274 Rec.Scale := aScale;
6276 SetLength(Rec.Heights, Width * Height);
6280 SetLength(Rec.MatrixU, 2);
6281 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
6282 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
6284 SetLength(Rec.MatrixV, 2);
6285 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
6286 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
6290 SetLength(Rec.MatrixU, 6);
6291 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
6292 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
6293 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
6294 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
6295 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
6296 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
6298 SetLength(Rec.MatrixV, 6);
6299 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
6300 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
6301 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
6302 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
6303 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
6304 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
6308 SetLength(Rec.MatrixU, 6);
6309 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
6310 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
6311 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
6312 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
6313 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
6314 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
6316 SetLength(Rec.MatrixV, 6);
6317 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
6318 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
6319 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
6320 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
6321 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
6322 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
6326 SetLength(Rec.MatrixU, 20);
6327 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
6328 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
6329 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
6330 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
6331 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
6332 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
6333 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
6334 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
6335 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
6336 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
6337 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
6338 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
6339 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
6340 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
6341 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
6342 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
6343 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
6344 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
6345 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
6346 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
6348 SetLength(Rec.MatrixV, 20);
6349 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
6350 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
6351 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
6352 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
6353 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
6354 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
6355 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
6356 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
6357 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
6358 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
6359 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
6360 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
6361 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
6362 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
6363 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
6364 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
6365 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
6366 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
6367 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
6368 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
6373 if aUseAlpha and FORMAT_DESCRIPTORS[Format].HasAlpha then
6374 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, PtrInt(@Rec))
6376 AddFunc(glBitmapToNormalMapPrepareFunc, false, PtrInt(@Rec));
6377 AddFunc(glBitmapToNormalMapFunc, false, PtrInt(@Rec));
6379 SetLength(Rec.Heights, 0);
6392 procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
6397 if Height > 1 then begin
6398 // extract first line of the data
6399 Size := FormatGetImageSize(glBitmapPosition(Width), Format);
6400 GetMem(pTemp, Size);
6402 Move(Data^, pTemp^, Size);
6409 inherited SetDataPointer(pTemp, Format, Width);
6411 if FormatIsUncompressed(Format) then begin
6412 fUnmapFunc := FormatGetUnMapFunc(Format);
6413 fGetPixelFunc := GetPixel1DUnmap;
6418 procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
6423 Inc(pTemp, Pos.X * fPixelSize);
6425 fUnmapFunc(pTemp, Pixel);
6429 function TglBitmap1D.FlipHorz: Boolean;
6432 pTempDest, pDest, pSource: pByte;
6434 result := inherited FlipHorz;
6436 if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin
6439 GetMem(pDest, fRowSize);
6443 Inc(pTempDest, fRowSize);
6444 for Col := 0 to Width -1 do begin
6445 Move(pSource^, pTempDest^, fPixelSize);
6447 Inc(pSource, fPixelSize);
6448 Dec(pTempDest, fPixelSize);
6451 SetDataPointer(pDest, InternalFormat);
6461 procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
6464 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
6465 glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data)
6469 if BuildWithGlu then
6470 gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data)
6472 glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data);
6475 if (FreeDataAfterGenTexture) then
6480 procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean);
6482 BuildWithGlu, TexRec: Boolean;
6483 glFormat, glInternalFormat, glType: Cardinal;
6486 if Assigned(Data) then begin
6487 // Check Texture Size
6488 if (TestTextureSize) then begin
6489 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
6491 if (Width > TexSize) then
6492 raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
6494 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
6495 (Target = GL_TEXTURE_RECTANGLE_ARB);
6497 if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
6498 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
6503 SetupParameters(BuildWithGlu);
6504 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
6506 UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
6509 glAreTexturesResident(1, @fID, @fIsResident);
6514 procedure TglBitmap1D.AfterConstruction;
6518 Target := GL_TEXTURE_1D;
6522 { TglBitmapCubeMap }
6524 procedure TglBitmapCubeMap.AfterConstruction;
6528 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
6529 raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
6531 SetWrap; // set all to GL_CLAMP_TO_EDGE
6532 Target := GL_TEXTURE_CUBE_MAP;
6533 fGenMode := GL_REFLECTION_MAP;
6537 procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean);
6539 inherited Bind (EnableTextureUnit);
6541 if EnableTexCoordsGen then begin
6542 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
6543 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
6544 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
6545 glEnable(GL_TEXTURE_GEN_S);
6546 glEnable(GL_TEXTURE_GEN_T);
6547 glEnable(GL_TEXTURE_GEN_R);
6552 procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean);
6554 glFormat, glInternalFormat, glType: Cardinal;
6555 BuildWithGlu: Boolean;
6558 // Check Texture Size
6559 if (TestTextureSize) then begin
6560 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
6562 if ((Height > TexSize) or (Width > TexSize)) then
6563 raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
6565 if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
6566 raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
6570 if ID = 0 then begin
6572 SetupParameters(BuildWithGlu);
6575 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
6577 UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu);
6581 procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean);
6583 Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
6587 procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen,
6588 DisableTextureUnit: Boolean);
6590 inherited Unbind (DisableTextureUnit);
6592 if DisableTexCoordsGen then begin
6593 glDisable(GL_TEXTURE_GEN_S);
6594 glDisable(GL_TEXTURE_GEN_T);
6595 glDisable(GL_TEXTURE_GEN_R);
6600 { TglBitmapNormalMap }
6603 TVec = Array[0..2] of Single;
6604 TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6606 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
6607 TglBitmapNormalMapRec = record
6609 Func: TglBitmapNormalMapGetVectorFunc;
6613 procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6616 Vec[1] := - (Position.Y + 0.5 - HalfSize);
6617 Vec[2] := - (Position.X + 0.5 - HalfSize);
6621 procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6623 Vec[0] := - HalfSize;
6624 Vec[1] := - (Position.Y + 0.5 - HalfSize);
6625 Vec[2] := Position.X + 0.5 - HalfSize;
6629 procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6631 Vec[0] := Position.X + 0.5 - HalfSize;
6633 Vec[2] := Position.Y + 0.5 - HalfSize;
6637 procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6639 Vec[0] := Position.X + 0.5 - HalfSize;
6640 Vec[1] := - HalfSize;
6641 Vec[2] := - (Position.Y + 0.5 - HalfSize);
6645 procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6647 Vec[0] := Position.X + 0.5 - HalfSize;
6648 Vec[1] := - (Position.Y + 0.5 - HalfSize);
6653 procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6655 Vec[0] := - (Position.X + 0.5 - HalfSize);
6656 Vec[1] := - (Position.Y + 0.5 - HalfSize);
6657 Vec[2] := - HalfSize;
6661 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
6666 with FuncRec do begin
6667 with PglBitmapNormalMapRec (CustomData)^ do begin
6668 Func(Vec, Position, HalfSize);
6671 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
6672 if Len <> 0 then begin
6673 Vec[0] := Vec[0] * Len;
6674 Vec[1] := Vec[1] * Len;
6675 Vec[2] := Vec[2] * Len;
6678 // Scale Vector and AddVectro
6679 Vec[0] := Vec[0] * 0.5 + 0.5;
6680 Vec[1] := Vec[1] * 0.5 + 0.5;
6681 Vec[2] := Vec[2] * 0.5 + 0.5;
6685 Dest.Red := Round(Vec[0] * 255);
6686 Dest.Green := Round(Vec[1] * 255);
6687 Dest.Blue := Round(Vec[2] * 255);
6692 procedure TglBitmapNormalMap.AfterConstruction;
6696 fGenMode := GL_NORMAL_MAP;
6700 procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer;
6701 TestTextureSize: Boolean);
6703 Rec: TglBitmapNormalMapRec;
6704 SizeRec: TglBitmapPixelPosition;
6706 Rec.HalfSize := Size div 2;
6708 FreeDataAfterGenTexture := false;
6710 SizeRec.Fields := [ffX, ffY];
6715 Rec.Func := glBitmapNormalMapPosX;
6716 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6717 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize);
6720 Rec.Func := glBitmapNormalMapNegX;
6721 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6722 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize);
6725 Rec.Func := glBitmapNormalMapPosY;
6726 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6727 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize);
6730 Rec.Func := glBitmapNormalMapNegY;
6731 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6732 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize);
6735 Rec.Func := glBitmapNormalMapPosZ;
6736 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6737 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize);
6740 Rec.Func := glBitmapNormalMapNegZ;
6741 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6742 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize);
6747 glBitmapSetDefaultFormat(tfEmpty);
6748 glBitmapSetDefaultMipmap(mmMipmap);
6749 glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
6750 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
6752 glBitmapSetDefaultFreeDataAfterGenTexture(true);
6753 glBitmapSetDefaultDeleteTextureOnFree (true);