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;
604 ////////////////////////////////////////////////////////////////////////////////////////////////////
605 TglBitmapPixelData = packed record
610 PixelDesc: TglBitmapPixelDesc;
613 ////////////////////////////////////////////////////////////////////////////////////////////////////
614 TglBitmapFormatDesc = packed record
616 InternalFormat: Cardinal;
620 ////////////////////////////////////////////////////////////////////////////////////////////////////
621 TglBitmapPixelPositionFields = set of (ffX, ffY);
622 TglBitmapPixelPosition = record
623 Fields : TglBitmapPixelPositionFields;
628 ////////////////////////////////////////////////////////////////////////////////////////////////////
630 TglBitmapFunctionRec = record
632 Size: TglBitmapPixelPosition;
633 Position: TglBitmapPixelPosition;
634 Source: TglBitmapPixelData;
635 Dest: TglBitmapPixelData;
638 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
640 ////////////////////////////////////////////////////////////////////////////////////////////////////
641 TglBitmapFileType = (
642 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
643 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
647 TglBitmapFileTypes = set of TglBitmapFileType;
654 TglBitmapNormalMapFunc = (
676 { tfLuminance12Alpha4,
677 tfLuminance12Alpha12,
678 tfLuminance16Alpha16,
704 ////////////////////////////////////////////////////////////////////////////////////////////////////
705 TglBitmapGetPixel = procedure(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData) of object;
706 TglBitmapSetPixel = procedure(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData) of object;
708 TglBitmapMapFunc = procedure(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
709 TglBitmapUnMapFunc = procedure(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData);
711 ////////////////////////////////////////////////////////////////////////////////////////////////////
712 TglBitmapFormatDescriptor = class(TObject)
715 class function GetFormat: TglBitmapFormat; virtual; abstract;
716 class function GetPixelDesc: TglBitmapPixelDesc; virtual; abstract;
717 class function GetFormatDesc: TglBitmapFormatDesc; virtual; abstract;
719 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); virtual; abstract;
720 class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); virtual; abstract;
723 class function WithoutAlpha: TglBitmapFormat; virtual;
724 class function WithAlpha: TglBitmapFormat; virtual;
726 class function IsEmpty: Boolean; virtual;
727 class function HasAlpha: Boolean; virtual;
728 class function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual;
730 class procedure PreparePixel(var aPixel: TglBitmapPixelData); virtual;
733 function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
734 function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
735 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
736 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
737 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
740 TglBitmapFormatDescClass = class of TglBitmapFormatDescriptor;
747 fAnisotropic: Integer;
748 fDeleteTextureOnFree: Boolean;
749 fFreeDataAfterGenTexture: Boolean;
751 fIsResident: Boolean;
752 fBorderColor: array[0..3] of Single;
754 fDimension: TglBitmapPixelPosition;
755 fMipMap: TglBitmapMipMap;
756 fFormat: TglBitmapFormat;
761 fUnmapFunc: TglBitmapUnMapFunc;
762 fMapFunc: TglBitmapMapFunc;
765 fFilterMin: Cardinal;
766 fFilterMag: Cardinal;
773 fGetPixelFunc: TglBitmapGetPixel;
774 fSetPixelFunc: TglBitmapSetPixel;
779 fCustomNameW: WideString;
780 fCustomData: Pointer;
783 function GetHeight: Integer; virtual;
784 function GetWidth: Integer; virtual;
787 procedure SetCustomData(const aValue: Pointer);
788 procedure SetCustomName(const aValue: String);
789 procedure SetCustomNameW(const aValue: WideString);
790 procedure SetDeleteTextureOnFree(const aValue: Boolean);
791 procedure SetFormat(const aValue: TglBitmapFormat);
792 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
793 procedure SetID(const aValue: Cardinal);
794 procedure SetMipMap(const aValue: TglBitmapMipMap);
795 procedure SetTarget(const aValue: Cardinal);
796 procedure SetAnisotropic(const aValue: Integer);
799 {$IFDEF GLB_SUPPORT_PNG_READ}
800 function LoadPNG(Stream: TStream): Boolean; virtual;
802 {$IFDEF GLB_SUPPORT_JPEG_READ}
803 function LoadJPEG(Stream: TStream): Boolean; virtual;
805 function LoadDDS(Stream: TStream): Boolean; virtual;
806 function LoadTGA(Stream: TStream): Boolean; virtual;
807 function LoadBMP(Stream: TStream): Boolean; virtual;
810 {$IFDEF GLB_SUPPORT_PNG_WRITE}
811 procedure SavePNG(Stream: TStream); virtual;
813 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
814 procedure SaveJPEG(Stream: TStream); virtual;
816 procedure SaveDDS(Stream: TStream); virtual;
817 procedure SaveTGA(Stream: TStream); virtual;
818 procedure SaveBMP(Stream: TStream); virtual;
821 procedure SetupParameters(var aBuildWithGlu: Boolean);
822 procedure SelectFormat(const aFormat: TglBitmapFormat; var glFormat, glInternalFormat, glType: Cardinal);
824 procedure SetDataPointer(NewData: pByte; Format: TglBitmapFormat; Width: Integer = -1; Height: Integer = -1); virtual;
825 procedure GenTexture(TestTextureSize: Boolean = True); virtual; abstract;
827 function FlipHorz: Boolean; virtual;
828 function FlipVert: Boolean; virtual;
830 property Width: Integer read GetWidth;
831 property Height: Integer read GetHeight;
833 property ID: Cardinal read fID write SetID;
834 property Target: Cardinal read fTarget write SetTarget;
835 property Format: TglBitmapFormat read fFormat write SetFormat;
836 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
837 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
839 property Filename: String read fFilename;
840 property CustomName: String read fCustomName write SetCustomName;
841 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
842 property CustomData: Pointer read fCustomData write SetCustomData;
844 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
845 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
847 property Dimension: TglBitmapPixelPosition read fDimension;
848 property Data: PByte read fData;
849 property IsResident: Boolean read fIsResident;
851 procedure AfterConstruction; override;
852 procedure BeforeDestruction; override;
855 procedure LoadFromFile(const aFileName: String);
856 procedure LoadFromStream(const aStream: TStream); virtual;
857 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
858 const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0);
860 procedure LoadFromResource(const aInstance: Cardinal; aResource: String; const aResType: PChar = nil);
861 procedure LoadFromResourceID(const sInstance: Cardinal; aResourceID: Integer; const aResType: PChar);
864 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
865 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
867 //function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; Format: TglBitmapFormat; CustomData: Pointer = nil): boolean; overload;
868 //function AddFunc(const aFunc: TglBitmapFunction; CreateTemp: Boolean; CustomData: Pointer = nil): boolean; overload;
871 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
872 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
873 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
874 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
875 const aArgs: PtrInt = 0): Boolean;
879 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
880 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
881 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
882 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
883 const aArgs: PtrInt = 0): Boolean;
886 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0): Boolean; virtual;
887 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
888 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
889 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
891 function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil;
892 const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
893 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
894 const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
897 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
898 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
899 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
901 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
902 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
903 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
905 function RemoveAlpha: Boolean; virtual;
906 function Clone: TglBitmap;
907 function ConvertTo(const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapFormat): Boolean; virtual;
908 procedure SetBorderColor(Red, Green, Blue, Alpha: Single);
909 procedure Invert(const aUseRGB: Boolean = true; aUseAlpha: Boolean = false);
912 procedure FillWithColor(const aRed, aGreen, aBlue: aByte; Alpha: Byte = 255);
913 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
914 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
916 procedure SetFilter(const aMin, aMag: Cardinal);
918 const S: Cardinal = GL_CLAMP_TO_EDGE;
919 const T: Cardinal = GL_CLAMP_TO_EDGE;
920 const R: Cardinal = GL_CLAMP_TO_EDGE);
922 procedure GetPixel(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); virtual;
923 procedure SetPixel(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); virtual;
925 procedure Unbind(DisableTextureUnit: Boolean = True); virtual;
926 procedure Bind(EnableTextureUnit: Boolean = True); virtual;
928 constructor Create; overload;
929 constructor Create(FileName: String); overload;
930 constructor Create(Stream: TStream); overload;
932 constructor CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar = nil);
933 constructor Create(Instance: Cardinal; Resource: String; ResType: PChar = nil); overload;
934 constructor Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar); overload;
936 constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapFormat); overload;
937 constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapFormat; Func: TglBitmapFunction; CustomData: Pointer = nil); overload;
941 TglBitmap2D = class(TglBitmap)
944 fLines: array of PByte;
946 procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
947 procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
948 procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
949 procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
950 procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
951 function GetScanline(Index: Integer): Pointer;
953 procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
955 procedure SetDataPointer(Data: pByte; Format: TglBitmapFormat; Width: Integer = -1; Height: Integer = -1); override;
956 procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
960 property Scanline[Index: Integer]: Pointer read GetScanline;
962 procedure AfterConstruction; override;
964 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
965 procedure GetDataFromTexture;
966 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3; const aScale: Single = 2; const aUseAlpha: Boolean = False);
967 procedure GenTexture(TestTextureSize: Boolean = True); override;
969 function FlipHorz: Boolean; override;
970 function FlipVert: Boolean; override;
974 TglBitmapCubeMap = class(TglBitmap2D)
979 procedure GenTexture(TestTextureSize: Boolean = True); reintroduce;
981 procedure AfterConstruction; override;
983 procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true);
985 procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = True); reintroduce; virtual;
986 procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = True); reintroduce; virtual;
990 TglBitmapNormalMap = class(TglBitmapCubeMap)
992 procedure AfterConstruction; override;
994 procedure GenerateNormalMap(Size: Integer = 32; TestTextureSize: Boolean = true);
998 TglBitmap1D = class(TglBitmap)
1000 procedure GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
1002 procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override;
1003 procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
1008 procedure AfterConstruction; override;
1011 function FlipHorz: Boolean; override;
1014 procedure GenTexture(TestTextureSize: Boolean = True); override;
1019 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
1021 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1022 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1023 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1024 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1025 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1026 procedure glBitmapSetDefaultWrap(
1027 const S: Cardinal = GL_CLAMP_TO_EDGE;
1028 const T: Cardinal = GL_CLAMP_TO_EDGE;
1029 const R: Cardinal = GL_CLAMP_TO_EDGE);
1031 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1032 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1033 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1034 function glBitmapGetDefaultFormat: TglBitmapFormat;
1035 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1036 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1038 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1041 function FormatGetSize(const aFormat: TglBitmapFormat): Single;
1044 glBitmapDefaultDeleteTextureOnFree: Boolean;
1045 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1046 glBitmapDefaultFormat: TglBitmapFormat;
1047 glBitmapDefaultMipmap: TglBitmapMipMap;
1048 glBitmapDefaultFilterMin: Cardinal;
1049 glBitmapDefaultFilterMag: Cardinal;
1050 glBitmapDefaultWrapS: Cardinal;
1051 glBitmapDefaultWrapT: Cardinal;
1052 glBitmapDefaultWrapR: Cardinal;
1055 function CreateGrayPalette: HPALETTE;
1064 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1065 TfdEmpty = class(TglBitmapFormatDescriptor)
1067 class function GetFormat: TglBitmapFormat; override;
1068 class function GetPixelDesc: TglBitmapPixelDesc; override;
1069 class function GetFormatDesc: TglBitmapFormatDesc; override;
1071 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override;
1072 class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override;
1075 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1076 TfdLuminance8 = class(TglBitmapFormatDescriptor)
1078 class function GetFormat: TglBitmapFormat; override;
1079 class function GetPixelDesc: TglBitmapPixelDesc; override;
1080 class function GetFormatDesc: TglBitmapFormatDesc; override;
1081 class function WithAlpha: TglBitmapFormat; override;
1083 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override;
1084 class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override;
1087 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1088 TfdLuminance8Alpha8 = class(TglBitmapFormatDescriptor)
1090 class function GetFormat: TglBitmapFormat; override;
1091 class function GetPixelDesc: TglBitmapPixelDesc; override;
1092 class function GetFormatDesc: TglBitmapFormatDesc; override;
1093 class function WithoutAlpha: TglBitmapFormat; override;
1095 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override;
1096 class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override;
1099 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1100 TfdRGB8 = class(TglBitmapFormatDescriptor)
1102 class function GetFormat: TglBitmapFormat; override;
1103 class function GetPixelDesc: TglBitmapPixelDesc; override;
1104 class function GetFormatDesc: TglBitmapFormatDesc; override;
1105 class function WithAlpha: TglBitmapFormat; override;
1107 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override;
1108 class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override;
1111 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1112 TfdRGBA8 = class(TglBitmapFormatDescriptor)
1114 class function GetFormat: TglBitmapFormat; override;
1115 class function GetPixelDesc: TglBitmapPixelDesc; override;
1116 class function GetFormatDesc: TglBitmapFormatDesc; override;
1117 class function WithoutAlpha: TglBitmapFormat; override;
1119 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override;
1120 class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override;
1123 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1124 TfdBGR8 = class(TglBitmapFormatDescriptor)
1126 class function GetFormat: TglBitmapFormat; override;
1127 class function GetPixelDesc: TglBitmapPixelDesc; override;
1128 class function GetFormatDesc: TglBitmapFormatDesc; override;
1129 class function WithAlpha: TglBitmapFormat; override;
1131 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override;
1132 class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override;
1135 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1136 TfdBGRA8 = class(TglBitmapFormatDescriptor)
1138 class function GetFormat: TglBitmapFormat; override;
1139 class function GetPixelDesc: TglBitmapPixelDesc; override;
1140 class function GetFormatDesc: TglBitmapFormatDesc; override;
1141 class function WithoutAlpha: TglBitmapFormat; override;
1143 class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override;
1144 class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override;
1148 LUMINANCE_WEIGHT_R = 0.30;
1149 LUMINANCE_WEIGHT_G = 0.59;
1150 LUMINANCE_WEIGHT_B = 0.11;
1151 UNSUPPORTED_INTERNAL_FORMAT = 'the given format isn''t supported by this function.';
1153 {$REGION Private Helper}
1154 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1155 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1157 Result.Fields := [];
1160 Result.Fields := Result.Fields + [ffX];
1162 Result.Fields := Result.Fields + [ffY];
1164 Result.X := Max(0, X);
1165 Result.Y := Max(0, Y);
1168 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1169 function FormatGetImageSize(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat): Integer;
1171 if (aSize.X = 0) and (aSize.Y = 0) then
1174 Result := Ceil(Max(aSize.Y, 1) * Max(aSize.X, 1) * FormatGetSize(aFormat));
1177 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1178 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
1180 //TODO check Formats!
1183 {$IFDEF GLB_SUPPORT_PNG_WRITE}
1185 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1186 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1187 tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
1188 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1189 tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
1190 tfDepth16, tfDepth24, tfDepth32]
1192 result := result + [ftPNG];
1195 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
1197 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1198 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1199 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1200 tfDepth16, tfDepth24, tfDepth32]
1202 result := result + [ftJPEG];
1206 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
1207 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
1208 tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
1209 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
1210 tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
1211 tfDepth16, tfDepth24, tfDepth32]
1213 result := result + [ftDDS, ftTGA, ftBMP];
1216 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1217 function IsPowerOfTwo(aNumber: Integer): Boolean;
1219 while (aNumber and 1) = 0 do
1220 aNumber := aNumber shr 1;
1221 result := aNumber = 1;
1224 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1225 function GetBitSize(aBitSet: Cardinal): Integer;
1228 while aBitSet > 0 do begin
1229 if (aBitSet and 1) = 1 then
1231 aBitSet := aBitSet shr 1;
1237 {$IFNDEF GLB_NO_NATIVE_GL}
1238 procedure ReadOpenGLExtensions;
1244 MajorVersion, MinorVersion: Integer;
1247 procedure TrimVersionString(Buffer: AnsiString; var Major, Minor: Integer);
1254 Separator := Pos(AnsiString('.'), Buffer);
1256 if (Separator > 1) and (Separator < Length(Buffer)) and
1257 (Buffer[Separator - 1] in ['0'..'9']) and
1258 (Buffer[Separator + 1] in ['0'..'9']) then begin
1261 while (Separator > 0) and (Buffer[Separator] in ['0'..'9']) do
1264 Delete(Buffer, 1, Separator);
1265 Separator := Pos(AnsiString('.'), Buffer) + 1;
1267 while (Separator <= Length(Buffer)) and (AnsiChar(Buffer[Separator]) in ['0'..'9']) do
1270 Delete(Buffer, Separator, 255);
1271 Separator := Pos(AnsiString('.'), Buffer);
1273 Major := StrToInt(Copy(String(Buffer), 1, Separator - 1));
1274 Minor := StrToInt(Copy(String(Buffer), Separator + 1, 1));
1279 function CheckExtension(const Extension: AnsiString): Boolean;
1283 ExtPos := Pos(Extension, Buffer);
1284 Result := ExtPos > 0;
1287 Result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
1291 function glLoad (aFunc: pAnsiChar): pointer;
1294 Result := glXGetProcAddress(aFunc);
1296 Result := wglGetProcAddress(aFunc);
1303 Context := wglGetCurrentContext;
1305 if Context <> gLastContext then begin
1306 gLastContext := Context;
1310 Buffer := glGetString(GL_VERSION);
1311 TrimVersionString(Buffer, MajorVersion, MinorVersion);
1313 GL_VERSION_1_2 := False;
1314 GL_VERSION_1_3 := False;
1315 GL_VERSION_1_4 := False;
1316 GL_VERSION_2_0 := False;
1318 if MajorVersion = 1 then begin
1319 if MinorVersion >= 1 then begin
1320 if MinorVersion >= 2 then
1321 GL_VERSION_1_2 := True;
1323 if MinorVersion >= 3 then
1324 GL_VERSION_1_3 := True;
1326 if MinorVersion >= 4 then
1327 GL_VERSION_1_4 := True;
1331 if MajorVersion >= 2 then begin
1332 GL_VERSION_1_2 := True;
1333 GL_VERSION_1_3 := True;
1334 GL_VERSION_1_4 := True;
1335 GL_VERSION_2_0 := True;
1339 Buffer := glGetString(GL_EXTENSIONS);
1340 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
1341 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
1342 GL_ARB_texture_compression := CheckExtension('GL_ARB_texture_compression');
1343 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
1344 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
1345 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
1346 GL_EXT_bgra := CheckExtension('GL_EXT_bgra');
1347 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
1348 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
1349 GL_EXT_texture_compression_s3tc := CheckExtension('GL_EXT_texture_compression_s3tc');
1350 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
1351 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
1352 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
1353 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
1354 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
1357 if GL_VERSION_1_3 then begin
1359 glCompressedTexImage1D := glLoad('glCompressedTexImage1D');
1360 glCompressedTexImage2D := glLoad('glCompressedTexImage2D');
1361 glGetCompressedTexImage := glLoad('glGetCompressedTexImage');
1365 // Try loading Extension
1366 glCompressedTexImage1D := glLoad('glCompressedTexImage1DARB');
1367 glCompressedTexImage2D := glLoad('glCompressedTexImage2DARB');
1368 glGetCompressedTexImage := glLoad('glGetCompressedTexImageARB');
1379 function CreateGrayPalette: HPALETTE;
1384 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
1386 Pal.palVersion := $300;
1387 Pal.palNumEntries := 256;
1390 {$DEFINE GLB_TEMPRANGECHECK}
1394 for Idx := 0 to 256 - 1 do begin
1395 Pal.palPalEntry[Idx].peRed := Idx;
1396 Pal.palPalEntry[Idx].peGreen := Idx;
1397 Pal.palPalEntry[Idx].peBlue := Idx;
1398 Pal.palPalEntry[Idx].peFlags := 0;
1401 {$IFDEF GLB_TEMPRANGECHECK}
1402 {$UNDEF GLB_TEMPRANGECHECK}
1406 Result := CreatePalette(Pal^);
1413 (* TODO GLB_SDL_IMAGE
1414 {$IFDEF GLB_SDL_IMAGE}
1415 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
1417 Result := TStream(context^.unknown.data1).Seek(offset, whence);
1420 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
1422 Result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
1425 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
1427 Result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
1430 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
1435 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
1437 Result := SDL_AllocRW;
1439 if Result = nil then
1440 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
1442 Result^.seek := glBitmapRWseek;
1443 Result^.read := glBitmapRWread;
1444 Result^.write := glBitmapRWwrite;
1445 Result^.close := glBitmapRWclose;
1446 Result^.unknown.data1 := Stream;
1452 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
1454 glBitmap: TglBitmap2D;
1460 if Instance = 0 then
1461 Instance := HInstance;
1463 if (LoadFromRes) then
1464 glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName)
1467 glBitmap := TglBitmap2D.Create(FileName);
1470 glBitmap.DeleteTextureOnFree := False;
1471 glBitmap.FreeDataAfterGenTexture := False;
1472 glBitmap.GenTexture(True);
1473 if (glBitmap.ID > 0) then begin
1474 Texture := glBitmap.ID;
1482 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
1484 CM: TglBitmapCubeMap;
1489 if Instance = 0 then
1490 Instance := HInstance;
1493 CM := TglBitmapCubeMap.Create;
1495 CM.DeleteTextureOnFree := False;
1499 if (LoadFromRes) then
1500 CM.LoadFromResource(Instance, PositiveX)
1503 CM.LoadFromFile(PositiveX);
1504 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
1507 if (LoadFromRes) then
1508 CM.LoadFromResource(Instance, NegativeX)
1511 CM.LoadFromFile(NegativeX);
1512 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
1515 if (LoadFromRes) then
1516 CM.LoadFromResource(Instance, PositiveY)
1519 CM.LoadFromFile(PositiveY);
1520 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
1523 if (LoadFromRes) then
1524 CM.LoadFromResource(Instance, NegativeY)
1527 CM.LoadFromFile(NegativeY);
1528 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
1531 if (LoadFromRes) then
1532 CM.LoadFromResource(Instance, PositiveZ)
1535 CM.LoadFromFile(PositiveZ);
1536 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
1539 if (LoadFromRes) then
1540 CM.LoadFromResource(Instance, NegativeZ)
1543 CM.LoadFromFile(NegativeZ);
1544 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
1553 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
1555 NM: TglBitmapNormalMap;
1559 NM := TglBitmapNormalMap.Create;
1561 NM.DeleteTextureOnFree := False;
1562 NM.GenerateNormalMap(Size);
1572 {$REGION default Setter and Gettter}
1573 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1574 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
1576 glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
1579 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1580 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
1582 glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
1585 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1586 procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
1588 glBitmapDefaultMipmap := aValue;
1591 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1592 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
1594 glBitmapDefaultFormat := aFormat;
1597 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1598 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1600 glBitmapDefaultFilterMin := aMin;
1601 glBitmapDefaultFilterMag := aMag;
1604 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1605 procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
1607 glBitmapDefaultWrapS := S;
1608 glBitmapDefaultWrapT := T;
1609 glBitmapDefaultWrapR := R;
1612 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1613 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1615 result := glBitmapDefaultDeleteTextureOnFree;
1618 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1619 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1621 result := glBitmapDefaultFreeDataAfterGenTextures;
1624 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1625 function glBitmapGetDefaultMipmap: TglBitmapMipMap;
1627 result := glBitmapDefaultMipmap;
1630 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1631 function glBitmapGetDefaultFormat: TglBitmapFormat;
1633 result := glBitmapDefaultFormat;
1636 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1637 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1639 aMin := glBitmapDefaultFilterMin;
1640 aMag := glBitmapDefaultFilterMag;
1643 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1644 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1646 S := glBitmapDefaultWrapS;
1647 T := glBitmapDefaultWrapT;
1648 R := glBitmapDefaultWrapR;
1652 {$REGION TglBitmapFormatDescriptor}
1653 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1654 //TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1655 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1656 class function TglBitmapFormatDescriptor.WithoutAlpha: TglBitmapFormat;
1658 if not HasAlpha then
1664 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1665 class function TglBitmapFormatDescriptor.WithAlpha: TglBitmapFormat;
1673 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1674 class function TglBitmapFormatDescriptor.IsEmpty: Boolean;
1676 result := (GetFormat = tfEmpty);
1679 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1680 class function TglBitmapFormatDescriptor.HasAlpha: Boolean;
1682 result := (GetPixelDesc.AlphaRange > 0);
1685 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1686 class function TglBitmapFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean;
1688 PixelDesc: TglBitmapPixelDesc;
1692 if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
1693 raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
1695 PixelDesc := GetPixelDesc;
1696 with PixelDesc do begin
1697 if (aRedMask <> 0) and (aRedMask <> (RedRange shl RedShift)) then
1699 if (aGreenMask <> 0) and (aGreenMask <> (GreenRange shl GreenShift)) then
1701 if (aBlueMask <> 0) and (aBlueMask <> (BlueRange shl BlueShift)) then
1703 if (aAlphaMask <> 0) and (aAlphaMask <> (AlphaRange shl AlphaShift)) then
1709 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1710 class procedure TglBitmapFormatDescriptor.PreparePixel(var aPixel: TglBitmapPixelData);
1712 FillChar(aPixel, SizeOf(aPixel), 0);
1713 with GetPixelDesc do begin
1714 aPixel.Red := RedRange;
1715 aPixel.Green := GreenRange;
1716 aPixel.Blue := BlueRange;
1717 aPixel.Alpha := AlphaRange;
1723 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1724 //TfdEmpty////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1725 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1726 class function TfdEmpty.GetFormat: TglBitmapFormat;
1731 class function TfdEmpty.GetPixelDesc: TglBitmapPixelDesc;
1733 with result do begin
1734 RedRange := $00000000; RedShift := 0;
1735 GreenRange := $00000000; GreenShift := 0;
1736 BlueRange := $00000000; BlueShift := 0;
1737 AlphaRange := $00000000; AlphaShift := 0;
1741 class function TfdEmpty.GetFormatDesc: TglBitmapFormatDesc;
1743 with result do begin
1745 InternalFormat := 0;
1750 class procedure TfdEmpty.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1752 raise EglBitmapException.Create('format does not support mapping');
1755 class procedure TfdEmpty.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData);
1757 raise EglBitmapException.Create('format does not support unmapping');
1761 {$REGION TfdLuminance8}
1762 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1763 //TfdLuminance8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1764 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1765 class function TfdLuminance8.GetFormat: TglBitmapFormat;
1770 class function TfdLuminance8.GetPixelDesc: TglBitmapPixelDesc;
1772 with result do begin
1773 RedRange := $000000FF; RedShift := 0;
1774 GreenRange := $000000FF; GreenShift := 0;
1775 BlueRange := $000000FF; BlueShift := 0;
1776 AlphaRange := $00000000; AlphaShift := 0;
1780 class function TfdLuminance8.GetFormatDesc: TglBitmapFormatDesc;
1782 with result do begin
1783 Format := GL_LUMINANCE;
1784 InternalFormat := GL_LUMINANCE8;
1785 DataType := GL_UNSIGNED_BYTE;
1789 class function TfdLuminance8.WithAlpha: TglBitmapFormat;
1791 result := tfLuminance8Alpha8;
1794 class procedure TfdLuminance8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1797 aPixel.Red * LUMINANCE_WEIGHT_R +
1798 aPixel.Green * LUMINANCE_WEIGHT_G +
1799 aPixel.Blue * LUMINANCE_WEIGHT_B);
1803 class procedure TfdLuminance8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData);
1805 aPixel.Red := aData^;
1806 aPixel.Green := aData^;
1807 aPixel.Blue := aData^;
1813 {$REGION TfdLuminance8Alpha8}
1814 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1815 //TfdLuminance8Alpha8/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1816 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1817 class function TfdLuminance8Alpha8.GetFormat: TglBitmapFormat;
1819 result := tfLuminance8Alpha8;
1822 class function TfdLuminance8Alpha8.GetPixelDesc: TglBitmapPixelDesc;
1824 with result do begin
1825 RedRange := $000000FF; RedShift := 0;
1826 GreenRange := $000000FF; GreenShift := 0;
1827 BlueRange := $000000FF; BlueShift := 0;
1828 AlphaRange := $000000FF; AlphaShift := 8;
1832 class function TfdLuminance8Alpha8.GetFormatDesc: TglBitmapFormatDesc;
1834 with result do begin
1835 Format := GL_LUMINANCE_ALPHA;
1836 InternalFormat := GL_LUMINANCE8_ALPHA8;
1837 DataType := GL_UNSIGNED_BYTE;
1841 class function TfdLuminance8Alpha8.WithoutAlpha: TglBitmapFormat;
1843 result := tfLuminance8;
1846 class procedure TfdLuminance8Alpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1849 aPixel.Red * LUMINANCE_WEIGHT_R +
1850 aPixel.Green * LUMINANCE_WEIGHT_G +
1851 aPixel.Blue * LUMINANCE_WEIGHT_B);
1854 aData^ := aPixel.Alpha;
1858 class procedure TfdLuminance8Alpha8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData);
1860 aPixel.Red := aData^;
1861 aPixel.Green := aData^;
1862 aPixel.Blue := aData^;
1865 aPixel.Alpha := aData^;
1871 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1872 //TfdRGB8/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1873 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1874 class function TfdRGB8.GetFormat: TglBitmapFormat;
1879 class function TfdRGB8.GetPixelDesc: TglBitmapPixelDesc;
1881 with result do begin
1882 RedRange := $000000FF; RedShift := 0;
1883 GreenRange := $000000FF; GreenShift := 8;
1884 BlueRange := $000000FF; BlueShift := 16;
1885 AlphaRange := $00000000; AlphaShift := 0;
1889 class function TfdRGB8.GetFormatDesc: TglBitmapFormatDesc;
1891 with result do begin
1892 Format := GL_LUMINANCE;
1893 InternalFormat := GL_LUMINANCE8;
1894 DataType := GL_UNSIGNED_BYTE;
1898 class function TfdRGB8.WithAlpha: TglBitmapFormat;
1903 class procedure TfdRGB8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1905 aData^ := aPixel.Red;
1907 aData^ := aPixel.Green;
1909 aData^ := aPixel.Blue;
1913 class procedure TfdRGB8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData);
1915 aPixel.Red := aData^;
1917 aPixel.Green := aData^;
1919 aPixel.Blue := aData^;
1926 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1927 //TfdRGBA8////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1928 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1929 class function TfdRGBA8.GetFormat: TglBitmapFormat;
1934 class function TfdRGBA8.GetPixelDesc: TglBitmapPixelDesc;
1936 with result do begin
1937 RedRange := $000000FF; RedShift := 0;
1938 GreenRange := $000000FF; GreenShift := 8;
1939 BlueRange := $000000FF; BlueShift := 16;
1940 AlphaRange := $000000FF; AlphaShift := 24;
1944 class function TfdRGBA8.GetFormatDesc: TglBitmapFormatDesc;
1946 with result do begin
1948 InternalFormat := GL_RGB8;
1949 DataType := GL_UNSIGNED_BYTE;
1953 class function TfdRGBA8.WithoutAlpha: TglBitmapFormat;
1958 class procedure TfdRGBA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1960 aData^ := aPixel.Red;
1962 aData^ := aPixel.Green;
1964 aData^ := aPixel.Blue;
1966 aData^ := aPixel.Alpha;
1970 class procedure TfdRGBA8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData);
1972 aPixel.Red := aData^;
1974 aPixel.Green := aData^;
1976 aPixel.Blue := aData^;
1978 aPixel.Alpha := aData^;
1984 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1985 //TfdBGR8/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1986 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1987 class function TfdBGR8.GetFormat: TglBitmapFormat;
1992 class function TfdBGR8.GetPixelDesc: TglBitmapPixelDesc;
1994 with result do begin
1995 RedRange := $000000FF; RedShift := 16;
1996 GreenRange := $000000FF; GreenShift := 8;
1997 BlueRange := $000000FF; BlueShift := 0;
1998 AlphaRange := $00000000; AlphaShift := 0;
2002 class function TfdBGR8.GetFormatDesc: TglBitmapFormatDesc;
2004 with result do begin
2006 InternalFormat := GL_RGB8;
2007 DataType := GL_UNSIGNED_BYTE;
2011 class function TfdBGR8.WithAlpha: TglBitmapFormat;
2016 class procedure TfdBGR8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
2018 aData^ := aPixel.Blue;
2020 aData^ := aPixel.Green;
2022 aData^ := aPixel.Red;
2026 class procedure TfdBGR8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData);
2028 aPixel.Blue := aData^;
2030 aPixel.Green := aData^;
2032 aPixel.Red := aData^;
2038 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2039 //TfdBGRA8////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2040 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2041 class function TfdBGRA8.GetFormat: TglBitmapFormat;
2046 class function TfdBGRA8.GetPixelDesc: TglBitmapPixelDesc;
2048 with result do begin
2049 RedRange := $000000FF; RedShift := 16;
2050 GreenRange := $000000FF; GreenShift := 8;
2051 BlueRange := $000000FF; BlueShift := 0;
2052 AlphaRange := $000000FF; AlphaShift := 24;
2056 class function TfdBGRA8.GetFormatDesc: TglBitmapFormatDesc;
2058 with result do begin
2060 InternalFormat := GL_RGBA8;
2061 DataType := GL_UNSIGNED_BYTE;
2065 class function TfdBGRA8.WithoutAlpha: TglBitmapFormat;
2070 class procedure TfdBGRA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
2072 aData^ := aPixel.Blue;
2074 aData^ := aPixel.Green;
2076 aData^ := aPixel.Red;
2078 aData^ := aPixel.Alpha;
2082 class procedure TfdBGRA8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData);
2084 aPixel.Blue := aData^;
2086 aPixel.Green := aData^;
2088 aPixel.Red := aData^;
2090 aPixel.Alpha := aData^;
2095 {$REGION TglBitmap }
2096 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2097 //TglBitmap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2098 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2099 function TglBitmap.GetHeight: Integer;
2101 if (ffY in fDimension.Fields) then
2102 result := fDimension.Y
2107 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2108 function TglBitmap.GetWidth: Integer;
2110 if (ffX in fDimension.Fields) then
2111 result := fDimension.X
2117 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2118 procedure TglBitmap.SetCustomData(const aValue: Pointer);
2120 if fCustomData = aValue then
2122 fCustomData := aValue;
2125 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2126 procedure TglBitmap.SetCustomName(const aValue: String);
2128 if fCustomName = aValue then
2130 fCustomName := aValue;
2133 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2134 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
2136 if fCustomNameW = aValue then
2138 fCustomNameW := aValue;
2141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2142 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
2144 if fDeleteTextureOnFree = aValue then
2146 fDeleteTextureOnFree := aValue;
2149 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2150 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
2152 if fFormat = aValue then
2157 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2158 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
2160 if fFreeDataAfterGenTexture = aValue then
2162 fFreeDataAfterGenTexture := aValue;
2165 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2166 procedure TglBitmap.SetID(const aValue: Cardinal);
2168 if fID = aValue then
2173 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2174 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
2176 if fMipMap = aValue then
2181 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2182 procedure TglBitmap.SetTarget(const aValue: Cardinal);
2184 if fTarget = aValue then
2189 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2190 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
2192 MaxAnisotropic: Integer;
2194 fAnisotropic := Value;
2195 if (ID > 0) then begin
2196 if GL_EXT_texture_filter_anisotropic then begin
2197 if fAnisotropic > 0 then begin
2199 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
2200 if aValue > MaxAnisotropic then
2201 fAnisotropic := MaxAnisotropic;
2202 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
2211 procedure TglBitmap.AfterConstruction;
2213 inherited AfterConstruction;
2217 fIsResident := False;
2219 fFormat := glBitmapGetDefaultFormat;
2220 fMipMap := glBitmapDefaultMipmap;
2221 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
2222 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
2224 glBitmapGetDefaultFilter (fFilterMin, fFilterMag);
2225 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
2228 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2229 procedure TglBitmap.BeforeDestruction;
2231 SetDataPointer(nil, ifEmpty);
2232 if (ID > 0) and fDeleteTextureOnFree then
2233 glDeleteTextures(1, @ID);
2234 inherited BeforeDestruction;
2237 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2238 procedure TglBitmap.CreateID;
2241 glDeleteTextures(1, @ID);
2242 glGenTextures(1, @ID);
2246 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2247 procedure TglBitmap.SetupParameters(var aBuildWithGlu: Boolean);
2249 // Set Up Parameters
2250 SetWrap(fWrapS, fWrapT, fWrapR);
2251 SetFilter(fFilterMin, fFilterMag);
2252 SetAnisotropic(fAnisotropic);
2253 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
2255 // Mip Maps Generation Mode
2256 aBuildWithGlu := False;
2257 if (MipMap = mmMipmap) then begin
2258 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
2259 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
2261 BuildWithGlu := True;
2262 end else if (MipMap = mmMipmapGlu) then
2263 BuildWithGlu := True;
2266 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2267 procedure TglBitmap.SelectFormat(const aFormat: TglBitmapFormat; var glFormat, glInternalFormat, glType: Cardinal);
2271 if not GL_VERSION_1_2 then
2272 raise EglBitmapUnsupportedFormatFormat.Create('SelectFormat - You need at least OpenGL 1.2 to support these format.');
2277 glType := GL_UNSIGNED_BYTE;
2278 glInternalFormat := Cardinal(aFormat);
2281 tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16:
2282 glFormat := GL_ALPHA;
2284 tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16:
2285 glFormat := GL_LUMINANCE;
2287 tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8,
2288 tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16:
2289 glFormat := GL_LUMINANCE_ALPHA;
2291 tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16:
2294 tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16:
2295 glFormat := GL_RGBA;
2297 tfDepth16, tfDepth24, tfDepth32:
2298 glFormat := GL_DEPTH_COMPONENT;
2305 glType := GL_UNSIGNED_SHORT_4_4_4_4;
2307 glType := GL_UNSIGNED_SHORT_5_5_5_1;
2315 glFormat := GL_ALPHA;
2317 glFormat := GL_LUMINANCE;
2319 glFormat := GL_DEPTH_COMPONENT;
2321 glFormat := GL_LUMINANCE_ALPHA;
2324 if (GL_VERSION_1_2 or GL_EXT_bgra) then begin
2327 if CanConvertImage then
2334 if (GL_VERSION_1_2 or GL_EXT_bgra) then begin
2335 glFormat := GL_BGRA;
2337 if CanConvertImage then
2339 glFormat := GL_RGBA;
2345 glFormat := GL_RGBA;
2349 glFormat := GL_BGRA;
2350 glType := GL_UNSIGNED_SHORT_4_4_4_4_REV;
2355 glFormat := GL_BGRA;
2356 glType := GL_UNSIGNED_SHORT_1_5_5_5_REV;
2361 glFormat := GL_BGRA;
2362 glType := GL_UNSIGNED_INT_2_10_10_10_REV;
2368 glType := GL_UNSIGNED_SHORT_5_6_5;
2374 // Selecting InternalFormat
2376 ifDXT1, ifDXT3, ifDXT5:
2378 if GL_EXT_texture_compression_s3tc then begin
2381 glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
2383 glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
2385 glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
2388 // Compression isn't supported so convert to RGBA
2389 if CanConvertImage then
2391 glFormat := GL_RGBA;
2392 glInternalFormat := GL_RGBA8;
2399 glInternalFormat := GL_ALPHA4;
2401 glInternalFormat := GL_ALPHA8;
2404 if (GL_ARB_texture_compression or GL_VERSION_1_3) then
2405 glInternalFormat := GL_COMPRESSED_ALPHA
2407 glInternalFormat := GL_ALPHA;
2410 glInternalFormat := GL_ALPHA;
2417 glInternalFormat := GL_LUMINANCE4;
2419 glInternalFormat := GL_LUMINANCE8;
2422 if (GL_ARB_texture_compression or GL_VERSION_1_3) then
2423 glInternalFormat := GL_COMPRESSED_LUMINANCE
2425 glInternalFormat := GL_LUMINANCE;
2428 glInternalFormat := GL_LUMINANCE;
2433 glInternalFormat := GL_DEPTH_COMPONENT;
2439 glInternalFormat := GL_LUMINANCE4_ALPHA4;
2441 glInternalFormat := GL_LUMINANCE8_ALPHA8;
2444 if (GL_ARB_texture_compression or GL_VERSION_1_3) then
2445 glInternalFormat := GL_COMPRESSED_LUMINANCE_ALPHA
2447 glInternalFormat := GL_LUMINANCE_ALPHA;
2450 glInternalFormat := GL_LUMINANCE_ALPHA;
2457 glInternalFormat := GL_RGB4;
2459 glInternalFormat := GL_RGB8;
2462 if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin
2463 glInternalFormat := GL_COMPRESSED_RGB
2465 if (GL_EXT_texture_compression_s3tc) then
2466 glInternalFormat := GL_COMPRESSED_RGB_S3TC_DXT1_EXT
2468 glInternalFormat := GL_RGB;
2472 glInternalFormat := GL_RGB;
2475 ifBGRA8, tfRGBA8, tfRGBA4, tfRGB5A1, tfRGB10A2, ifR5G6B5:
2479 glInternalFormat := GL_RGBA4;
2481 glInternalFormat := GL_RGBA8;
2484 if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin
2485 glInternalFormat := GL_COMPRESSED_RGBA
2487 if (GL_EXT_texture_compression_s3tc) then
2488 glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2490 glInternalFormat := GL_RGBA;
2494 glInternalFormat := GL_RGBA;
2516 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2517 constructor TglBitmap.Create;
2519 {$IFNDEF GLB_NO_NATIVE_GL}
2520 ReadOpenGLExtensions;
2523 if (ClassType = TglBitmap) then
2524 raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
2530 constructor TglBitmap.Create(FileName: String);
2533 LoadFromFile(FileName);
2537 constructor TglBitmap.Create(Stream: TStream);
2540 LoadFromStream(Stream);
2545 constructor TglBitmap.CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar);
2548 LoadFromResource(Instance, Resource, ResType);
2552 constructor TglBitmap.Create(Instance: Cardinal; Resource: String; ResType: PChar);
2555 LoadFromResource(Instance, Resource, ResType);
2560 constructor TglBitmap.Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar);
2563 LoadFromResourceID(Instance, ResourceID, ResType);
2568 constructor TglBitmap.Create(Size: TglBitmapPixelPosition;
2569 Format: TglBitmapFormat);
2576 ImageSize := FormatGetImageSize(Size, Format);
2577 GetMem(Image, ImageSize);
2579 FillChar(Image^, ImageSize, #$FF);
2581 SetDataPointer(Image, Format, Size.X, Size.Y);
2589 constructor TglBitmap.Create(Size: TglBitmapPixelPosition;
2590 Format: TglBitmapFormat; Func: TglBitmapFunction; CustomData: Pointer);
2593 LoadFromFunc(Size, Func, Format, CustomData);
2597 function TglBitmap.Clone: TglBitmap;
2603 Temp := ClassType.Create as TglBitmap;
2605 // copy texture data if assigned
2606 if Assigned(Data) then begin
2607 Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat);
2609 GetMem(TempPtr, Size);
2611 Move(Data^, TempPtr^, Size);
2612 Temp.SetDataPointer(TempPtr, InternalFormat, Width, Height);
2618 Temp.SetDataPointer(nil, InternalFormat, Width, Height);
2622 Temp.fTarget := Target;
2623 Temp.fFormat := Format;
2624 Temp.fMipMap := MipMap;
2625 Temp.fAnisotropic := Anisotropic;
2626 Temp.fBorderColor := fBorderColor;
2627 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
2628 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
2629 Temp.fFilterMin := fFilterMin;
2630 Temp.fFilterMag := fFilterMag;
2631 Temp.fWrapS := fWrapS;
2632 Temp.fWrapT := fWrapT;
2633 Temp.fWrapR := fWrapR;
2634 Temp.fFilename := fFilename;
2635 Temp.fCustomName := fCustomName;
2636 Temp.fCustomNameW := fCustomNameW;
2637 Temp.fCustomDataPointer := fCustomDataPointer;
2647 procedure TglBitmap.LoadFromFile(const aFileName: String);
2651 fFilename := FileName;
2653 FS := TFileStream.Create(FileName, fmOpenRead);
2664 procedure TglBitmap.LoadFromStream(const aStream: TStream);
2666 {$IFDEF GLB_SUPPORT_PNG_READ}
2667 if not LoadPNG(Stream) then
2669 {$IFDEF GLB_SUPPORT_JPEG_READ}
2670 if not LoadJPEG(Stream) then
2672 if not LoadDDS(Stream) then
2673 if not LoadTGA(Stream) then
2674 if not LoadBMP(Stream) then
2675 raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
2680 procedure TglBitmap.LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar);
2682 RS: TResourceStream;
2687 if Assigned(ResType) then
2688 TempResType := ResType
2691 TempPos := Pos('.', Resource);
2692 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
2693 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
2694 TempResType := PChar(ResTypeStr);
2697 RS := TResourceStream.Create(Instance, Resource, TempResType);
2706 procedure TglBitmap.LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar);
2708 RS: TResourceStream;
2710 RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
2721 procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition;
2722 const aFunc: TglBitmapFunction; const aFormat: TglBitmapFormat;
2723 const aArgs: PtrInt);
2728 ImageSize := FormatGetImageSize(Size, Format);
2729 GetMem(Image, ImageSize);
2731 FillChar(Image^, ImageSize, #$FF);
2733 SetDataPointer(Image, Format, Size.X, Size.Y);
2739 AddFunc(Self, Func, False, Format, CustomData)
2743 procedure TglBitmap.SaveToFile(const aFileName: String;
2744 const aFileType: TglBitmapFileType);
2748 FS := TFileStream.Create(FileName, fmCreate);
2751 SaveToStream(FS, FileType);
2758 procedure TglBitmap.SaveToStream(const aStream: TStream;
2759 const aFileType: TglBitmapFileType);
2762 {$IFDEF GLB_SUPPORT_PNG_WRITE}
2763 ftPNG: SavePng(Stream);
2765 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
2766 ftJPEG: SaveJPEG(Stream);
2768 ftDDS: SaveDDS(Stream);
2769 ftTGA: SaveTGA(Stream);
2770 ftBMP: SaveBMP(Stream);
2776 function TglBitmap.AssignToSurface(out Surface: PSDL_Surface): boolean;
2778 Row, RowSize: Integer;
2779 pSource, pData: PByte;
2781 Pix: TglBitmapPixelData;
2783 function GetRowPointer(Row: Integer): pByte;
2785 Result := Surface.pixels;
2786 Inc(Result, Row * RowSize);
2792 if not FormatIsUncompressed(InternalFormat) then
2793 raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
2795 if Assigned(Data) then begin
2796 case Trunc(FormatGetSize(InternalFormat)) of
2802 raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
2805 FormatPreparePixel(Pix, InternalFormat);
2807 with Pix.PixelDesc do
2808 Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth, RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift);
2811 RowSize := Trunc(FileWidth * FormatGetSize(InternalFormat));
2813 for Row := 0 to FileHeight -1 do begin
2814 pData := GetRowPointer(Row);
2816 if Assigned(pData) then begin
2817 Move(pSource^, pData^, RowSize);
2818 Inc(pSource, RowSize);
2827 function TglBitmap.AssignFromSurface(const Surface: PSDL_Surface): boolean;
2829 pSource, pData, pTempData: PByte;
2830 Row, RowSize, TempWidth, TempHeight: Integer;
2831 IntFormat: TglBitmapInternalFormat;
2833 function GetRowPointer(Row: Integer): pByte;
2835 Result := Surface^.pixels;
2836 Inc(Result, Row * RowSize);
2842 if (Assigned(Surface)) then begin
2843 with Surface^.format^ do begin
2844 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminance) then
2845 IntFormat := ifLuminance
2848 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminanceAlpha) then
2849 IntFormat := ifLuminanceAlpha
2852 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA4) then
2853 IntFormat := ifRGBA4
2856 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifR5G6B5) then
2857 IntFormat := ifR5G6B5
2860 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB5A1) then
2861 IntFormat := ifRGB5A1
2864 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGR8) then
2868 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB8) then
2872 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGRA8) then
2873 IntFormat := ifBGRA8
2876 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA8) then
2877 IntFormat := ifRGBA8
2880 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB10A2) then
2881 IntFormat := ifRGB10A2
2883 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
2886 TempWidth := Surface^.w;
2887 TempHeight := Surface^.h;
2889 RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
2891 GetMem(pData, TempHeight * RowSize);
2895 for Row := 0 to TempHeight -1 do begin
2896 pSource := GetRowPointer(Row);
2898 if (Assigned(pSource)) then begin
2899 Move(pSource^, pTempData^, RowSize);
2900 Inc(pTempData, RowSize);
2904 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
2915 function TglBitmap.AssignAlphaToSurface(out Surface: PSDL_Surface): boolean;
2917 Row, Col, AlphaInterleave: Integer;
2918 pSource, pDest: PByte;
2920 function GetRowPointer(Row: Integer): pByte;
2922 Result := Surface.pixels;
2923 Inc(Result, Row * Width);
2929 if Assigned(Data) then begin
2930 if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifBGRA8, ifRGBA8] then begin
2931 Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
2933 case InternalFormat of
2935 AlphaInterleave := 1;
2937 AlphaInterleave := 3;
2939 AlphaInterleave := 0;
2945 for Row := 0 to Height -1 do begin
2946 pDest := GetRowPointer(Row);
2948 if Assigned(pDest) then begin
2949 for Col := 0 to Width -1 do begin
2950 Inc(pSource, AlphaInterleave);
2964 function TglBitmap.AddAlphaFromSurface(Surface: PSDL_Surface; Func: TglBitmapFunction; CustomData: Pointer): boolean;
2966 glBitmap: TglBitmap2D;
2968 glBitmap := TglBitmap2D.Create;
2970 glBitmap.AssignFromSurface(Surface);
2972 Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
2981 function TglBitmap.AssignFromBitmap(const Bitmap: TBitmap): boolean;
2983 pSource, pData, pTempData: PByte;
2984 Row, RowSize, TempWidth, TempHeight: Integer;
2985 IntFormat: TglBitmapInternalFormat;
2989 if (Assigned(Bitmap)) then begin
2990 case Bitmap.PixelFormat of
2992 IntFormat := ifLuminance;
2994 IntFormat := ifRGB5A1;
2996 IntFormat := ifR5G6B5;
2998 IntFormat := ifBGR8;
3000 IntFormat := ifBGRA8;
3002 raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
3005 TempWidth := Bitmap.Width;
3006 TempHeight := Bitmap.Height;
3008 RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
3010 GetMem(pData, TempHeight * RowSize);
3014 for Row := 0 to TempHeight -1 do begin
3015 pSource := Bitmap.Scanline[Row];
3017 if (Assigned(pSource)) then begin
3018 Move(pSource^, pTempData^, RowSize);
3019 Inc(pTempData, RowSize);
3023 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
3034 function TglBitmap.AssignToBitmap(const Bitmap: TBitmap): boolean;
3037 pSource, pData: PByte;
3041 if Assigned(Data) then begin
3042 if Assigned(Bitmap) then begin
3043 Bitmap.Width := Width;
3044 Bitmap.Height := Height;
3046 case InternalFormat of
3047 ifAlpha, ifLuminance, ifDepth8:
3049 Bitmap.PixelFormat := pf8bit;
3050 Bitmap.Palette := CreateGrayPalette;
3053 Bitmap.PixelFormat := pf15bit;
3055 Bitmap.PixelFormat := pf16bit;
3057 Bitmap.PixelFormat := pf24bit;
3059 Bitmap.PixelFormat := pf32bit;
3061 raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
3065 for Row := 0 to FileHeight -1 do begin
3066 pData := Bitmap.Scanline[Row];
3068 Move(pSource^, pData^, fRowSize);
3069 Inc(pSource, fRowSize);
3071 // swap RGB(A) to BGR(A)
3072 if InternalFormat in [ifRGB8, ifRGBA8] then
3073 SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8);
3082 function TglBitmap.AssignAlphaToBitmap(const Bitmap: TBitmap): boolean;
3084 Row, Col, AlphaInterleave: Integer;
3085 pSource, pDest: PByte;
3089 if Assigned(Data) then begin
3090 if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin
3091 if Assigned(Bitmap) then begin
3092 Bitmap.PixelFormat := pf8bit;
3093 Bitmap.Palette := CreateGrayPalette;
3094 Bitmap.Width := Width;
3095 Bitmap.Height := Height;
3097 case InternalFormat of
3099 AlphaInterleave := 1;
3101 AlphaInterleave := 3;
3103 AlphaInterleave := 0;
3109 for Row := 0 to Height -1 do begin
3110 pDest := Bitmap.Scanline[Row];
3112 if Assigned(pDest) then begin
3113 for Col := 0 to Width -1 do begin
3114 Inc(pSource, AlphaInterleave);
3129 function TglBitmap.AddAlphaFromBitmap(Bitmap: TBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean;
3131 glBitmap: TglBitmap2D;
3133 glBitmap := TglBitmap2D.Create;
3135 glBitmap.AssignFromBitmap(Bitmap);
3137 Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
3145 function TglBitmap.AddAlphaFromFile(FileName: String; Func: TglBitmapFunction; CustomData: Pointer): boolean;
3149 FS := TFileStream.Create(FileName, fmOpenRead);
3151 Result := AddAlphaFromStream(FS, Func, CustomData);
3158 function TglBitmap.AddAlphaFromStream(Stream: TStream; Func: TglBitmapFunction; CustomData: Pointer): boolean;
3160 glBitmap: TglBitmap2D;
3162 glBitmap := TglBitmap2D.Create(Stream);
3164 Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
3172 function TglBitmap.AddAlphaFromResource(Instance: Cardinal; Resource: String;
3173 ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean;
3175 RS: TResourceStream;
3180 if Assigned(ResType) then
3181 TempResType := ResType
3184 TempPos := Pos('.', Resource);
3185 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
3186 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
3187 TempResType := PChar(ResTypeStr);
3190 RS := TResourceStream.Create(Instance, Resource, TempResType);
3192 Result := AddAlphaFromStream(RS, Func, CustomData);
3199 function TglBitmap.AddAlphaFromResourceID(Instance: Cardinal; ResourceID: Integer;
3200 ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean;
3202 RS: TResourceStream;
3204 RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
3206 Result := AddAlphaFromStream(RS, Func, CustomData);
3214 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3216 with FuncRec do begin
3217 Dest.Red := Source.Red;
3218 Dest.Green := Source.Green;
3219 Dest.Blue := Source.Blue;
3221 with TglBitmapPixelData(CustomData^) do
3222 if ((Dest.Red <= Red ) and (Dest.Red >= PixelDesc.RedRange ) and
3223 (Dest.Green <= Green) and (Dest.Green >= PixelDesc.GreenRange) and
3224 (Dest.Blue <= Blue ) and (Dest.Blue >= PixelDesc.BlueRange )) then
3227 Dest.Alpha := Dest.PixelDesc.AlphaRange;
3232 function TglBitmap.AddAlphaFromColorKey(Red, Green, Blue: Byte; Deviation: Byte
3235 Result := AddAlphaFromColorKeyFloat(Red / $FF, Green / $FF, Blue / $FF, Deviation / $FF);
3239 function TglBitmap.AddAlphaFromColorKeyRange(Red, Green, Blue: Cardinal; Deviation: Cardinal = 0): Boolean;
3241 PixelData: TglBitmapPixelData;
3243 FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
3245 Result := AddAlphaFromColorKeyFloat(
3246 Red / PixelData.PixelDesc.RedRange,
3247 Green / PixelData.PixelDesc.GreenRange,
3248 Blue / PixelData.PixelDesc.BlueRange,
3249 Deviation / Max(PixelData.PixelDesc.RedRange, Max(PixelData.PixelDesc.GreenRange, PixelData.PixelDesc.BlueRange)));
3253 function TglBitmap.AddAlphaFromColorKeyFloat(Red, Green, Blue: Single; Deviation: Single = 0): Boolean;
3255 TempR, TempG, TempB: Cardinal;
3256 PixelData: TglBitmapPixelData;
3258 FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
3260 // Calculate Colorrange
3261 with PixelData.PixelDesc do begin
3262 TempR := Trunc(RedRange * Deviation);
3263 TempG := Trunc(GreenRange * Deviation);
3264 TempB := Trunc(BlueRange * Deviation);
3266 PixelData.Red := Min(RedRange, Trunc(RedRange * Red) + TempR);
3267 RedRange := Max(0, Trunc(RedRange * Red) - TempR);
3268 PixelData.Green := Min(GreenRange, Trunc(GreenRange * Green) + TempG);
3269 GreenRange := Max(0, Trunc(GreenRange * Green) - TempG);
3270 PixelData.Blue := Min(BlueRange, Trunc(BlueRange * Blue) + TempB);
3271 BlueRange := Max(0, Trunc(BlueRange * Blue) - TempB);
3272 PixelData.Alpha := 0;
3276 Result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
3280 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3282 with FuncRec do begin
3283 Dest.Red := Source.Red;
3284 Dest.Green := Source.Green;
3285 Dest.Blue := Source.Blue;
3287 with TglBitmapPixelData(CustomData^) do
3288 Dest.Alpha := Alpha;
3293 function TglBitmap.AddAlphaFromValue(Alpha: Byte): Boolean;
3295 Result := AddAlphaFromValueFloat(Alpha / $FF);
3299 function TglBitmap.AddAlphaFromValueFloat(Alpha: Single): Boolean;
3301 PixelData: TglBitmapPixelData;
3303 FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
3305 with PixelData.PixelDesc do
3306 PixelData.Alpha := Min(AlphaRange, Max(0, Round(AlphaRange * Alpha)));
3308 Result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData);
3312 function TglBitmap.AddAlphaFromValueRange(Alpha: Cardinal): Boolean;
3314 PixelData: TglBitmapPixelData;
3316 FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
3318 Result := AddAlphaFromValueFloat(Alpha / PixelData.PixelDesc.AlphaRange);
3322 procedure glBitmapInvertFunc(var FuncRec: TglBitmapFunctionRec);
3324 with FuncRec do begin
3325 Dest.Red := Source.Red;
3326 Dest.Green := Source.Green;
3327 Dest.Blue := Source.Blue;
3328 Dest.Alpha := Source.Alpha;
3330 if (Integer(CustomData) and $1 > 0) then begin
3331 Dest.Red := Dest.Red xor Dest.PixelDesc.RedRange;
3332 Dest.Green := Dest.Green xor Dest.PixelDesc.GreenRange;
3333 Dest.Blue := Dest.Blue xor Dest.PixelDesc.BlueRange;
3336 if (Integer(CustomData) and $2 > 0) then begin
3337 Dest.Alpha := Dest.Alpha xor Dest.PixelDesc.AlphaRange;
3343 procedure TglBitmap.Invert(UseRGB: Boolean; UseAlpha: Boolean);
3345 if ((UseRGB) or (UseAlpha)) then
3346 AddFunc(glBitmapInvertFunc, False, Pointer(Integer(UseAlpha) shl 1 or Integer(UseRGB)));
3350 procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal);
3354 fFilterMin := GL_NEAREST;
3356 fFilterMin := GL_LINEAR;
3357 GL_NEAREST_MIPMAP_NEAREST:
3358 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
3359 GL_LINEAR_MIPMAP_NEAREST:
3360 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
3361 GL_NEAREST_MIPMAP_LINEAR:
3362 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
3363 GL_LINEAR_MIPMAP_LINEAR:
3364 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
3366 raise EglBitmapException.Create('SetFilter - Unknow Minfilter.');
3371 fFilterMag := GL_NEAREST;
3373 fFilterMag := GL_LINEAR;
3375 raise EglBitmapException.Create('SetFilter - Unknow Magfilter.');
3378 // If texture is created then assign filter
3379 if ID > 0 then begin
3382 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
3384 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE_ARB) then begin
3386 GL_NEAREST, GL_LINEAR:
3387 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
3388 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
3389 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3390 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
3391 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3394 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
3399 procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal;
3406 fWrapS := GL_REPEAT;
3409 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
3410 fWrapS := GL_CLAMP_TO_EDGE
3416 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
3417 fWrapS := GL_CLAMP_TO_BORDER
3423 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
3424 fWrapS := GL_MIRRORED_REPEAT
3426 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
3429 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).');
3436 fWrapT := GL_REPEAT;
3439 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
3440 fWrapT := GL_CLAMP_TO_EDGE
3446 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
3447 fWrapT := GL_CLAMP_TO_BORDER
3453 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
3454 fWrapT := GL_MIRRORED_REPEAT
3456 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (T).');
3459 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (T).');
3466 fWrapR := GL_REPEAT;
3469 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
3470 fWrapR := GL_CLAMP_TO_EDGE
3476 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
3477 fWrapR := GL_CLAMP_TO_BORDER
3483 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
3484 fWrapR := GL_MIRRORED_REPEAT
3486 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (R).');
3489 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (R).');
3492 if ID > 0 then begin
3494 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
3495 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
3496 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
3501 procedure TglBitmap.SetDataPointer(NewData: pByte;
3502 Format: TglBitmapFormat; Width: Integer; Height: Integer);
3505 if Data <> NewData then begin
3512 if Data = nil then begin
3513 fInternalFormat := ifEmpty;
3517 if Width <> -1 then begin
3518 fDimension.Fields := fDimension.Fields + [ffX];
3519 fDimension.X := Width;
3522 if Height <> -1 then begin
3523 fDimension.Fields := fDimension.Fields + [ffY];
3524 fDimension.Y := Height;
3527 fInternalFormat := Format;
3528 fPixelSize := Trunc(FormatGetSize(InternalFormat));
3529 fRowSize := Trunc(FormatGetSize(InternalFormat) * Self.Width);
3533 {$IFDEF GLB_SUPPORT_PNG_READ}
3534 {$IFDEF GLB_LIB_PNG}
3535 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
3537 TStream(png_get_io_ptr(png)).Read(buffer^, size);
3542 function TglBitmap.LoadPNG(Stream: TStream): Boolean;
3543 {$IFDEF GLB_SDL_IMAGE}
3545 Surface: PSDL_Surface;
3550 RWops := glBitmapCreateRWops(Stream);
3552 if IMG_isPNG(RWops) > 0 then begin
3553 Surface := IMG_LoadPNG_RW(RWops);
3555 AssignFromSurface(Surface);
3558 SDL_FreeSurface(Surface);
3566 {$IFDEF GLB_LIB_PNG}
3569 signature: array [0..7] of byte;
3571 png_info: png_infop;
3573 TempHeight, TempWidth: Integer;
3574 Format: TglBitmapInternalFormat;
3577 png_rows: array of pByte;
3578 Row, LineSize: Integer;
3582 if not init_libPNG then
3583 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
3587 StreamPos := Stream.Position;
3588 Stream.Read(signature, 8);
3589 Stream.Position := StreamPos;
3591 if png_check_sig(@signature, 8) <> 0 then begin
3593 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
3595 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
3598 png_info := png_create_info_struct(png);
3599 if png_info = nil then begin
3600 png_destroy_read_struct(@png, nil, nil);
3601 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
3604 // set read callback
3605 png_set_read_fn(png, stream, glBitmap_libPNG_read_func);
3607 // read informations
3608 png_read_info(png, png_info);
3611 TempHeight := png_get_image_height(png, png_info);
3612 TempWidth := png_get_image_width(png, png_info);
3615 case png_get_color_type(png, png_info) of
3616 PNG_COLOR_TYPE_GRAY:
3617 Format := ifLuminance;
3618 PNG_COLOR_TYPE_GRAY_ALPHA:
3619 Format := ifLuminanceAlpha;
3622 PNG_COLOR_TYPE_RGB_ALPHA:
3625 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
3628 // cut upper 8 bit from 16 bit formats
3629 if png_get_bit_depth(png, png_info) > 8 then
3630 png_set_strip_16(png);
3632 // expand bitdepth smaller than 8
3633 if png_get_bit_depth(png, png_info) < 8 then
3634 png_set_expand(png);
3636 // allocating mem for scanlines
3637 LineSize := png_get_rowbytes(png, png_info);
3638 GetMem(png_data, TempHeight * LineSize);
3640 SetLength(png_rows, TempHeight);
3641 for Row := Low(png_rows) to High(png_rows) do begin
3642 png_rows[Row] := png_data;
3643 Inc(png_rows[Row], Row * LineSize);
3646 // read complete image into scanlines
3647 png_read_image(png, @png_rows[0]);
3650 png_read_end(png, png_info);
3652 // destroy read struct
3653 png_destroy_read_struct(@png, @png_info, nil);
3655 SetLength(png_rows, 0);
3658 SetDataPointer(png_data, Format, TempWidth, TempHeight);
3671 {$IFDEF GLB_PNGIMAGE}
3675 Header: Array[0..7] of Byte;
3676 Row, Col, PixSize, LineSize: Integer;
3677 NewImage, pSource, pDest, pAlpha: pByte;
3678 Format: TglBitmapInternalFormat;
3681 PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10);
3686 StreamPos := Stream.Position;
3687 Stream.Read(Header[0], SizeOf(Header));
3688 Stream.Position := StreamPos;
3690 {Test if the header matches}
3691 if Header = PngHeader then begin
3692 Png := TPNGObject.Create;
3694 Png.LoadFromStream(Stream);
3696 case Png.Header.ColorType of
3698 Format := ifLuminance;
3699 COLOR_GRAYSCALEALPHA:
3700 Format := ifLuminanceAlpha;
3706 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
3709 PixSize := Trunc(FormatGetSize(Format));
3710 LineSize := Integer(Png.Header.Width) * PixSize;
3712 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
3716 case Png.Header.ColorType of
3717 COLOR_RGB, COLOR_GRAYSCALE:
3719 for Row := 0 to Png.Height -1 do begin
3720 Move (Png.Scanline[Row]^, pDest^, LineSize);
3721 Inc(pDest, LineSize);
3724 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
3726 PixSize := PixSize -1;
3728 for Row := 0 to Png.Height -1 do begin
3729 pSource := Png.Scanline[Row];
3730 pAlpha := pByte(Png.AlphaScanline[Row]);
3732 for Col := 0 to Png.Width -1 do begin
3733 Move (pSource^, pDest^, PixSize);
3734 Inc(pSource, PixSize);
3735 Inc(pDest, PixSize);
3744 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
3747 SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height);
3763 {$IFDEF GLB_LIB_JPEG}
3765 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
3766 glBitmap_libJPEG_source_mgr = record
3767 pub: jpeg_source_mgr;
3770 SrcBuffer: array [1..4096] of byte;
3774 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
3775 glBitmap_libJPEG_dest_mgr = record
3776 pub: jpeg_destination_mgr;
3778 DestStream: TStream;
3779 DestBuffer: array [1..4096] of byte;
3784 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
3788 // SetLength(Msg, 256);
3789 // cinfo^.err^.format_message(cinfo, pChar(Msg));
3791 // Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
3793 // cinfo^.global_state := 0;
3795 // jpeg_abort(cinfo);
3799 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
3803 // SetLength(Msg, 256);
3804 // cinfo^.err^.format_message(cinfo, pChar(Msg));
3806 // Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
3808 // cinfo^.global_state := 0;
3812 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
3817 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
3819 src: glBitmap_libJPEG_source_mgr_ptr;
3822 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
3824 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
3825 if (bytes <= 0) then begin
3826 src^.SrcBuffer[1] := $FF;
3827 src^.SrcBuffer[2] := JPEG_EOI;
3831 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
3832 src^.pub.bytes_in_buffer := bytes;
3838 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
3840 src: glBitmap_libJPEG_source_mgr_ptr;
3842 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
3844 if num_bytes > 0 then begin
3845 // wanted byte isn't in buffer so set stream position and read buffer
3846 if num_bytes > src^.pub.bytes_in_buffer then begin
3847 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
3848 src^.pub.fill_input_buffer(cinfo);
3850 // wanted byte is in buffer so only skip
3851 inc(src^.pub.next_input_byte, num_bytes);
3852 dec(src^.pub.bytes_in_buffer, num_bytes);
3858 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
3863 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
3868 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
3870 dest: glBitmap_libJPEG_dest_mgr_ptr;
3872 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
3874 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
3875 // write complete buffer
3876 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
3879 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
3880 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
3887 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
3890 dest: glBitmap_libJPEG_dest_mgr_ptr;
3892 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
3894 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
3895 // check for endblock
3896 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
3898 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
3903 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
3909 {$IFDEF GLB_SUPPORT_JPEG_READ}
3910 function TglBitmap.LoadJPEG(Stream: TStream): Boolean;
3911 {$IFDEF GLB_SDL_IMAGE}
3913 Surface: PSDL_Surface;
3918 RWops := glBitmapCreateRWops(Stream);
3920 if IMG_isJPG(RWops) > 0 then begin
3921 Surface := IMG_LoadJPG_RW(RWops);
3923 AssignFromSurface(Surface);
3926 SDL_FreeSurface(Surface);
3934 {$IFDEF GLB_LIB_JPEG}
3937 Temp: array[0..1]of Byte;
3939 jpeg: jpeg_decompress_struct;
3940 jpeg_err: jpeg_error_mgr;
3942 IntFormat: TglBitmapInternalFormat;
3944 TempHeight, TempWidth: Integer;
3951 if not init_libJPEG then
3952 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
3955 // reading first two bytes to test file and set cursor back to begin
3956 StreamPos := Stream.Position;
3957 Stream.Read(Temp[0], 2);
3958 Stream.Position := StreamPos;
3960 // if Bitmap then read file.
3961 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
3962 FillChar(jpeg, SizeOf(jpeg_decompress_struct), $00);
3963 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
3966 jpeg.err := jpeg_std_error(@jpeg_err);
3967 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
3968 jpeg_err.output_message := glBitmap_libJPEG_output_message;
3970 // decompression struct
3971 jpeg_create_decompress(@jpeg);
3973 // allocation space for streaming methods
3974 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
3976 // seeting up custom functions
3977 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
3978 pub.init_source := glBitmap_libJPEG_init_source;
3979 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
3980 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
3981 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
3982 pub.term_source := glBitmap_libJPEG_term_source;
3984 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
3985 pub.next_input_byte := nil; // until buffer loaded
3987 SrcStream := Stream;
3990 // set global decoding state
3991 jpeg.global_state := DSTATE_START;
3993 // read header of jpeg
3994 jpeg_read_header(@jpeg, False);
3996 // setting output parameter
3997 case jpeg.jpeg_color_space of
4000 jpeg.out_color_space := JCS_GRAYSCALE;
4001 IntFormat := ifLuminance;
4004 jpeg.out_color_space := JCS_RGB;
4005 IntFormat := ifRGB8;
4009 jpeg_start_decompress(@jpeg);
4011 TempHeight := jpeg.output_height;
4012 TempWidth := jpeg.output_width;
4014 // creating new image
4015 GetMem(pImage, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
4019 for Row := 0 to TempHeight -1 do begin
4020 jpeg_read_scanlines(@jpeg, @pTemp, 1);
4021 Inc(pTemp, Trunc(FormatGetSize(IntFormat) * TempWidth));
4024 // finish decompression
4025 jpeg_finish_decompress(@jpeg);
4027 // destroy decompression
4028 jpeg_destroy_decompress(@jpeg);
4030 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight);
4043 {$IFDEF GLB_DELPHI_JPEG}
4048 Temp: array[0..1]of Byte;
4052 // reading first two bytes to test file and set cursor back to begin
4053 StreamPos := Stream.Position;
4054 Stream.Read(Temp[0], 2);
4055 Stream.Position := StreamPos;
4057 // if Bitmap then read file.
4058 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
4059 bmp := TBitmap.Create;
4061 jpg := TJPEGImage.Create;
4063 jpg.LoadFromStream(Stream);
4065 Result := AssignFromBitmap(bmp);
4084 BMP_COMP_BITFIELDS = 3;
4087 TBMPHeader = packed record
4092 bfOffBits: Cardinal;
4095 TBMPInfo = packed record
4101 biCompression: Cardinal;
4102 biSizeImage: Cardinal;
4103 biXPelsPerMeter: Longint;
4104 biYPelsPerMeter: Longint;
4105 biClrUsed: Cardinal;
4106 biClrImportant: Cardinal;
4109 TBMPInfoOS = packed record
4117 // TBMPPalette = record
4119 // True : (Colors: array[Byte] of TRGBQUAD);
4120 // False: (redMask, greenMask, blueMask: Cardinal);
4123 function TglBitmap.LoadBMP(Stream: TStream): Boolean;
4128 NewImage, pData: pByte;
4130 Format: TglBitmapFormat;
4131 LineSize, Padding, LineIdx: Integer;
4132 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
4134 PaddingBuff: Cardinal;
4137 function GetLineWidth : Integer;
4139 Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
4152 StreamPos := Stream.Position;
4153 Stream.Read(Header, SizeOf(Header));
4155 if Header.bfType = BMP_MAGIC then begin
4156 Stream.Read(Info, SizeOf(Info));
4158 // Check for Compression
4159 if Info.biCompression <> BMP_COMP_RGB then begin
4160 if Info.biCompression = BMP_COMP_BITFIELDS then begin
4161 // Read Bitmasks for 16 or 32 Bit (24 Bit dosn't support Bitmasks!)
4162 if (Info.biBitCount = 16) or (Info.biBitCount = 32) then begin
4163 Stream.Read(RedMask, SizeOf(Cardinal));
4164 Stream.Read(GreenMask, SizeOf(Cardinal));
4165 Stream.Read(BlueMask, SizeOf(Cardinal));
4166 Stream.Read(AlphaMask, SizeOf(Cardinal));
4169 // RLE compression is unsupported
4170 Stream.Position := StreamPos;
4177 if Info.biBitCount < 16 then
4178 Stream.Position := Stream.Position + Info.biClrUsed * 4;
4181 Stream.Position := StreamPos + Header.bfOffBits;
4184 case Info.biBitCount of
4185 8 : Format := ifLuminance;
4188 if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin
4191 if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifLuminanceAlpha) then
4192 Format := ifLuminanceAlpha;
4194 if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, tfRGBA4) then
4197 if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, tfRGB5A1) then
4200 if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifR5G6B5) then
4204 24: Format := ifBGR8;
4207 if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin
4210 if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, tfRGBA8) then
4213 if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifBGRA8) then
4216 if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, tfRGB10A2) then
4217 Format := tfRGB10A2;
4222 if Format <> ifEmpty then begin
4223 LineSize := Trunc(Info.biWidth * FormatGetSize(Format));
4224 Padding := GetLineWidth - LineSize;
4227 GetMem(NewImage, Info.biHeight * LineSize);
4229 FillChar(NewImage^, Info.biHeight * LineSize, $FF);
4231 // Set pData to last Line
4233 Inc(pData, LineSize * (Info.biHeight -1));
4236 for LineIdx := 0 to Info.biHeight - 1 do begin
4237 Stream.Read(pData^, LineSize);
4238 Dec(pData, LineSize);
4240 Stream.Read(PaddingBuff, Padding);
4244 SetDataPointer(NewImage, Format, Info.biWidth, Info.biHeight);
4253 else Stream.Position := StreamPos;
4258 DDS_MAGIC = $20534444;
4260 // DDS_header.dwFlags
4261 DDSD_CAPS = $00000001;
4262 DDSD_HEIGHT = $00000002;
4263 DDSD_WIDTH = $00000004;
4264 DDSD_PITCH = $00000008;
4265 DDSD_PIXELFORMAT = $00001000;
4266 DDSD_MIPMAPCOUNT = $00020000;
4267 DDSD_LINEARSIZE = $00080000;
4268 DDSD_DEPTH = $00800000;
4270 // DDS_header.sPixelFormat.dwFlags
4271 DDPF_ALPHAPIXELS = $00000001;
4272 DDPF_FOURCC = $00000004;
4273 DDPF_INDEXED = $00000020;
4274 DDPF_RGB = $00000040;
4276 // DDS_header.sCaps.dwCaps1
4277 DDSCAPS_COMPLEX = $00000008;
4278 DDSCAPS_TEXTURE = $00001000;
4279 DDSCAPS_MIPMAP = $00400000;
4281 // DDS_header.sCaps.dwCaps2
4282 DDSCAPS2_CUBEMAP = $00000200;
4283 DDSCAPS2_CUBEMAP_POSITIVEX = $00000400;
4284 DDSCAPS2_CUBEMAP_NEGATIVEX = $00000800;
4285 DDSCAPS2_CUBEMAP_POSITIVEY = $00001000;
4286 DDSCAPS2_CUBEMAP_NEGATIVEY = $00002000;
4287 DDSCAPS2_CUBEMAP_POSITIVEZ = $00004000;
4288 DDSCAPS2_CUBEMAP_NEGATIVEZ = $00008000;
4289 DDSCAPS2_VOLUME = $00200000;
4291 D3DFMT_DXT1 = $31545844;
4292 D3DFMT_DXT3 = $33545844;
4293 D3DFMT_DXT5 = $35545844;
4296 TDDSPixelFormat = packed record
4300 dwRGBBitCount: Cardinal;
4301 dwRBitMask: Cardinal;
4302 dwGBitMask: Cardinal;
4303 dwBBitMask: Cardinal;
4304 dwAlphaBitMask: Cardinal;
4307 TDDSCaps = packed record
4311 dwReserved: Cardinal;
4314 TDDSHeader = packed record
4320 dwPitchOrLinearSize: Cardinal;
4322 dwMipMapCount: Cardinal;
4323 dwReserved: array[0..10] of Cardinal;
4324 PixelFormat: TDDSPixelFormat;
4326 dwReserved2: Cardinal;
4331 function TglBitmap.LoadDDS(Stream: TStream): Boolean;
4335 Y, LineSize: Cardinal;
4337 // MipMapCount, X, Y, XSize, YSize: Cardinal;
4339 NewImage, pData: pByte;
4340 Format: TglBitmapFormat;
4343 function RaiseEx : Exception;
4345 Result := EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
4349 function GetInternalFormat: TglBitmapFormat;
4351 with Header.PixelFormat do begin
4353 if (dwFlags and DDPF_FOURCC) > 0 then begin
4354 case Header.PixelFormat.dwFourCC of
4355 D3DFMT_DXT1: Result := ifDXT1;
4356 D3DFMT_DXT3: Result := ifDXT3;
4357 D3DFMT_DXT5: Result := ifDXT5;
4364 if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
4365 case dwRGBBitCount of
4368 if dwFlags and DDPF_ALPHAPIXELS > 0 then
4371 Result := ifLuminance;
4375 if dwFlags and DDPF_ALPHAPIXELS > 0 then begin
4377 case GetBitSize(dwRBitMask) of
4378 5: Result := tfRGB5A1;
4379 4: Result := tfRGBA4;
4381 Result := ifLuminanceAlpha;
4390 if dwRBitMask > dwBBitMask then
4397 if GetBitSize(dwRBitMask) = 10 then
4401 if dwRBitMask > dwBBitMask then
4418 StreamPos := Stream.Position;
4419 Stream.Read(Header, sizeof(Header));
4421 if ((Header.dwMagic <> DDS_MAGIC) or (Header.dwSize <> 124) or
4422 ((Header.dwFlags and DDSD_PIXELFORMAT) = 0) or ((Header.dwFlags and DDSD_CAPS) = 0)) then begin
4423 Stream.Position := StreamPos;
4428 // if Header.dwFlags and DDSD_MIPMAPCOUNT <> 0
4429 // then MipMapCount := Header.dwMipMapCount
4430 // else MipMapCount := 1;
4432 Format := GetInternalFormat;
4433 LineSize := Trunc(Header.dwWidth * FormatGetSize(Format));
4435 GetMem(NewImage, Header.dwHeight * LineSize);
4440 if (Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0 then begin
4441 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
4443 for Y := 0 to Header.dwHeight -1 do begin
4444 Stream.Read(pData^, RowSize);
4445 Inc(pData, LineSize);
4450 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
4451 RowSize := Header.dwPitchOrLinearSize;
4453 for Y := 0 to Header.dwHeight -1 do begin
4454 Stream.Read(pData^, RowSize);
4455 Inc(pData, LineSize);
4460 SetDataPointer(NewImage, Format, Header.dwWidth, Header.dwHeight);
4471 TTGAHeader = packed record
4475 ColorMapSpec: Array[0..4] of Byte;
4485 TGA_UNCOMPRESSED_RGB = 2;
4486 TGA_UNCOMPRESSED_GRAY = 3;
4487 TGA_COMPRESSED_RGB = 10;
4488 TGA_COMPRESSED_GRAY = 11;
4492 function TglBitmap.LoadTGA(Stream: TStream): Boolean;
4495 NewImage, pData: PByte;
4497 PixelSize, LineSize, YStart, YEnd, YInc: Integer;
4498 Format: TglBitmapFormat;
4503 procedure ReadUncompressed;
4507 RowSize := Header.Width * PixelSize;
4509 // copy line by line
4510 while YStart <> YEnd + YInc do begin
4512 Inc(pData, YStart * LineSize);
4514 Stream.Read(pData^, RowSize);
4520 procedure ReadCompressed;
4522 HeaderWidth, HeaderHeight: Integer;
4523 LinePixelsRead, ImgPixelsRead, ImgPixelsToRead: Integer;
4526 CacheSize, CachePos: Integer;
4529 TempBuf: Array [0..15] of Byte;
4531 PixelRepeat: Boolean;
4532 PixelToRead, TempPixels: Integer;
4535 procedure CheckLine;
4537 if LinePixelsRead >= HeaderWidth then begin
4538 LinePixelsRead := 0;
4541 Inc(pData, YStart * LineSize);
4546 procedure CachedRead(var Buffer; Count: Integer);
4550 if (CachePos + Count) > CacheSize then begin
4554 if CacheSize - CachePos > 0 then begin
4555 BytesRead := CacheSize - CachePos;
4557 Move(pByteArray(Cache)^[CachePos], Buffer, BytesRead);
4558 Inc(CachePos, BytesRead);
4562 CacheSize := Min(CACHE_SIZE, Stream.Size - Stream.Position);
4563 Stream.Read(Cache^, CacheSize);
4567 if Count - BytesRead > 0 then begin
4568 Move(pByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
4569 Inc(CachePos, Count - BytesRead);
4572 Move(pByteArray(Cache)^[CachePos], Buffer, Count);
4573 Inc(CachePos, Count);
4582 HeaderWidth := Header.Width;
4583 HeaderHeight := Header.Height;
4585 GetMem(Cache, CACHE_SIZE); // 16K Buffer
4587 ImgPixelsToRead := HeaderWidth * HeaderHeight;
4589 LinePixelsRead := 0;
4592 Inc(pData, YStart * LineSize);
4594 // Read until all Pixels
4596 CachedRead(Temp, 1);
4598 PixelRepeat := Temp and $80 > 0;
4599 PixelToRead := (Temp and $7F) + 1;
4601 Inc(ImgPixelsRead, PixelToRead);
4603 if PixelRepeat then begin
4604 // repeat one pixel x times
4605 CachedRead(TempBuf[0], PixelSize);
4608 while PixelToRead > 0 do begin
4611 TempPixels := HeaderWidth - LinePixelsRead;
4612 if PixelToRead < TempPixels then
4613 TempPixels := PixelToRead;
4615 Inc(LinePixelsRead, TempPixels);
4616 Dec(PixelToRead, TempPixels);
4618 while TempPixels > 0 do begin
4622 pData^ := TempBuf[0];
4627 pWord(pData)^ := pWord(@TempBuf[0])^;
4632 pWord(pData)^ := pWord(@TempBuf[0])^;
4634 pData^ := TempBuf[2];
4639 pDWord(pData)^ := pDWord(@TempBuf[0])^;
4649 while PixelToRead > 0 do begin
4652 TempPixels := HeaderWidth - LinePixelsRead;
4653 if PixelToRead < TempPixels then
4654 TempPixels := PixelToRead;
4656 CachedRead(pData^, PixelSize * TempPixels);
4657 Inc(pData, PixelSize * TempPixels);
4659 Inc(LinePixelsRead, TempPixels);
4661 Dec(PixelToRead, TempPixels);
4664 until ImgPixelsRead >= ImgPixelsToRead;
4673 // reading header to test file and set cursor back to begin
4674 StreamPos := Stream.Position;
4675 Stream.Read(Header, SizeOf(Header));
4677 // no colormapped files
4678 if (Header.ColorMapType = 0) then begin
4679 if Header.ImageType in [TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY] then begin
4681 8: Format := ifAlpha;
4682 16: Format := ifLuminanceAlpha;
4683 24: Format := ifBGR8;
4684 32: Format := ifBGRA8;
4686 raise EglBitmapException.Create('LoadTga - unsupported BitsPerPixel found.');
4690 if Header.ImageID <> 0 then
4691 Stream.Position := Stream.Position + Header.ImageID;
4693 PixelSize := Trunc(FormatGetSize(Format));
4694 LineSize := Trunc(Header.Width * PixelSize);
4696 GetMem(NewImage, LineSize * Header.Height);
4699 if (Header.ImageDes and $20 > 0) then begin
4701 YEnd := Header.Height -1;
4704 YStart := Header.Height -1;
4710 case Header.ImageType of
4711 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
4713 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
4717 SetDataPointer(NewImage, Format, Header.Width, Header.Height);
4725 else Stream.Position := StreamPos;
4727 else Stream.Position := StreamPos;
4731 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4732 {$IFDEF GLB_LIB_PNG}
4733 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
4735 TStream(png_get_io_ptr(png)).Write(buffer^, size);
4739 procedure TglBitmap.SavePNG(Stream: TStream);
4740 {$IFDEF GLB_LIB_PNG}
4743 png_info: png_infop;
4744 png_rows: array of pByte;
4749 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
4750 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
4752 if not init_libPNG then
4753 raise Exception.Create('SavePNG - unable to initialize libPNG.');
4756 case FInternalFormat of
4757 ifAlpha, ifLuminance, ifDepth8:
4758 ColorType := PNG_COLOR_TYPE_GRAY;
4760 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
4762 ColorType := PNG_COLOR_TYPE_RGB;
4764 ColorType := PNG_COLOR_TYPE_RGBA;
4766 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
4769 LineSize := Trunc(FormatGetSize(FInternalFormat) * Width);
4771 // creating array for scanline
4772 SetLength(png_rows, Height);
4774 for Row := 0 to Height - 1 do begin
4775 png_rows[Row] := Data;
4776 Inc(png_rows[Row], Row * LineSize)
4780 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
4782 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
4785 png_info := png_create_info_struct(png);
4786 if png_info = nil then begin
4787 png_destroy_write_struct(@png, nil);
4788 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
4791 // set read callback
4792 png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil);
4795 png_set_compression_level(png, 6);
4797 if InternalFormat in [ifBGR8, ifBGRA8] then
4801 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
4804 png_write_info(png, png_info);
4807 png_write_image(png, @png_rows[0]);
4810 png_write_end(png, png_info);
4812 // destroy write struct
4813 png_destroy_write_struct(@png, @png_info);
4815 SetLength(png_rows, 0);
4822 {$IFDEF GLB_PNGIMAGE}
4826 pSource, pDest: pByte;
4827 X, Y, PixSize: Integer;
4828 ColorType: Cardinal;
4834 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
4835 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
4837 case FInternalFormat of
4838 ifAlpha, ifLuminance, ifDepth8:
4840 ColorType := COLOR_GRAYSCALE;
4846 ColorType := COLOR_GRAYSCALEALPHA;
4852 ColorType := COLOR_RGB;
4858 ColorType := COLOR_RGBALPHA;
4863 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
4866 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
4870 for Y := 0 to Height -1 do begin
4871 pDest := png.ScanLine[Y];
4873 for X := 0 to Width -1 do begin
4874 Move(pSource^, pDest^, PixSize);
4876 Inc(pDest, PixSize);
4877 Inc(pSource, PixSize);
4880 png.AlphaScanline[Y]^[X] := pSource^;
4885 // convert RGB line to BGR
4886 if InternalFormat in [ifRGB8, ifRGBA8] then begin
4887 pTemp := png.ScanLine[Y];
4889 for X := 0 to Width -1 do begin
4890 Temp := pByteArray(pTemp)^[0];
4891 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
4892 pByteArray(pTemp)^[2] := Temp;
4900 Png.CompressionLevel := 6;
4901 Png.SaveToStream(Stream);
4910 procedure TglBitmap.SaveDDS(Stream: TStream);
4913 Pix: TglBitmapPixelData;
4915 if not FormatIsUncompressed(InternalFormat) then
4916 raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_INTERNAL_FORMAT);
4918 if InternalFormat = ifAlpha then
4919 FormatPreparePixel(Pix, ifLuminance)
4921 FormatPreparePixel(Pix, InternalFormat);
4924 FillChar(Header, SizeOf(Header), 0);
4926 Header.dwMagic := DDS_MAGIC;
4927 Header.dwSize := 124;
4928 Header.dwFlags := DDSD_PITCH or DDSD_CAPS or DDSD_PIXELFORMAT;
4930 if Width > 0 then begin
4931 Header.dwWidth := Width;
4932 Header.dwFlags := Header.dwFlags or DDSD_WIDTH;
4935 if Height > 0 then begin
4936 Header.dwHeight := Height;
4937 Header.dwFlags := Header.dwFlags or DDSD_HEIGHT;
4940 Header.dwPitchOrLinearSize := fRowSize;
4941 Header.dwMipMapCount := 1;
4944 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
4947 Header.PixelFormat.dwSize := Sizeof(Header.PixelFormat);
4948 Header.PixelFormat.dwFlags := DDPF_RGB;
4950 if FormatHasAlpha(InternalFormat) and (InternalFormat <> ifAlpha)
4951 then Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
4953 Header.PixelFormat.dwRGBBitCount := Trunc(FormatGetSize(InternalFormat) * 8);
4954 Header.PixelFormat.dwRBitMask := Pix.PixelDesc.RedRange shl Pix.PixelDesc.RedShift;
4955 Header.PixelFormat.dwGBitMask := Pix.PixelDesc.GreenRange shl Pix.PixelDesc.GreenShift;
4956 Header.PixelFormat.dwBBitMask := Pix.PixelDesc.BlueRange shl Pix.PixelDesc.BlueShift;
4957 Header.PixelFormat.dwAlphaBitMask := Pix.PixelDesc.AlphaRange shl Pix.PixelDesc.AlphaShift;
4960 Stream.Write(Header, SizeOf(Header));
4962 Stream.Write(Data^, FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat));
4966 procedure TglBitmap.SaveTGA(Stream: TStream);
4973 procedure ConvertData(pTemp: pByte);
4975 Idx, PixelSize: Integer;
4978 PixelSize := fPixelSize;
4980 for Idx := 1 to Height * Width do begin
4981 Temp := pByteArray(pTemp)^[2];
4982 pByteArray(pTemp)^[2] := pByteArray(pTemp)^[0];
4983 pByteArray(pTemp)^[0] := Temp;
4985 Inc(pTemp, PixelSize);
4991 if not (ftTGA in FormatGetSupportedFiles (InternalFormat)) then
4992 raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT);
4994 FillChar(Header, SizeOf(Header), 0);
4996 case InternalFormat of
4997 ifAlpha, ifLuminance, ifDepth8:
4999 Header.ImageType := TGA_UNCOMPRESSED_GRAY;
5004 Header.ImageType := TGA_UNCOMPRESSED_GRAY;
5009 Header.ImageType := TGA_UNCOMPRESSED_RGB;
5014 Header.ImageType := TGA_UNCOMPRESSED_RGB;
5018 raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT);
5021 Header.Width := Width;
5022 Header.Height := Height;
5023 Header.ImageDes := $20;
5025 if FormatHasAlpha(InternalFormat) then
5026 Header.ImageDes := Header.ImageDes or $08;
5028 Stream.Write(Header, SizeOf(Header));
5030 // convert RGB(A) to BGR(A)
5031 Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat);
5032 if InternalFormat in [tfRGB8, tfRGBA8] then begin
5033 GetMem(pTemp, Size);
5039 if InternalFormat in [tfRGB8, tfRGBA8] then begin
5040 Move(Data^, pTemp^, Size);
5045 Stream.Write(pTemp^, Size);
5048 if InternalFormat in [tfRGB8, tfRGBA8] then
5054 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
5055 procedure TglBitmap.SaveJPEG(Stream: TStream);
5056 {$IFDEF GLB_LIB_JPEG}
5058 jpeg: jpeg_compress_struct;
5059 jpeg_err: jpeg_error_mgr;
5061 pTemp, pTemp2: pByte;
5064 procedure CopyRow(pDest, pSource: pByte);
5068 for X := 0 to Width - 1 do begin
5069 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
5070 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
5071 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
5079 if not (ftJPEG in FormatGetSupportedFiles(InternalFormat)) then
5080 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
5082 if not init_libJPEG then
5083 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
5086 FillChar(jpeg, SizeOf(jpeg_compress_struct), $00);
5087 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
5090 jpeg.err := jpeg_std_error(@jpeg_err);
5091 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
5092 jpeg_err.output_message := glBitmap_libJPEG_output_message;
5094 // compression struct
5095 jpeg_create_compress(@jpeg);
5097 // allocation space for streaming methods
5098 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
5100 // seeting up custom functions
5101 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
5102 pub.init_destination := glBitmap_libJPEG_init_destination;
5103 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
5104 pub.term_destination := glBitmap_libJPEG_term_destination;
5106 pub.next_output_byte := @DestBuffer[1];
5107 pub.free_in_buffer := Length(DestBuffer);
5109 DestStream := Stream;
5112 // very important state
5113 jpeg.global_state := CSTATE_START;
5115 jpeg.image_width := Width;
5116 jpeg.image_height := Height;
5117 case InternalFormat of
5118 ifAlpha, ifLuminance, ifDepth8:
5120 jpeg.input_components := 1;
5121 jpeg.in_color_space := JCS_GRAYSCALE;
5125 jpeg.input_components := 3;
5126 jpeg.in_color_space := JCS_RGB;
5131 jpeg_set_defaults(@jpeg);
5133 // compression quality
5134 jpeg_set_quality(@jpeg, 95, True);
5136 // start compression
5137 jpeg_start_compress(@jpeg, true);
5143 if InternalFormat = ifBGR8 then
5144 GetMem(pTemp2, fRowSize)
5149 for Row := 0 to jpeg.image_height -1 do begin
5151 if InternalFormat = ifBGR8 then
5152 CopyRow(pTemp2, pTemp)
5157 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
5158 inc(pTemp, fRowSize);
5162 if InternalFormat = ifBGR8 then
5166 // finish compression
5167 jpeg_finish_compress(@jpeg);
5169 // destroy compression
5170 jpeg_destroy_compress(@jpeg);
5176 {$IFDEF GLB_DELPHI_JPEG}
5181 if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then
5182 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
5184 Bmp := TBitmap.Create;
5186 Jpg := TJPEGImage.Create;
5188 AssignToBitmap(Bmp);
5190 if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
5191 Jpg.Grayscale := True;
5192 Jpg.PixelFormat := jf8Bit;
5197 Jpg.SaveToStream(Stream);
5209 procedure TglBitmap.SaveBMP(Stream: TStream);
5213 pData, pTemp: pByte;
5215 PixelFormat: TglBitmapPixelData;
5216 ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer;
5217 Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
5219 PaddingBuff: Cardinal;
5222 function GetLineWidth : Integer;
5224 Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
5229 if not (ftBMP in FormatGetSupportedFiles(InternalFormat)) then
5230 raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT);
5232 ImageSize := Trunc(Width * Height * FormatGetSize(InternalFormat));
5234 Header.bfType := BMP_MAGIC;
5235 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
5236 Header.bfReserved1 := 0;
5237 Header.bfReserved2 := 0;
5238 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
5240 FillChar(Info, SizeOf(Info), 0);
5241 Info.biSize := SizeOf(Info);
5242 Info.biWidth := Width;
5243 Info.biHeight := Height;
5245 Info.biCompression := BMP_COMP_RGB;
5246 Info.biSizeImage := ImageSize;
5247 case InternalFormat of
5248 ifAlpha, ifLuminance, ifDepth8:
5250 Info.biBitCount := 8;
5252 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
5253 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal);
5255 Info.biClrUsed := 256;
5256 Info.biClrImportant := 256;
5258 ifLuminanceAlpha, tfRGBA4, ifR5G6B5, tfRGB5A1:
5260 Info.biBitCount := 16;
5261 Info.biCompression := BMP_COMP_BITFIELDS;
5264 Info.biBitCount := 24;
5265 ifBGRA8, tfRGBA8, tfRGB10A2:
5267 Info.biBitCount := 32;
5268 Info.biCompression := BMP_COMP_BITFIELDS;
5271 raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT);
5273 Info.biXPelsPerMeter := 2835;
5274 Info.biYPelsPerMeter := 2835;
5277 if Info.biCompression = BMP_COMP_BITFIELDS then begin
5278 Info.biSize := Info.biSize + 4 * SizeOf(Cardinal);
5279 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
5280 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
5282 FormatPreparePixel(PixelFormat, InternalFormat);
5284 with PixelFormat.PixelDesc do begin
5285 RedMask := RedRange shl RedShift;
5286 GreenMask := GreenRange shl GreenShift;
5287 BlueMask := BlueRange shl BlueShift;
5288 AlphaMask := AlphaRange shl AlphaShift;
5293 Stream.Write(Header, SizeOf(Header));
5294 Stream.Write(Info, SizeOf(Info));
5297 if Info.biBitCount = 8 then begin
5299 for ColorIdx := Low(Byte) to High(Byte) do begin
5300 Stream.Write(Temp, 4);
5301 Temp := Temp + $00010101;
5306 if Info.biCompression = BMP_COMP_BITFIELDS then begin
5307 Stream.Write(RedMask, SizeOf(Cardinal));
5308 Stream.Write(GreenMask, SizeOf(Cardinal));
5309 Stream.Write(BlueMask, SizeOf(Cardinal));
5310 Stream.Write(AlphaMask, SizeOf(Cardinal));
5314 LineSize := Trunc(Width * FormatGetSize(InternalFormat));
5315 Padding := GetLineWidth - LineSize;
5319 Inc(pData, (Height -1) * LineSize);
5321 // prepare row buffer. But only for RGB because RGBA supports color masks
5322 // so it's possible to change color within the image.
5323 if InternalFormat = tfRGB8 then
5324 GetMem(pTemp, fRowSize)
5330 for LineIdx := 0 to Height - 1 do begin
5332 if InternalFormat = tfRGB8 then begin
5333 Move(pData^, pTemp^, fRowSize);
5334 SwapRGB(pTemp, Width, False);
5338 Stream.Write(pTemp^, LineSize);
5340 Dec(pData, LineSize);
5343 Stream.Write(PaddingBuff, Padding);
5346 // destroy row buffer
5347 if InternalFormat = tfRGB8 then
5353 procedure TglBitmap.Bind(EnableTextureUnit: Boolean);
5355 if EnableTextureUnit then
5359 glBindTexture(Target, ID);
5363 procedure TglBitmap.Unbind(DisableTextureUnit: Boolean);
5365 if DisableTextureUnit then
5368 glBindTexture(Target, 0);
5372 procedure TglBitmap.GetPixel(const Pos: TglBitmapPixelPosition;
5373 var Pixel: TglBitmapPixelData);
5375 if Assigned (fGetPixelFunc) then
5376 fGetPixelFunc(Pos, Pixel);
5380 procedure TglBitmap.SetPixel (const Pos: TglBitmapPixelPosition;
5381 const Pixel: TglBitmapPixelData);
5383 if Assigned (fSetPixelFunc) then
5384 fSetPixelFunc(Pos, Pixel);
5392 function TglBitmap.FlipHorz: Boolean;
5398 function TglBitmap.FlipVert: Boolean;
5404 procedure TglBitmap.FreeData;
5406 SetDataPointer(nil, ifEmpty);
5410 procedure glBitmapFillWithColorFunc(var FuncRec: TglBitmapFunctionRec);
5412 PglBitmapPixelData = ^TglBitmapPixelData;
5414 with FuncRec do begin
5415 Dest.Red := PglBitmapPixelData(CustomData)^.Red;
5416 Dest.Green := PglBitmapPixelData(CustomData)^.Green;
5417 Dest.Blue := PglBitmapPixelData(CustomData)^.Blue;
5418 Dest.Alpha := PglBitmapPixelData(CustomData)^.Alpha;
5423 procedure TglBitmap.FillWithColor(Red, Green, Blue: Byte; Alpha: Byte);
5425 FillWithColorFloat(Red / $FF, Green / $FF, Blue / $FF, Alpha / $FF);
5429 procedure TglBitmap.FillWithColorFloat(Red, Green, Blue: Single; Alpha: Single);
5431 PixelData: TglBitmapPixelData;
5433 FormatPreparePixel(PixelData, InternalFormat);
5435 PixelData.Red := Max(0, Min(PixelData.PixelDesc.RedRange, Trunc(PixelData.PixelDesc.RedRange * Red)));
5436 PixelData.Green := Max(0, Min(PixelData.PixelDesc.GreenRange, Trunc(PixelData.PixelDesc.GreenRange * Green)));
5437 PixelData.Blue := Max(0, Min(PixelData.PixelDesc.BlueRange, Trunc(PixelData.PixelDesc.BlueRange * Blue)));
5438 PixelData.Alpha := Max(0, Min(PixelData.PixelDesc.AlphaRange, Trunc(PixelData.PixelDesc.AlphaRange * Alpha)));
5440 AddFunc(glBitmapFillWithColorFunc, False, @PixelData);
5444 procedure TglBitmap.FillWithColorRange(Red, Green, Blue: Cardinal;
5447 PixelData: TglBitmapPixelData;
5449 FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
5452 Red / PixelData.PixelDesc.RedRange,
5453 Green / PixelData.PixelDesc.GreenRange,
5454 Blue / PixelData.PixelDesc.BlueRange,
5455 Alpha / PixelData.PixelDesc.AlphaRange);
5460 procedure TglBitmap.SetInternalFormat(const aValue: TglBitmapFormat);
5462 if InternalFormat <> Value then begin
5463 if FormatGetSize(Value) <> FormatGetSize(InternalFormat) then
5464 raise EglBitmapUnsupportedFormatFormat.Create('SetInternalFormat - ' + UNSUPPORTED_INTERNAL_FORMAT);
5467 SetDataPointer(Data, Value);
5472 function TglBitmap.AddFunc(Func: TglBitmapFunction; CreateTemp: Boolean;
5473 CustomData: Pointer): boolean;
5475 Result := AddFunc(Self, Func, CreateTemp, InternalFormat, CustomData);
5479 function TglBitmap.AddFunc(Source: TglBitmap; Func: TglBitmapFunction;
5480 CreateTemp: Boolean; Format: TglBitmapFormat; CustomData: Pointer): boolean;
5482 pDest, NewImage, pSource: pByte;
5483 TempHeight, TempWidth: Integer;
5484 MapFunc: TglBitmapMapFunc;
5485 UnMapFunc: TglBitmapUnMapFunc;
5487 FuncRec: TglBitmapFunctionRec;
5489 Assert(Assigned(Data));
5490 Assert(Assigned(Source));
5491 Assert(Assigned(Source.Data));
5495 if Assigned (Source.Data) and FormatIsUncompressed(Format) and
5496 ((Source.Height > 0) or (Source.Width > 0)) then begin
5498 // inkompatible Formats so CreateTemp
5499 if FormatGetSize(Format) <> FormatGetSize(InternalFormat) then
5503 TempHeight := Max(1, Source.Height);
5504 TempWidth := Max(1, Source.Width);
5506 FuncRec.Sender := Self;
5507 FuncRec.CustomData := CustomData;
5511 if CreateTemp then begin
5512 GetMem(NewImage, Trunc(FormatGetSize(Format) * TempHeight * TempWidth));
5519 MapFunc := FormatGetMapFunc(Format);
5520 FormatPreparePixel(FuncRec.Dest, Format);
5521 FormatPreparePixel(FuncRec.Source, Source.InternalFormat);
5523 FuncRec.Size := Source.Dimension;
5524 FuncRec.Position.Fields := FuncRec.Size.Fields;
5526 if FormatIsUncompressed(Source.InternalFormat) then begin
5527 // Uncompressed Images
5528 pSource := Source.Data;
5529 UnMapFunc := FormatGetUnMapFunc(Source.InternalFormat);
5531 FuncRec.Position.Y := 0;
5532 while FuncRec.Position.Y < TempHeight do begin
5533 FuncRec.Position.X := 0;
5534 while FuncRec.Position.X < TempWidth do begin
5536 UnMapFunc(pSource, FuncRec.Source);
5540 MapFunc(FuncRec.Dest, pDest);
5541 Inc(FuncRec.Position.X);
5543 Inc(FuncRec.Position.Y);
5546 // Compressed Images
5547 FuncRec.Position.Y := 0;
5548 while FuncRec.Position.Y < TempHeight do begin
5549 FuncRec.Position.X := 0;
5550 while FuncRec.Position.X < TempWidth do begin
5552 fGetPixelFunc(FuncRec.Position, FuncRec.Source);
5556 MapFunc(FuncRec.Dest, pDest);
5557 Inc(FuncRec.Position.X);
5559 Inc(FuncRec.Position.Y);
5563 // Updating Image or InternalFormat
5565 SetDataPointer(NewImage, Format)
5568 if Format <> InternalFormat then
5569 SetInternalFormat(Format);
5574 then FreeMem(NewImage);
5581 procedure glBitmapConvertCopyFunc(var FuncRec: TglBitmapFunctionRec);
5583 with FuncRec do begin
5584 if Source.PixelDesc.RedRange > 0 then
5585 Dest.Red := Source.Red;
5587 if Source.PixelDesc.GreenRange > 0 then
5588 Dest.Green := Source.Green;
5590 if Source.PixelDesc.BlueRange > 0 then
5591 Dest.Blue := Source.Blue;
5593 if Source.PixelDesc.AlphaRange > 0 then
5594 Dest.Alpha := Source.Alpha;
5599 procedure glBitmapConvertCalculateRGBAFunc(var FuncRec: TglBitmapFunctionRec);
5601 with FuncRec do begin
5602 if Source.PixelDesc.RedRange > 0 then
5603 Dest.Red := Round(Dest.PixelDesc.RedRange * Source.Red / Source.PixelDesc.RedRange);
5605 if Source.PixelDesc.GreenRange > 0 then
5606 Dest.Green := Round(Dest.PixelDesc.GreenRange * Source.Green / Source.PixelDesc.GreenRange);
5608 if Source.PixelDesc.BlueRange > 0 then
5609 Dest.Blue := Round(Dest.PixelDesc.BlueRange * Source.Blue / Source.PixelDesc.BlueRange);
5611 if Source.PixelDesc.AlphaRange > 0 then
5612 Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Source.Alpha / Source.PixelDesc.AlphaRange);
5617 procedure glBitmapConvertShiftRGBAFunc(var FuncRec: TglBitmapFunctionRec);
5620 with TglBitmapPixelDesc(CustomData^) do begin
5621 if Source.PixelDesc.RedRange > 0 then
5622 Dest.Red := Source.Red shr RedShift;
5624 if Source.PixelDesc.GreenRange > 0 then
5625 Dest.Green := Source.Green shr GreenShift;
5627 if Source.PixelDesc.BlueRange > 0 then
5628 Dest.Blue := Source.Blue shr BlueShift;
5630 if Source.PixelDesc.AlphaRange > 0 then
5631 Dest.Alpha := Source.Alpha shr AlphaShift;
5636 function TglBitmap.ConvertTo(NewFormat: TglBitmapFormat): boolean;
5638 Source, Dest: TglBitmapPixelData;
5639 PixelDesc: TglBitmapPixelDesc;
5641 function CopyDirect: Boolean;
5644 ((Source.PixelDesc.RedRange = Dest.PixelDesc.RedRange) or (Source.PixelDesc.RedRange = 0) or (Dest.PixelDesc.RedRange = 0)) and
5645 ((Source.PixelDesc.GreenRange = Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and
5646 ((Source.PixelDesc.BlueRange = Dest.PixelDesc.BlueRange) or (Source.PixelDesc.BlueRange = 0) or (Dest.PixelDesc.BlueRange = 0)) and
5647 ((Source.PixelDesc.AlphaRange = Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0));
5650 function CanShift: Boolean;
5653 ((Source.PixelDesc.RedRange >= Dest.PixelDesc.RedRange ) or (Source.PixelDesc.RedRange = 0) or (Dest.PixelDesc.RedRange = 0)) and
5654 ((Source.PixelDesc.GreenRange >= Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and
5655 ((Source.PixelDesc.BlueRange >= Dest.PixelDesc.BlueRange ) or (Source.PixelDesc.BlueRange = 0) or (Dest.PixelDesc.BlueRange = 0)) and
5656 ((Source.PixelDesc.AlphaRange >= Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0));
5659 function GetShift(Source, Dest: Cardinal) : ShortInt;
5663 while (Source > Dest) and (Source > 0) do begin
5665 Source := Source shr 1;
5670 if NewFormat <> InternalFormat then begin
5671 FormatPreparePixel(Source, InternalFormat);
5672 FormatPreparePixel(Dest, NewFormat);
5675 Result := AddFunc(Self, glBitmapConvertCopyFunc, False, NewFormat)
5677 if CanShift then begin
5678 PixelDesc.RedShift := GetShift(Source.PixelDesc.RedRange, Dest.PixelDesc.RedRange);
5679 PixelDesc.GreenShift := GetShift(Source.PixelDesc.GreenRange, Dest.PixelDesc.GreenRange);
5680 PixelDesc.BlueShift := GetShift(Source.PixelDesc.BlueRange, Dest.PixelDesc.BlueRange);
5681 PixelDesc.AlphaShift := GetShift(Source.PixelDesc.AlphaRange, Dest.PixelDesc.AlphaRange);
5683 Result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, False, NewFormat, @PixelDesc);
5685 else Result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, False, NewFormat);
5687 else Result := True;
5691 function TglBitmap.RemoveAlpha: Boolean;
5695 if (Assigned(Data)) then begin
5696 if not (FormatIsUncompressed(InternalFormat) or FormatHasAlpha(InternalFormat)) then
5697 raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_INTERNAL_FORMAT);
5699 Result := ConvertTo(FormatGetWithoutAlpha(InternalFormat));
5704 function TglBitmap.AddAlphaFromFunc(Func: TglBitmapFunction; CustomData: Pointer): boolean;
5706 if not FormatIsUncompressed(InternalFormat) then
5707 raise EglBitmapUnsupportedFormatFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_INTERNAL_FORMAT);
5709 Result := AddFunc(Self, Func, False, FormatGetWithAlpha(InternalFormat), CustomData);
5713 function TglBitmap.GetFileHeight: Integer;
5715 Result := Max(1, Height);
5719 function TglBitmap.GetFileWidth: Integer;
5721 Result := Max(1, Width);
5725 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
5729 with FuncRec do begin
5731 Source.Red / Source.PixelDesc.RedRange * 0.3 +
5732 Source.Green / Source.PixelDesc.GreenRange * 0.59 +
5733 Source.Blue / Source.PixelDesc.BlueRange * 0.11;
5735 Dest.Alpha := Round (Dest.PixelDesc.AlphaRange * Temp);
5740 function TglBitmap.AddAlphaFromglBitmap(glBitmap: TglBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean;
5742 pDest, pDest2, pSource: pByte;
5743 TempHeight, TempWidth: Integer;
5744 MapFunc: TglBitmapMapFunc;
5745 DestUnMapFunc, UnMapFunc: TglBitmapUnMapFunc;
5747 FuncRec: TglBitmapFunctionRec;
5751 assert(Assigned(Data));
5752 assert(Assigned(glBitmap));
5753 assert(Assigned(glBitmap.Data));
5755 if ((glBitmap.Width = Width) and (glBitmap.Height = Height)) then begin
5756 // Convert to Data with Alpha
5757 Result := ConvertTo(FormatGetWithAlpha(FormatGetUncompressed(InternalFormat)));
5759 if not Assigned(Func) then
5760 Func := glBitmapAlphaFunc;
5763 TempHeight := glBitmap.FileHeight;
5764 TempWidth := glBitmap.FileWidth;
5766 FuncRec.Sender := Self;
5767 FuncRec.CustomData := CustomData;
5771 pSource := glBitmap.Data;
5774 FormatPreparePixel(FuncRec.Dest, InternalFormat);
5775 FormatPreparePixel(FuncRec.Source, glBitmap.InternalFormat);
5776 MapFunc := FormatGetMapFunc(InternalFormat);
5777 DestUnMapFunc := FormatGetUnMapFunc(InternalFormat);
5778 UnMapFunc := FormatGetUnMapFunc(glBitmap.InternalFormat);
5780 FuncRec.Size := Dimension;
5781 FuncRec.Position.Fields := FuncRec.Size.Fields;
5783 FuncRec.Position.Y := 0;
5784 while FuncRec.Position.Y < TempHeight do begin
5785 FuncRec.Position.X := 0;
5786 while FuncRec.Position.X < TempWidth do begin
5788 UnMapFunc(pSource, FuncRec.Source);
5789 DestUnMapFunc(pDest2, FuncRec.Dest);
5793 MapFunc(FuncRec.Dest, pDest);
5794 Inc(FuncRec.Position.X);
5796 Inc(FuncRec.Position.Y);
5802 procedure TglBitmap.SetBorderColor(Red, Green, Blue, Alpha: Single);
5804 fBorderColor[0] := Red;
5805 fBorderColor[1] := Green;
5806 fBorderColor[2] := Blue;
5807 fBorderColor[3] := Alpha;
5809 if ID > 0 then begin
5812 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
5819 procedure TglBitmap2D.SetDataPointer(Data: pByte; Format: TglBitmapFormat; Width, Height: Integer);
5821 Idx, LineWidth: Integer;
5826 if FormatIsUncompressed(Format) then begin
5827 fUnmapFunc := FormatGetUnMapFunc(Format);
5828 fGetPixelFunc := GetPixel2DUnmap;
5830 fMapFunc := FormatGetMapFunc(Format);
5831 fSetPixelFunc := SetPixel2DUnmap;
5834 if Assigned(Data) then begin
5835 SetLength(fLines, GetHeight);
5837 LineWidth := Trunc(GetWidth * FormatGetSize(InternalFormat));
5839 for Idx := 0 to GetHeight -1 do begin
5840 fLines[Idx] := Data;
5841 Inc(fLines[Idx], Idx * LineWidth);
5844 else SetLength(fLines, 0);
5846 SetLength(fLines, 0);
5848 fSetPixelFunc := nil;
5852 fGetPixelFunc := GetPixel2DDXT1;
5854 fGetPixelFunc := GetPixel2DDXT3;
5856 fGetPixelFunc := GetPixel2DDXT5;
5858 fGetPixelFunc := nil;
5864 procedure TglBitmap2D.GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
5866 PDXT1Chunk = ^TDXT1Chunk;
5867 TDXT1Chunk = packed record
5870 Pixels: array [0..3] of byte;
5874 BasePtr: pDXT1Chunk;
5876 Colors: array [0..3] of TRGBQuad;
5878 BasePtr := pDXT1Chunk(pData);
5880 PixPos := BasePtr^.Pixels[relY] shr (relX * 2) and $3;
5882 if PixPos in [0, 2, 3] then begin
5883 Colors[0].rgbRed := BasePtr^.Color1 and $F800 shr 8;
5884 Colors[0].rgbGreen := BasePtr^.Color1 and $07E0 shr 3;
5885 Colors[0].rgbBlue := BasePtr^.Color1 and $001F shl 3;
5886 Colors[0].rgbReserved := 255;
5889 if PixPos in [1, 2, 3] then begin
5890 Colors[1].rgbRed := BasePtr^.Color2 and $F800 shr 8;
5891 Colors[1].rgbGreen := BasePtr^.Color2 and $07E0 shr 3;
5892 Colors[1].rgbBlue := BasePtr^.Color2 and $001F shl 3;
5893 Colors[1].rgbReserved := 255;
5896 if PixPos = 2 then begin
5897 Colors[2].rgbRed := (Colors[0].rgbRed * 67 + Colors[1].rgbRed * 33) div 100;
5898 Colors[2].rgbGreen := (Colors[0].rgbGreen * 67 + Colors[1].rgbGreen * 33) div 100;
5899 Colors[2].rgbBlue := (Colors[0].rgbBlue * 67 + Colors[1].rgbBlue * 33) div 100;
5900 Colors[2].rgbReserved := 255;
5903 if PixPos = 3 then begin
5904 Colors[3].rgbRed := (Colors[0].rgbRed * 33 + Colors[1].rgbRed * 67) div 100;
5905 Colors[3].rgbGreen := (Colors[0].rgbGreen * 33 + Colors[1].rgbGreen * 67) div 100;
5906 Colors[3].rgbBlue := (Colors[0].rgbBlue * 33 + Colors[1].rgbBlue * 67) div 100;
5907 if BasePtr^.Color1 > BasePtr^.Color2 then
5908 Colors[3].rgbReserved := 255
5910 Colors[3].rgbReserved := 0;
5913 Pixel.Red := Colors[PixPos].rgbRed;
5914 Pixel.Green := Colors[PixPos].rgbGreen;
5915 Pixel.Blue := Colors[PixPos].rgbBlue;
5916 Pixel.Alpha := Colors[PixPos].rgbReserved;
5920 procedure TglBitmap2D.GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
5923 PosX, PosY: Integer;
5927 if (Pos.Y <= Height) and (Pos.X <= Width) then begin
5928 PosX := Pos.X div 4;
5929 PosY := Pos.Y div 4;
5932 Inc(BasePtr, (PosY * Width div 4 + PosX) * 8);
5934 GetDXTColorBlock(BasePtr, Pos.X - PosX * 4, Pos.Y - PosY * 4, Pixel);
5939 procedure TglBitmap2D.GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
5941 PDXT3AlphaChunk = ^TDXT3AlphaChunk;
5942 TDXT3AlphaChunk = array [0..3] of WORD;
5946 AlphaPtr: PDXT3AlphaChunk;
5947 PosX, PosY, relX, relY: Integer;
5951 if (Pos.Y <= Height) and (Pos.X <= Width) then begin
5952 PosX := Pos.X div 4;
5953 PosY := Pos.Y div 4;
5954 relX := Pos.X - PosX * 4;
5955 relY := Pos.Y - PosY * 4;
5958 AlphaPtr := PDXT3AlphaChunk(Data);
5959 Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2);
5961 ColorPtr := pByte(AlphaPtr);
5964 GetDXTColorBlock(ColorPtr, relX, relY, Pixel);
5967 Pixel.Alpha := AlphaPtr^[relY] shr (4 * relX) and $0F shl 4;
5972 procedure TglBitmap2D.GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
5976 PixPos, PosX, PosY, relX, relY: Integer;
5977 Alpha0, Alpha1: Byte;
5981 if (Pos.Y <= Height) and (Pos.X <= Width) then begin
5982 PosX := Pos.X div 4;
5983 PosY := Pos.Y div 4;
5984 relX := Pos.X - PosX * 4;
5985 relY := Pos.Y - PosY * 4;
5988 AlphaPtr := PInt64(Data);
5989 Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2);
5991 ColorPtr := pByte(AlphaPtr);
5994 GetDXTColorBlock(ColorPtr, relX, relY, Pixel);
5997 Alpha0 := AlphaPtr^ and $FF;
5998 Alpha1 := AlphaPtr^ shr 8 and $FF;
6000 PixPos := AlphaPtr^ shr (16 + (relY * 4 + relX) * 3) and $07;
6003 if PixPos = 0 then begin
6004 Pixel.Alpha := Alpha0;
6008 if PixPos = 1 then begin
6009 Pixel.Alpha := Alpha1;
6012 // alpha interpolate 7 Steps
6013 if Alpha0 > Alpha1 then begin
6014 Pixel.Alpha := ((8 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 7;
6017 // alpha is 100% transparent or not transparent
6018 if PixPos >= 6 then begin
6025 // alpha interpolate 5 Steps
6027 Pixel.Alpha := ((6 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 5;
6033 procedure TglBitmap2D.GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
6037 pTemp := fLines[Pos.Y];
6038 Inc(pTemp, Pos.X * fPixelSize);
6040 fUnmapFunc(pTemp, Pixel);
6044 procedure TglBitmap2D.SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
6048 pTemp := fLines[Pos.Y];
6049 Inc(pTemp, Pos.X * fPixelSize);
6051 fMapFunc(Pixel, pTemp);
6055 function TglBitmap2D.FlipHorz: Boolean;
6058 pTempDest, pDest, pSource: pByte;
6061 Result := Inherited FlipHorz;
6063 if Assigned(Data) then begin
6065 ImgSize := Height * fRowSize;
6067 GetMem(pDest, ImgSize);
6071 Dec(pTempDest, fRowSize + fPixelSize);
6072 for Row := 0 to Height -1 do begin
6073 Inc(pTempDest, fRowSize * 2);
6074 for Col := 0 to Width -1 do begin
6075 Move(pSource^, pTempDest^, fPixelSize);
6077 Inc(pSource, fPixelSize);
6078 Dec(pTempDest, fPixelSize);
6082 SetDataPointer(pDest, InternalFormat);
6093 function TglBitmap2D.FlipVert: Boolean;
6096 pTempDest, pDest, pSource: pByte;
6098 Result := Inherited FlipVert;
6100 if Assigned(Data) then begin
6102 GetMem(pDest, Height * fRowSize);
6106 Inc(pTempDest, Width * (Height -1) * fPixelSize);
6108 for Row := 0 to Height -1 do begin
6109 Move(pSource^, pTempDest^, fRowSize);
6111 Dec(pTempDest, fRowSize);
6112 Inc(pSource, fRowSize);
6115 SetDataPointer(pDest, InternalFormat);
6126 procedure TglBitmap2D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
6128 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6131 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
6132 glCompressedTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Trunc(Width * Height * FormatGetSize(Self.InternalFormat)), Data)
6135 if BuildWithGlu then
6136 gluBuild2DMipmaps(Target, InternalFormat, Width, Height, Format, Typ, Data)
6138 glTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Format, Typ, Data);
6141 if (FreeDataAfterGenTexture) then
6146 procedure TglBitmap2D.GenTexture(TestTextureSize: Boolean);
6148 BuildWithGlu, PotTex, TexRec: Boolean;
6149 glFormat, glInternalFormat, glType: Cardinal;
6152 if Assigned(Data) then begin
6153 // Check Texture Size
6154 if (TestTextureSize) then begin
6155 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
6157 if ((Height > TexSize) or (Width > TexSize)) then
6158 raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
6160 PotTex := IsPowerOfTwo (Height) and IsPowerOfTwo (Width);
6161 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
6162 (Target = GL_TEXTURE_RECTANGLE_ARB);
6164 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
6165 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
6170 SetupParameters(BuildWithGlu);
6171 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
6173 UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
6176 glAreTexturesResident(1, @ID, @fIsResident);
6181 procedure TglBitmap2D.AfterConstruction;
6185 Target := GL_TEXTURE_2D;
6190 TMatrixItem = record
6195 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
6196 TglBitmapToNormalMapRec = Record
6198 Heights: array of Single;
6199 MatrixU : array of TMatrixItem;
6200 MatrixV : array of TMatrixItem;
6204 oneover255 = 1 / 255;
6206 procedure glBitmapToNormalMapPrepareFunc (var FuncRec: TglBitmapFunctionRec);
6210 with FuncRec do begin
6211 Val := Source.Red * 0.3 + Source.Green * 0.59 + Source.Blue * 0.11;
6212 PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Val * oneover255;
6217 procedure glBitmapToNormalMapPrepareAlphaFunc (var FuncRec: TglBitmapFunctionRec);
6220 PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Source.Alpha * oneover255;
6224 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
6226 TVec = Array[0..2] of Single;
6233 function GetHeight(X, Y: Integer): Single;
6235 with FuncRec do begin
6236 X := Max(0, Min(Size.X -1, X));
6237 Y := Max(0, Min(Size.Y -1, Y));
6239 Result := PglBitmapToNormalMapRec (CustomData)^.Heights[Y * Size.X + X];
6244 with FuncRec do begin
6245 with PglBitmapToNormalMapRec (CustomData)^ do begin
6247 for Idx := Low(MatrixU) to High(MatrixU) do
6248 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
6251 for Idx := Low(MatrixU) to High(MatrixU) do
6252 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
6254 Vec[0] := -du * Scale;
6255 Vec[1] := -dv * Scale;
6260 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
6261 if Len <> 0 then begin
6262 Vec[0] := Vec[0] * Len;
6263 Vec[1] := Vec[1] * Len;
6264 Vec[2] := Vec[2] * Len;
6268 Dest.Red := Trunc((Vec[0] + 1) * 127.5);
6269 Dest.Green := Trunc((Vec[1] + 1) * 127.5);
6270 Dest.Blue := Trunc((Vec[2] + 1) * 127.5);
6275 procedure TglBitmap2D.ToNormalMap(Func: TglBitmapNormalMapFunc; Scale: Single; UseAlpha: Boolean);
6277 Rec: TglBitmapToNormalMapRec;
6279 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
6281 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
6282 Matrix[Index].X := X;
6283 Matrix[Index].Y := Y;
6284 Matrix[Index].W := W;
6289 if not FormatIsUncompressed(InternalFormat) then
6290 raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_INTERNAL_FORMAT);
6295 if Scale < -100 then
6300 SetLength(Rec.Heights, Width * Height);
6305 SetLength(Rec.MatrixU, 2);
6306 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
6307 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
6309 SetLength(Rec.MatrixV, 2);
6310 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
6311 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
6315 SetLength(Rec.MatrixU, 6);
6316 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
6317 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
6318 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
6319 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
6320 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
6321 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
6323 SetLength(Rec.MatrixV, 6);
6324 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
6325 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
6326 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
6327 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
6328 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
6329 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
6333 SetLength(Rec.MatrixU, 6);
6334 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
6335 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
6336 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
6337 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
6338 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
6339 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
6341 SetLength(Rec.MatrixV, 6);
6342 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
6343 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
6344 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
6345 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
6346 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
6347 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
6351 SetLength(Rec.MatrixU, 20);
6352 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
6353 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
6354 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
6355 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
6356 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
6357 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
6358 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
6359 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
6360 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
6361 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
6362 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
6363 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
6364 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
6365 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
6366 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
6367 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
6368 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
6369 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
6370 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
6371 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
6373 SetLength(Rec.MatrixV, 20);
6374 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
6375 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
6376 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
6377 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
6378 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
6379 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
6380 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
6381 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
6382 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
6383 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
6384 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
6385 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
6386 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
6387 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
6388 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
6389 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
6390 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
6391 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
6392 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
6393 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
6398 if UseAlpha and FormatHasAlpha(InternalFormat) then
6399 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, False, @Rec)
6401 AddFunc(glBitmapToNormalMapPrepareFunc, False, @Rec);
6403 // Neues Bild berechnen
6404 AddFunc(glBitmapToNormalMapFunc, False, @Rec);
6406 SetLength(Rec.Heights, 0);
6411 procedure TglBitmap2D.GrabScreen(Top, Left, Right, Bottom: Integer; Format: TglBitmapFormat);
6415 glFormat, glInternalFormat, glType: Cardinal;
6417 if not FormatIsUncompressed(Format) then
6418 raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_INTERNAL_FORMAT);
6420 // Only to select Formats
6421 SelectFormat(Format, glFormat, glInternalFormat, glType, False);
6423 Size := FormatGetImageSize(glBitmapPosition(Right - Left, Bottom - Top), Format);
6426 glPixelStorei(GL_PACK_ALIGNMENT, 1);
6427 glReadPixels(Left, Top, Right - Left, Bottom - Top, glFormat, glType, Temp);
6430 SetDataPointer(Temp, Format, Right - Left, Bottom - Top);
6441 procedure TglBitmap2D.GetDataFromTexture;
6444 TempWidth, TempHeight, RedSize, GreenSize, BlueSize, AlphaSize, LumSize: Integer;
6445 TempType, TempIntFormat: Cardinal;
6446 IntFormat: TglBitmapFormat;
6451 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
6452 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
6453 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
6455 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_RED_SIZE, @RedSize);
6456 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_GREEN_SIZE, @GreenSize);
6457 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_BLUE_SIZE, @BlueSize);
6458 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_ALPHA_SIZE, @AlphaSize);
6459 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_LUMINANCE_SIZE, @LumSize);
6461 // Get glBitmapInternalFormat from TempIntFormat
6462 TempType := GL_UNSIGNED_BYTE;
6463 case TempIntFormat of
6465 IntFormat := ifAlpha;
6467 IntFormat := ifLuminance;
6469 IntFormat := ifLuminanceAlpha;
6472 IntFormat := ifR5G6B5;
6473 TempIntFormat := GL_RGB;
6474 TempType := GL_UNSIGNED_SHORT_5_6_5;
6477 IntFormat := tfRGB8;
6478 GL_RGBA, GL_RGBA4, GL_RGBA8:
6480 if (RedSize = 4) and (BlueSize = 4) and (GreenSize = 4) and (AlphaSize = 4) then begin
6481 IntFormat := tfRGBA4;
6482 TempIntFormat := GL_BGRA;
6483 TempType := GL_UNSIGNED_SHORT_4_4_4_4_REV;
6485 if (RedSize = 5) and (BlueSize = 5) and (GreenSize = 5) and (AlphaSize = 1) then begin
6486 IntFormat := tfRGB5A1;
6487 TempIntFormat := GL_BGRA;
6488 TempType := GL_UNSIGNED_SHORT_1_5_5_5_REV;
6490 IntFormat := tfRGBA8;
6494 IntFormat := ifBGR8;
6496 IntFormat := ifBGRA8;
6497 GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
6498 IntFormat := ifDXT1;
6499 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
6500 IntFormat := ifDXT1;
6501 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
6502 IntFormat := ifDXT3;
6503 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
6504 IntFormat := ifDXT5;
6506 IntFormat := ifEmpty;
6509 // Getting data from OpenGL
6510 GetMem(Temp, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
6512 if FormatIsCompressed(IntFormat) and (GL_VERSION_1_3 or GL_ARB_texture_compression) then
6513 glGetCompressedTexImage(Target, 0, Temp)
6515 glGetTexImage(Target, 0, TempIntFormat, TempType, Temp);
6517 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
6525 function TglBitmap2D.GetScanline(Index: Integer): Pointer;
6527 if (Index >= Low(fLines)) and (Index <= High(fLines)) then
6528 Result := fLines[Index]
6536 procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
6541 if Height > 1 then begin
6542 // extract first line of the data
6543 Size := FormatGetImageSize(glBitmapPosition(Width), Format);
6544 GetMem(pTemp, Size);
6546 Move(Data^, pTemp^, Size);
6553 inherited SetDataPointer(pTemp, Format, Width);
6555 if FormatIsUncompressed(Format) then begin
6556 fUnmapFunc := FormatGetUnMapFunc(Format);
6557 fGetPixelFunc := GetPixel1DUnmap;
6562 procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
6567 Inc(pTemp, Pos.X * fPixelSize);
6569 fUnmapFunc(pTemp, Pixel);
6573 function TglBitmap1D.FlipHorz: Boolean;
6576 pTempDest, pDest, pSource: pByte;
6578 Result := Inherited FlipHorz;
6580 if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin
6583 GetMem(pDest, fRowSize);
6587 Inc(pTempDest, fRowSize);
6588 for Col := 0 to Width -1 do begin
6589 Move(pSource^, pTempDest^, fPixelSize);
6591 Inc(pSource, fPixelSize);
6592 Dec(pTempDest, fPixelSize);
6595 SetDataPointer(pDest, InternalFormat);
6605 procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
6608 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
6609 glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data)
6613 if BuildWithGlu then
6614 gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data)
6616 glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data);
6619 if (FreeDataAfterGenTexture) then
6624 procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean);
6626 BuildWithGlu, TexRec: Boolean;
6627 glFormat, glInternalFormat, glType: Cardinal;
6630 if Assigned(Data) then begin
6631 // Check Texture Size
6632 if (TestTextureSize) then begin
6633 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
6635 if (Width > TexSize) then
6636 raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
6638 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
6639 (Target = GL_TEXTURE_RECTANGLE_ARB);
6641 if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
6642 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
6647 SetupParameters(BuildWithGlu);
6648 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
6650 UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
6653 glAreTexturesResident(1, @ID, @fIsResident);
6658 procedure TglBitmap1D.AfterConstruction;
6662 Target := GL_TEXTURE_1D;
6666 { TglBitmapCubeMap }
6668 procedure TglBitmapCubeMap.AfterConstruction;
6672 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
6673 raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
6675 SetWrap; // set all to GL_CLAMP_TO_EDGE
6676 Target := GL_TEXTURE_CUBE_MAP;
6677 fGenMode := GL_REFLECTION_MAP;
6681 procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean);
6683 inherited Bind (EnableTextureUnit);
6685 if EnableTexCoordsGen then begin
6686 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
6687 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
6688 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
6689 glEnable(GL_TEXTURE_GEN_S);
6690 glEnable(GL_TEXTURE_GEN_T);
6691 glEnable(GL_TEXTURE_GEN_R);
6696 procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean);
6698 glFormat, glInternalFormat, glType: Cardinal;
6699 BuildWithGlu: Boolean;
6702 // Check Texture Size
6703 if (TestTextureSize) then begin
6704 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
6706 if ((Height > TexSize) or (Width > TexSize)) then
6707 raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
6709 if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
6710 raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
6714 if ID = 0 then begin
6716 SetupParameters(BuildWithGlu);
6719 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
6721 UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu);
6725 procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean);
6727 Assert(False, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
6731 procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen,
6732 DisableTextureUnit: Boolean);
6734 inherited Unbind (DisableTextureUnit);
6736 if DisableTexCoordsGen then begin
6737 glDisable(GL_TEXTURE_GEN_S);
6738 glDisable(GL_TEXTURE_GEN_T);
6739 glDisable(GL_TEXTURE_GEN_R);
6744 { TglBitmapNormalMap }
6747 TVec = Array[0..2] of Single;
6748 TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6750 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
6751 TglBitmapNormalMapRec = record
6753 Func: TglBitmapNormalMapGetVectorFunc;
6757 procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6760 Vec[1] := - (Position.Y + 0.5 - HalfSize);
6761 Vec[2] := - (Position.X + 0.5 - HalfSize);
6765 procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6767 Vec[0] := - HalfSize;
6768 Vec[1] := - (Position.Y + 0.5 - HalfSize);
6769 Vec[2] := Position.X + 0.5 - HalfSize;
6773 procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6775 Vec[0] := Position.X + 0.5 - HalfSize;
6777 Vec[2] := Position.Y + 0.5 - HalfSize;
6781 procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6783 Vec[0] := Position.X + 0.5 - HalfSize;
6784 Vec[1] := - HalfSize;
6785 Vec[2] := - (Position.Y + 0.5 - HalfSize);
6789 procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6791 Vec[0] := Position.X + 0.5 - HalfSize;
6792 Vec[1] := - (Position.Y + 0.5 - HalfSize);
6797 procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
6799 Vec[0] := - (Position.X + 0.5 - HalfSize);
6800 Vec[1] := - (Position.Y + 0.5 - HalfSize);
6801 Vec[2] := - HalfSize;
6805 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
6810 with FuncRec do begin
6811 with PglBitmapNormalMapRec (CustomData)^ do begin
6812 Func(Vec, Position, HalfSize);
6815 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
6816 if Len <> 0 then begin
6817 Vec[0] := Vec[0] * Len;
6818 Vec[1] := Vec[1] * Len;
6819 Vec[2] := Vec[2] * Len;
6822 // Scale Vector and AddVectro
6823 Vec[0] := Vec[0] * 0.5 + 0.5;
6824 Vec[1] := Vec[1] * 0.5 + 0.5;
6825 Vec[2] := Vec[2] * 0.5 + 0.5;
6829 Dest.Red := Round(Vec[0] * 255);
6830 Dest.Green := Round(Vec[1] * 255);
6831 Dest.Blue := Round(Vec[2] * 255);
6836 procedure TglBitmapNormalMap.AfterConstruction;
6840 fGenMode := GL_NORMAL_MAP;
6844 procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer;
6845 TestTextureSize: Boolean);
6847 Rec: TglBitmapNormalMapRec;
6848 SizeRec: TglBitmapPixelPosition;
6850 Rec.HalfSize := Size div 2;
6852 FreeDataAfterGenTexture := False;
6854 SizeRec.Fields := [ffX, ffY];
6859 Rec.Func := glBitmapNormalMapPosX;
6860 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6861 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize);
6864 Rec.Func := glBitmapNormalMapNegX;
6865 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6866 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize);
6869 Rec.Func := glBitmapNormalMapPosY;
6870 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6871 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize);
6874 Rec.Func := glBitmapNormalMapNegY;
6875 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6876 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize);
6879 Rec.Func := glBitmapNormalMapPosZ;
6880 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6881 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize);
6884 Rec.Func := glBitmapNormalMapNegZ;
6885 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
6886 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize);
6890 glBitmapSetDefaultFormat(tfEmpty);
6891 glBitmapSetDefaultMipmap(mmMipmap);
6892 glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
6893 glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
6895 glBitmapSetDefaultFreeDataAfterGenTexture(true);
6896 glBitmapSetDefaultDeleteTextureOnFree (true);