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 EglBitmapException = class(Exception);
587 EglBitmapSizeToLargeException = class(EglBitmapException);
588 EglBitmapNonPowerOfTwoException = class(EglBitmapException);
589 EglBitmapUnsupportedInternalFormat = class(EglBitmapException);
591 TglBitmapPixelDesc = packed record
593 GreenRange: Cardinal;
595 AlphaRange: Cardinal;
598 GreenShift: Shortint;
600 AlphaShift: Shortint;
603 TglBitmapPixelData = packed record
608 PixelDesc: TglBitmapPixelDesc;
611 TglBitmapPixelPositionFields = set of (ffX, ffY);
612 TglBitmapPixelPosition = record
613 Fields : TglBitmapPixelPositionFields;
619 NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
624 TglBitmapFunctionRec = record
626 Size: TglBitmapPixelPosition;
627 Position: TglBitmapPixelPosition;
628 Source: TglBitmapPixelData;
629 Dest: TglBitmapPixelData;
633 TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
635 TglBitmapGetPixel = procedure (
636 const Pos: TglBitmapPixelPosition;
637 var Pixel: TglBitmapPixelData) of object;
639 TglBitmapSetPixel = procedure (
640 const Pos: TglBitmapPixelPosition;
641 const Pixel: TglBitmapPixelData) of object;
643 TglBitmapFileType = (
644 {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF}
645 {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
649 TglBitmapFileTypes = set of TglBitmapFileType;
655 TglBitmapNormalMapFunc = (
669 tfLuminance = GL_LUMINANCE,
670 tfLuminanceAlpha = GL_LUMINANCE_ALPHA
672 TglBitmapInternalFormat = (
673 ifAlpha4 = GL_ALPHA4,
674 ifAlpha8 = GL_ALPHA8,
675 ifAlpha12 = GL_ALPHA12,
676 ifAlpha16 = GL_ALPHA16,
678 ifLuminance4 = GL_LUMINANCE4,
679 ifLuminance8 = GL_LUMINANCE8,
680 ifLuminance12 = GL_LUMINANCE12,
681 ifLuminance16 = GL_LUMINANCE16,
683 ifLuminance4Alpha4 = GL_LUMINANCE4_ALPHA4,
684 ifLuminance6Alpha2 = GL_LUMINANCE6_ALPHA2,
685 ifLuminance8Alpha8 = GL_LUMINANCE8_ALPHA8,
686 ifLuminance12Alpha4 = GL_LUMINANCE12_ALPHA4,
687 ifLuminance12Alpha12 = GL_LUMINANCE12_ALPHA12,
688 ifLuminance16Alpha16 = GL_LUMINANCE16_ALPHA16,
690 ifR3G3B2 = GL_R3_G3_B2,
700 ifRGB5A1 = GL_RGB5_A1,
702 ifRGB10A2 = GL_RGB10_A2,
703 ifRGBA12 = GL_RGBA12,
704 ifRGBA16 = GL_RGBA16,
706 ifDepth16 = GL_DEPTH_COMPONENT16,
707 ifDepth24 = GL_DEPTH_COMPONENT24,
708 ifDepth32 = GL_DEPTH_COMPONENT32
712 TglBitmapMapFunc = procedure(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
713 TglBitmapUnMapFunc = procedure(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData);
720 fAnisotropic: Integer;
721 fDeleteTextureOnFree: Boolean;
722 fFreeDataAfterGenTexture: Boolean;
724 fIsResident: Boolean;
725 fBorderColor: array[0..3] of Single;
727 fDimension: TglBitmapPixelPosition;
728 fMipMap: TglBitmapMipMap;
729 fFormat: TglBitmapFormat;
730 fInternalFormat: TglBitmapInternalFormat;
735 fUnmapFunc: TglBitmapUnMapFunc;
736 fMapFunc: TglBitmapMapFunc;
739 fFilterMin: Cardinal;
740 fFilterMag: Cardinal;
747 fGetPixelFunc: TglBitmapGetPixel;
748 fSetPixelFunc: TglBitmapSetPixel;
753 fCustomNameW: WideString;
754 fCustomData: Pointer;
757 function GetHeight: Integer; virtual;
758 function GetWidth: Integer; virtual;
761 procedure SetCustomData(const aValue: Pointer);
762 procedure SetCustomName(const aValue: String);
763 procedure SetCustomNameW(const aValue: WideString);
764 procedure SetDeleteTextureOnFree(const aValue: Boolean);
765 procedure SetFormat(const aValue: TglBitmapFormat);
766 procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
767 procedure SetID(const aValue: Cardinal);
768 procedure SetMipMap(const aValue: TglBitmapMipMap);
769 procedure SetTarget(const aValue: Cardinal);
770 procedure SetAnisotropic(const aValue: Integer);
771 procedure SetInternalFormat(const aValue: TglBitmapInternalFormat);
774 {$IFDEF GLB_SUPPORT_PNG_READ}
775 function LoadPNG(Stream: TStream): Boolean; virtual;
777 {$IFDEF GLB_SUPPORT_JPEG_READ}
778 function LoadJPEG(Stream: TStream): Boolean; virtual;
780 function LoadDDS(Stream: TStream): Boolean; virtual;
781 function LoadTGA(Stream: TStream): Boolean; virtual;
782 function LoadBMP(Stream: TStream): Boolean; virtual;
785 {$IFDEF GLB_SUPPORT_PNG_WRITE}
786 procedure SavePNG(Stream: TStream); virtual;
788 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
789 procedure SaveJPEG(Stream: TStream); virtual;
791 procedure SaveDDS(Stream: TStream); virtual;
792 procedure SaveTGA(Stream: TStream); virtual;
793 procedure SaveBMP(Stream: TStream); virtual;
796 procedure SetupParameters(var BuildWithGlu: Boolean);
797 procedure SelectFormat(DataFormat: TglBitmapInternalFormat; var glFormat, glInternalFormat, glType: Cardinal; CanConvertImage: Boolean = True);
799 procedure SetDataPointer(NewData: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); virtual;
800 procedure GenTexture(TestTextureSize: Boolean = True); virtual; abstract;
802 function FlipHorz: Boolean; virtual;
803 function FlipVert: Boolean; virtual;
805 property Width: Integer read GetWidth;
806 property Height: Integer read GetHeight;
808 property ID: Cardinal read fID write SetID;
809 property Target: Cardinal read fTarget write SetTarget;
810 property Format: TglBitmapFormat read fFormat write SetFormat;
811 property InternalFormat: TglBitmapInternalFormat read fInternalFormat write SetInternalFormat;
812 property MipMap: TglBitmapMipMap read fMipMap write SetMipMap;
813 property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
815 property Filename: String read fFilename;
816 property CustomName: String read fCustomName write SetCustomName;
817 property CustomNameW: WideString read fCustomNameW write SetCustomNameW;
818 property CustomData: Pointer read fCustomData write SetCustomData;
820 property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree;
821 property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
823 property Dimension: TglBitmapPixelPosition read fDimension;
824 property Data: PByte read fData;
825 property IsResident: Boolean read fIsResident;
827 procedure AfterConstruction; override;
828 procedure BeforeDestruction; override;
831 procedure LoadFromFile(const aFileName: String);
832 procedure LoadFromStream(const aStream: TStream); virtual;
833 procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
834 const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat;
835 const aArgs: PtrInt = 0);
837 procedure LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar = nil);
838 procedure LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar);
841 procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
842 procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
844 //function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer = nil): boolean; overload;
845 //function AddFunc(const aFunc: TglBitmapFunction; CreateTemp: Boolean; CustomData: Pointer = nil): boolean; overload;
848 function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
849 function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
850 function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
851 function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil;
852 const aArgs: PtrInt = 0): Boolean;
856 function AssignToBitmap(const aBitmap: TBitmap): Boolean;
857 function AssignFromBitmap(const aBitmap: TBitmap): Boolean;
858 function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
859 function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
860 const aArgs: PtrInt = 0): Boolean;
863 function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0): Boolean; virtual;
864 function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
865 function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
866 function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
868 function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil;
869 const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
870 function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
871 const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
874 function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
875 function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
876 function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
878 function AddAlphaFromValue(const aAlpha: Byte): Boolean;
879 function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
880 function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
882 function RemoveAlpha: Boolean; virtual;
883 function Clone: TglBitmap;
884 function ConvertTo(const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat): Boolean; virtual;
885 procedure SetBorderColor(Red, Green, Blue, Alpha: Single);
886 procedure Invert(const aUseRGB: Boolean = true; aUseAlpha: Boolean = false);
889 procedure FillWithColor(const aRed, aGreen, aBlue: aByte; Alpha: Byte = 255);
890 procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
891 procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
893 procedure SetFilter(const aMin, aMag: Cardinal);
895 const S: Cardinal = GL_CLAMP_TO_EDGE;
896 const T: Cardinal = GL_CLAMP_TO_EDGE;
897 const R: Cardinal = GL_CLAMP_TO_EDGE);
899 procedure GetPixel(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); virtual;
900 procedure SetPixel(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); virtual;
902 procedure Unbind(DisableTextureUnit: Boolean = True); virtual;
903 procedure Bind(EnableTextureUnit: Boolean = True); virtual;
905 constructor Create; overload;
906 constructor Create(FileName: String); overload;
907 constructor Create(Stream: TStream); overload;
909 constructor CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar = nil);
910 constructor Create(Instance: Cardinal; Resource: String; ResType: PChar = nil); overload;
911 constructor Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar); overload;
913 constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat); overload;
914 constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer = nil); overload;
918 TglBitmap2D = class(TglBitmap)
921 fLines: array of PByte;
923 procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
924 procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
925 procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
926 procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
927 procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
928 function GetScanline(Index: Integer): Pointer;
930 procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
932 procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override;
933 procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
937 property Scanline[Index: Integer]: Pointer read GetScanline;
939 procedure AfterConstruction; override;
941 procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat);
942 procedure GetDataFromTexture;
943 procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3; const aScale: Single = 2; const aUseAlpha: Boolean = False);
944 procedure GenTexture(TestTextureSize: Boolean = True); override;
946 function FlipHorz: Boolean; override;
947 function FlipVert: Boolean; override;
951 TglBitmapCubeMap = class(TglBitmap2D)
956 procedure GenTexture(TestTextureSize: Boolean = True); reintroduce;
958 procedure AfterConstruction; override;
960 procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true);
962 procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = True); reintroduce; virtual;
963 procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = True); reintroduce; virtual;
967 TglBitmapNormalMap = class(TglBitmapCubeMap)
969 procedure AfterConstruction; override;
971 procedure GenerateNormalMap(Size: Integer = 32; TestTextureSize: Boolean = true);
975 TglBitmap1D = class(TglBitmap)
977 procedure GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
979 procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override;
980 procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
985 procedure AfterConstruction; override;
988 function FlipHorz: Boolean; override;
991 procedure GenTexture(TestTextureSize: Boolean = True); override;
995 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
996 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
997 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
998 procedure glBitmapSetDefaultInternalFormat(const aInternalFormat: TglBitmapInternalFormat);
999 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
1000 procedure glBitmapSetDefaultWrap(
1001 const S: Cardinal = GL_CLAMP_TO_EDGE;
1002 const T: Cardinal = GL_CLAMP_TO_EDGE;
1003 const R: Cardinal = GL_CLAMP_TO_EDGE);
1005 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
1006 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
1007 function glBitmapGetDefaultFormat: TglBitmapFormat;
1008 function glBitmapGetDefaultInternalFormat: TglBitmapInternalFormat;
1009 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
1010 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
1013 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
1016 function FormatGetSize(Format: TglBitmapInternalFormat): Single;
1017 function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
1018 function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
1019 function FormatIsEmpty(Format: TglBitmapInternalFormat): boolean;
1020 function FormatHasAlpha(Format: TglBitmapInternalFormat): Boolean;
1021 procedure FormatPreparePixel(var Pixel: TglBitmapPixelData; Format: TglBitmapInternalFormat);
1022 function FormatGetWithoutAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
1023 function FormatGetWithAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
1024 function FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; Format: TglBitmapInternalFormat): boolean;
1028 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
1029 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
1030 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
1034 glBitmapDefaultDeleteTextureOnFree: Boolean;
1035 glBitmapDefaultFreeDataAfterGenTextures: Boolean;
1036 glBitmapDefaultFormat: TglBitmapFormat;
1037 glBitmapDefaultInternalFormat: TglBitmapInternalFormat;
1038 glBitmapDefaultFilterMin: Cardinal;
1039 glBitmapDefaultFilterMag: Cardinal;
1040 glBitmapDefaultWrapS: Cardinal;
1041 glBitmapDefaultWrapT: Cardinal;
1042 glBitmapDefaultWrapR: Cardinal;
1045 function CreateGrayPalette: HPALETTE;
1054 {$IFNDEF GLB_NO_NATIVE_GL}
1055 procedure ReadOpenGLExtensions;
1061 MajorVersion, MinorVersion: Integer;
1064 procedure TrimVersionString(Buffer: AnsiString; var Major, Minor: Integer);
1071 Separator := Pos(AnsiString('.'), Buffer);
1073 if (Separator > 1) and (Separator < Length(Buffer)) and
1074 (Buffer[Separator - 1] in ['0'..'9']) and
1075 (Buffer[Separator + 1] in ['0'..'9']) then begin
1078 while (Separator > 0) and (Buffer[Separator] in ['0'..'9']) do
1081 Delete(Buffer, 1, Separator);
1082 Separator := Pos(AnsiString('.'), Buffer) + 1;
1084 while (Separator <= Length(Buffer)) and (AnsiChar(Buffer[Separator]) in ['0'..'9']) do
1087 Delete(Buffer, Separator, 255);
1088 Separator := Pos(AnsiString('.'), Buffer);
1090 Major := StrToInt(Copy(String(Buffer), 1, Separator - 1));
1091 Minor := StrToInt(Copy(String(Buffer), Separator + 1, 1));
1096 function CheckExtension(const Extension: AnsiString): Boolean;
1100 ExtPos := Pos(Extension, Buffer);
1101 Result := ExtPos > 0;
1104 Result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
1108 function glLoad (aFunc: pAnsiChar): pointer;
1111 Result := glXGetProcAddress(aFunc);
1113 Result := wglGetProcAddress(aFunc);
1120 Context := wglGetCurrentContext;
1122 if Context <> gLastContext then begin
1123 gLastContext := Context;
1127 Buffer := glGetString(GL_VERSION);
1128 TrimVersionString(Buffer, MajorVersion, MinorVersion);
1130 GL_VERSION_1_2 := False;
1131 GL_VERSION_1_3 := False;
1132 GL_VERSION_1_4 := False;
1133 GL_VERSION_2_0 := False;
1135 if MajorVersion = 1 then begin
1136 if MinorVersion >= 1 then begin
1137 if MinorVersion >= 2 then
1138 GL_VERSION_1_2 := True;
1140 if MinorVersion >= 3 then
1141 GL_VERSION_1_3 := True;
1143 if MinorVersion >= 4 then
1144 GL_VERSION_1_4 := True;
1148 if MajorVersion >= 2 then begin
1149 GL_VERSION_1_2 := True;
1150 GL_VERSION_1_3 := True;
1151 GL_VERSION_1_4 := True;
1152 GL_VERSION_2_0 := True;
1156 Buffer := glGetString(GL_EXTENSIONS);
1157 GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
1158 GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
1159 GL_ARB_texture_compression := CheckExtension('GL_ARB_texture_compression');
1160 GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
1161 GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
1162 GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
1163 GL_EXT_bgra := CheckExtension('GL_EXT_bgra');
1164 GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
1165 GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
1166 GL_EXT_texture_compression_s3tc := CheckExtension('GL_EXT_texture_compression_s3tc');
1167 GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
1168 GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
1169 GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
1170 GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
1171 GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
1174 if GL_VERSION_1_3 then begin
1176 glCompressedTexImage1D := glLoad('glCompressedTexImage1D');
1177 glCompressedTexImage2D := glLoad('glCompressedTexImage2D');
1178 glGetCompressedTexImage := glLoad('glGetCompressedTexImage');
1182 // Try loading Extension
1183 glCompressedTexImage1D := glLoad('glCompressedTexImage1DARB');
1184 glCompressedTexImage2D := glLoad('glCompressedTexImage2DARB');
1185 glGetCompressedTexImage := glLoad('glGetCompressedTexImageARB');
1194 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1195 function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
1197 Result.Fields := [];
1200 Result.Fields := Result.Fields + [ffX];
1202 Result.Fields := Result.Fields + [ffY];
1204 Result.X := Max(0, X);
1205 Result.Y := Max(0, Y);
1210 LUMINANCE_WEIGHT_R = 0.30;
1211 LUMINANCE_WEIGHT_G = 0.59;
1212 LUMINANCE_WEIGHT_B = 0.11;
1213 UNSUPPORTED_INTERNAL_FORMAT = 'the given format isn''t supported by this function.';
1215 {$REGION PixelDescription}
1217 //ifAlpha4////////////////////////////////////////////////////////////////////////////////////////
1218 PIXEL_DESC_ALPHA4: TglBitmapPixelDesc = (
1219 RedRange: $00000000; RedShift: 0;
1220 GreenRange: $00000000; GreenShift: 0;
1221 BlueRange: $00000000; BlueShift: 0;
1222 AlphaRange: $0000000F; AlphaShift: 0);
1225 PIXEL_DESC_ALPHA8: TglBitmapPixelDesc = (
1226 RedRange: $00000000; RedShift: 0;
1227 GreenRange: $00000000; GreenShift: 0;
1228 BlueRange: $00000000; BlueShift: 0;
1229 AlphaRange: $000000FF; AlphaShift: 0);
1232 PIXEL_DESC_ALPHA12: TglBitmapPixelDesc = (
1233 RedRange: $00000000; RedShift: 0;
1234 GreenRange: $00000000; GreenShift: 0;
1235 BlueRange: $00000000; BlueShift: 0;
1236 AlphaRange: $00000FFF; AlphaShift: 0);
1239 PIXEL_DESC_ALPHA16: TglBitmapPixelDesc = (
1240 RedRange: $00000000; RedShift: 0;
1241 GreenRange: $00000000; GreenShift: 0;
1242 BlueRange: $00000000; BlueShift: 0;
1243 AlphaRange: $0000FFFF; AlphaShift: 0);
1245 //ifLuminance4////////////////////////////////////////////////////////////////////////////////////
1246 PIXEL_DESC_LUMINANCE4: TglBitmapPixelDesc = (
1247 RedRange: $0000000F; RedShift: 0;
1248 GreenRange: $0000000F; GreenShift: 0;
1249 BlueRange: $0000000F; BlueShift: 0;
1250 AlphaRange: $00000000; AlphaShift: 0);
1253 PIXEL_DESC_LUMINANCE8: TglBitmapPixelDesc = (
1254 RedRange: $000000FF; RedShift: 0;
1255 GreenRange: $000000FF; GreenShift: 0;
1256 BlueRange: $000000FF; BlueShift: 0;
1257 AlphaRange: $00000000; AlphaShift: 0);
1260 PIXEL_DESC_LUMINANCE12: TglBitmapPixelDesc = (
1261 RedRange: $00000FFF; RedShift: 0;
1262 GreenRange: $00000FFF; GreenShift: 0;
1263 BlueRange: $00000FFF; BlueShift: 0;
1264 AlphaRange: $00000000; AlphaShift: 0);
1267 PIXEL_DESC_LUMINANCE16: TglBitmapPixelDesc = (
1268 RedRange: $0000FFFF; RedShift: 0;
1269 GreenRange: $0000FFFF; GreenShift: 0;
1270 BlueRange: $0000FFFF; BlueShift: 0;
1271 AlphaRange: $00000000; AlphaShift: 0);
1273 //ifLuminance4Alpha4//////////////////////////////////////////////////////////////////////////////
1274 PIXEL_DESC_LUMINANCE4_ALPHA4: TglBitmapPixelDesc = (
1275 RedRange: $0000000F; RedShift: 0;
1276 GreenRange: $0000000F; GreenShift: 0;
1277 BlueRange: $0000000F; BlueShift: 0;
1278 AlphaRange: $0000000F; AlphaShift: 4);
1279 //ifLuminance6Alpha2
1280 PIXEL_DESC_LUMINANCE6_ALPHA2: TglBitmapPixelDesc = (
1281 RedRange: $0000003F; RedShift: 0;
1282 GreenRange: $0000003F; GreenShift: 0;
1283 BlueRange: $0000003F; BlueShift: 0;
1284 AlphaRange: $00000003; AlphaShift: 6);
1286 //ifLuminance8Alpha8
1287 PIXEL_DESC_LUMINANCE8_ALPHA8: TglBitmapPixelDesc = (
1288 RedRange: $000000FF; RedShift: 0;
1289 GreenRange: $000000FF; GreenShift: 0;
1290 BlueRange: $000000FF; BlueShift: 0;
1291 AlphaRange: $000000FF; AlphaShift: 8);
1293 //ifLuminance12Alpha4
1294 PIXEL_DESC_LUMINANCE12_ALPHA4: TglBitmapPixelDesc = (
1295 RedRange: $00000FFF; RedShift: 0;
1296 GreenRange: $00000FFF; GreenShift: 0;
1297 BlueRange: $00000FFF; BlueShift: 0;
1298 AlphaRange: $0000000F; AlphaShift: 12);
1300 //ifLuminance12Alpha12
1301 PIXEL_DESC_LUMINANCE12_ALPHA12: TglBitmapPixelDesc = (
1302 RedRange: $00000FFF; RedShift: 0;
1303 GreenRange: $00000FFF; GreenShift: 0;
1304 BlueRange: $00000FFF; BlueShift: 0;
1305 AlphaRange: $00000FFF; AlphaShift: 12);
1307 //ifLuminance16Alpha16
1308 PIXEL_DESC_LUMINANCE16_ALPHA16: TglBitmapPixelDesc = (
1309 RedRange: $0000FFFF; RedShift: 0;
1310 GreenRange: $0000FFFF; GreenShift: 0;
1311 BlueRange: $0000FFFF; BlueShift: 0;
1312 AlphaRange: $0000FFFF; AlphaShift: 16);
1314 //ifR3G3B2////////////////////////////////////////////////////////////////////////////////////////
1315 PIXEL_DESC_R3_G3_B2: TglBitmapPixelDesc = (
1316 RedRange: $00000007; RedShift: 0;
1317 GreenRange: $00000007; GreenShift: 3;
1318 BlueRange: $00000003; BlueShift: 6;
1319 AlphaRange: $00000000; AlphaShift: 0);
1322 PIXEL_DESC_RGB4: TglBitmapPixelDesc = (
1323 RedRange: $0000000F; RedShift: 0;
1324 GreenRange: $0000000F; GreenShift: 4;
1325 BlueRange: $0000000F; BlueShift: 8;
1326 AlphaRange: $00000000; AlphaShift: 0);
1329 PIXEL_DESC_RGB5: TglBitmapPixelDesc = (
1330 RedRange: $0000001F; RedShift: 0;
1331 GreenRange: $0000001F; GreenShift: 5;
1332 BlueRange: $0000001F; BlueShift: 10;
1333 AlphaRange: $00000000; AlphaShift: 0);
1336 PIXEL_DESC_RGB8: TglBitmapPixelDesc = (
1337 RedRange: $000000FF; RedShift: 0;
1338 GreenRange: $000000FF; GreenShift: 8;
1339 BlueRange: $000000FF; BlueShift: 16;
1340 AlphaRange: $00000000; AlphaShift: 0);
1343 PIXEL_DESC_RGB10: TglBitmapPixelDesc = (
1344 RedRange: $000003FF; RedShift: 0;
1345 GreenRange: $000003FF; GreenShift: 10;
1346 BlueRange: $000003FF; BlueShift: 20;
1347 AlphaRange: $000003FF; AlphaShift: 0);
1350 PIXEL_DESC_RGB12: TglBitmapPixelDesc = (
1351 RedRange: $00000000; RedShift: 0;
1352 GreenRange: $00000000; GreenShift: 0;
1353 BlueRange: $00000000; BlueShift: 0;
1354 AlphaRange: $00000000; AlphaShift: 0);
1357 PIXEL_DESC_RGB16: TglBitmapPixelDesc = (
1358 RedRange: $0000FFFF; RedShift: 0;
1359 GreenRange: $0000FFFF; GreenShift: 16;
1360 BlueRange: $0000FFFF; BlueShift: 32;
1361 AlphaRange: $0000FFFF; AlphaShift: 0);
1363 //ifRGBA2/////////////////////////////////////////////////////////////////////////////////////////
1364 PIXEL_DESC_RGBA2: TglBitmapPixelDesc = (
1365 RedRange: $00000003; RedShift: 0;
1366 GreenRange: $00000003; GreenShift: 2;
1367 BlueRange: $00000003; BlueShift: 4;
1368 AlphaRange: $00000003; AlphaShift: 6);
1371 PIXEL_DESC_RGBA4: TglBitmapPixelDesc = (
1372 RedRange: $0000000F; RedShift: 0;
1373 GreenRange: $0000000F; GreenShift: 4;
1374 BlueRange: $0000000F; BlueShift: 8;
1375 AlphaRange: $0000000F; AlphaShift: 12);
1378 PIXEL_DESC_RGB5_A1: TglBitmapPixelDesc = (
1379 RedRange: $0000001F; RedShift: 0;
1380 GreenRange: $0000001F; GreenShift: 5;
1381 BlueRange: $0000001F; BlueShift: 10;
1382 AlphaRange: $00000001; AlphaShift: 11);
1385 PIXEL_DESC_RGBA8: TglBitmapPixelDesc = (
1386 RedRange: $000000FF; RedShift: 0;
1387 GreenRange: $000000FF; GreenShift: 8;
1388 BlueRange: $000000FF; BlueShift: 16;
1389 AlphaRange: $000000FF; AlphaShift: 24);
1392 PIXEL_DESC_RGB10_A2: TglBitmapPixelDesc = (
1393 RedRange: $000003FF; RedShift: 0;
1394 GreenRange: $000003FF; GreenShift: 10;
1395 BlueRange: $000003FF; BlueShift: 20;
1396 AlphaRange: $00000003; AlphaShift: 22);
1399 PIXEL_DESC_RGBA12: TglBitmapPixelDesc = (
1400 RedRange: $00000FFF; RedShift: 0;
1401 GreenRange: $00000FFF; GreenShift: 12;
1402 BlueRange: $00000FFF; BlueShift: 24;
1403 AlphaRange: $00000FFF; AlphaShift: 36);
1406 PIXEL_DESC_RGBA16: TglBitmapPixelDesc = (
1407 RedRange: $0000FFFF; RedShift: 0;
1408 GreenRange: $0000FFFF; GreenShift: 16;
1409 BlueRange: $0000FFFF; BlueShift: 32;
1410 AlphaRange: $0000FFFF; AlphaShift: 48);
1412 //ifDepthComponent16//////////////////////////////////////////////////////////////////////////////
1413 PIXEL_DESC_DEPTH16: TglBitmapPixelDesc = (
1414 RedRange: $0000FFFF; RedShift: 0;
1415 GreenRange: $0000FFFF; GreenShift: 0;
1416 BlueRange: $0000FFFF; BlueShift: 0;
1417 AlphaRange: $0000FFFF; AlphaShift: 0);
1419 //ifDepthComponent24
1420 PIXEL_DESC_DEPTH24: TglBitmapPixelDesc = (
1421 RedRange: $00FFFFFF; RedShift: 0;
1422 GreenRange: $00FFFFFF; GreenShift: 0;
1423 BlueRange: $00FFFFFF; BlueShift: 0;
1424 AlphaRange: $00FFFFFF; AlphaShift: 0);
1426 //ifDepthComponent32
1427 PIXEL_DESC_DEPTH32: TglBitmapPixelDesc = (
1428 RedRange: $FFFFFFFF; RedShift: 0;
1429 GreenRange: $FFFFFFFF; GreenShift: 0;
1430 BlueRange: $FFFFFFFF; BlueShift: 0;
1431 AlphaRange: $00000000; AlphaShift: 0);
1434 {$REGION MapFunctions}
1435 //ALPHA/////////////////////////////////////////////////////////////////////////////////////////////
1436 procedure MapAlpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1441 procedure MapAlpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1443 aData^ := aPixel.Alpha;
1447 procedure MapAlpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1452 procedure MapAlpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1454 PWord(aData)^ := aPixel.Alpha;
1458 //LUMINANCE/////////////////////////////////////////////////////////////////////////////////////////
1459 procedure MapLuminance4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1464 procedure MapLuminance8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1467 aPixel.Red * LUMINANCE_WEIGHT_R +
1468 aPixel.Green * LUMINANCE_WEIGHT_G +
1469 aPixel.Blue * LUMINANCE_WEIGHT_B);
1473 procedure MapLuminance12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1478 procedure MapLuminance16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1480 PWord(aData)^ := Trunc(
1481 aPixel.Red * LUMINANCE_WEIGHT_R +
1482 aPixel.Green * LUMINANCE_WEIGHT_G +
1483 aPixel.Blue * LUMINANCE_WEIGHT_B);
1487 //LUMINANCE_ALPHA///////////////////////////////////////////////////////////////////////////////////
1488 procedure MapLuminance4Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1491 ((Trunc(aPixel.Red * LUMINANCE_WEIGHT_R +
1492 aPixel.Green * LUMINANCE_WEIGHT_G +
1493 aPixel.Blue * LUMINANCE_WEIGHT_B) and
1494 aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
1495 ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift;
1499 procedure MapLuminance6Alpha2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1501 MapLuminance4Alpha4(aPixel, aData, aBitOffset);
1504 procedure MapLuminance8Alpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1507 ((Trunc(aPixel.Red * LUMINANCE_WEIGHT_R +
1508 aPixel.Green * LUMINANCE_WEIGHT_G +
1509 aPixel.Blue * LUMINANCE_WEIGHT_B) and
1510 aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
1511 ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift;
1515 procedure MapLuminance12Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1517 MapLuminance8Alpha8(aPixel, aData, aBitOffset);
1520 procedure MapLuminance12Alpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1525 procedure MapLuminance16Alpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1527 PCardinal(aData)^ :=
1528 ((Trunc(aPixel.Red * LUMINANCE_WEIGHT_R +
1529 aPixel.Green * LUMINANCE_WEIGHT_G +
1530 aPixel.Blue * LUMINANCE_WEIGHT_B) and
1531 aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
1532 ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift;
1536 //RGB///////////////////////////////////////////////////////////////////////////////////////////////
1537 procedure MapR3G3B2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1540 ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
1541 ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
1542 ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift);
1546 procedure MapRGB4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1551 procedure MapRGB5(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1556 procedure MapRGB8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1558 PCardinal(aData)^ :=
1559 ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
1560 ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
1561 ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift);
1565 procedure MapRGB10(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1570 procedure MapRGB12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1575 procedure MapRGB16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1577 PWord(aData)^ := aPixel.Red;
1579 PWord(aData)^ := aPixel.Green;
1581 PWord(aData)^ := aPixel.Blue;
1585 //RGBA//////////////////////////////////////////////////////////////////////////////////////////////
1586 procedure MapRGBA2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1589 ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
1590 ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
1591 ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or
1592 ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift);
1596 procedure MapRGBA4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1599 ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
1600 ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
1601 ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or
1602 ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift);
1606 procedure MapRGB5A1(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1609 ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
1610 ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
1611 ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or
1612 ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift);
1616 procedure MapRGBA8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1618 PCardinal(aData)^ :=
1619 ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
1620 ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
1621 ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or
1622 ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift);
1626 procedure MapRGB10A2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1628 PCardinal(aData)^ :=
1629 ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
1630 ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
1631 ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or
1632 ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift);
1636 procedure MapRGBA12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1641 procedure MapRGBA16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1643 PWord(aData)^ := aPixel.Red;
1645 PWord(aData)^ := aPixel.Green;
1647 PWord(aData)^ := aPixel.Blue;
1649 PWord(aData)^ := aPixel.Alpha;
1653 //DEPTH/////////////////////////////////////////////////////////////////////////////////////////////
1654 procedure MapDepth16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1656 PWord(aData)^ := (aPixel.Red + aPixel.Green + aPixel.Blue) div 3;
1660 procedure MapDepth24(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1665 procedure MapDepth32(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1667 PCardinal(aData)^ := (aPixel.Red + aPixel.Green + aPixel.Blue) div 3;
1671 function FormatGetMapFunc(const aInternalFormat: TglBitmapInternalFormat): TglBitmapMapFunc;
1673 case aInternalFormat of
1674 ifAlpha4: result := MapAlpha4;
1675 ifAlpha8: result := MapAlpha8;
1676 ifAlpha12: result := MapAlpha12;
1677 ifAlpha16: result := MapAlpha16;
1679 ifLuminance4: result := MapLuminance4;
1680 ifLuminance8: result := MapLuminance8;
1681 ifLuminance12: result := MapLuminance8;
1682 ifLuminance16: result := MapLuminance8;
1684 ifLuminance4Alpha4: result := MapLuminance4Alpha4;
1685 ifLuminance6Alpha2: result := MapLuminance6Alpha2;
1686 ifLuminance8Alpha8: result := MapLuminance8Alpha8;
1687 ifLuminance12Alpha4: result := MapLuminance12Alpha4;
1688 ifLuminance12Alpha12: result := MapLuminance12Alpha12;
1689 ifLuminance16Alpha16: result := MapLuminance16Alpha16;
1691 ifR3G3B2: result := MapR3G3B2;
1692 ifRGB4: result := MapRGB4;
1693 ifRGB5: result := MapRGB5;
1694 ifRGB8: result := MapRGB8;
1695 ifRGB10: result := MapRGB10;
1696 ifRGB12: result := MapRGB12;
1697 ifRGB16: result := MapRGB16;
1699 ifRGBA2: result := MapRGBA2;
1700 ifRGBA4: result := MapRGBA4;
1701 ifRGB5A1: result := MapRGB5A1;
1702 ifRGBA8: result := MapRGBA8;
1703 ifRGB10A2: result := MapRGB10A2;
1704 ifRGBA12: result := MapRGBA12;
1705 ifRGBA16: result := MapRGBA16;
1707 ifDepth16: result := MapDepth16;
1708 ifDepth24: result := MapDepth24;
1709 ifDepth32: result := MapDepth32;
1711 raise EglBitmapUnsupportedInternalFormat.Create('FormatGetMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT);
1716 {$REGION UnmapFunctions}
1717 //ALPHA/////////////////////////////////////////////////////////////////////////////////////////////
1718 procedure UnmapAlpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1723 procedure UnmapAlpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1728 procedure UnmapAlpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1733 procedure UnmapAlpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1738 //LUMINANCE/////////////////////////////////////////////////////////////////////////////////////////
1739 procedure UnmapLuminance4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1744 procedure UnmapLuminance8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1749 procedure UnmapLuminance12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1754 procedure UnmapLuminance16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1759 //LUMINANCE_ALPHA///////////////////////////////////////////////////////////////////////////////////
1760 procedure UnmapLuminance4Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1765 procedure UnmapLuminance6Alpha2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1770 procedure UnmapLuminance8Alpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1775 procedure UnmapLuminance12Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1780 procedure UnmapLuminance12Alpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1785 procedure UnmapLuminance16Alpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1790 //RGB///////////////////////////////////////////////////////////////////////////////////////////////
1791 procedure UnmapR3G3B2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1796 procedure UnmapRGB4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1801 procedure UnmapRGB5(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1806 procedure UnmapRGB8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1811 procedure UnmapRGB10(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1816 procedure UnmapRGB12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1821 procedure UnmapRGB16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1826 //RGBA//////////////////////////////////////////////////////////////////////////////////////////////
1827 procedure UnmapRGBA2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1832 procedure UnmapRGBA4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1837 procedure UnmapRGB5A1(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1842 procedure UnmapRGBA8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1847 procedure UnmapRGB10A2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1852 procedure UnmapRGBA12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1857 procedure UnmapRGBA16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1862 //DEPTH/////////////////////////////////////////////////////////////////////////////////////////////
1863 procedure UnmapDepth16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1868 procedure UnmapDepth24(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1873 procedure UnmapDepth32(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
1881 procedure UnMapAlpha(var pData: pByte; var Pixel: TglBitmapPixelData);
1883 Pixel.Alpha := pData^;
1884 Pixel.Red := Pixel.PixelDesc.RedRange;
1885 Pixel.Green := Pixel.PixelDesc.GreenRange;
1886 Pixel.Blue := Pixel.PixelDesc.BlueRange;
1892 procedure UnMapLuminance(var pData: pByte; var Pixel: TglBitmapPixelData);
1895 Pixel.Red := pData^;
1896 Pixel.Green := pData^;
1897 Pixel.Blue := pData^;
1903 procedure UnMapDepth8(var pData: pByte; var Pixel: TglBitmapPixelData);
1906 Pixel.Red := pData^;
1907 Pixel.Green := pData^;
1908 Pixel.Blue := pData^;
1914 procedure UnMapLuminanceAlpha(var pData: pByte; var Pixel: TglBitmapPixelData);
1916 Pixel.Red := pData^;
1917 Pixel.Green := pData^;
1918 Pixel.Blue := pData^;
1921 Pixel.Alpha := pData^;
1926 procedure UnMapRGBA4(var pData: pByte; var Pixel: TglBitmapPixelData);
1930 Temp := pWord(pData)^;
1932 Pixel.Alpha := Temp shr PIXEL_DESC_RGBA4.AlphaShift and PIXEL_DESC_RGBA4.AlphaRange;
1933 Pixel.Red := Temp shr PIXEL_DESC_RGBA4.RedShift and PIXEL_DESC_RGBA4.RedRange;
1934 Pixel.Green := Temp shr PIXEL_DESC_RGBA4.GreenShift and PIXEL_DESC_RGBA4.GreenRange;
1935 Pixel.Blue := Temp and PIXEL_DESC_RGBA4.BlueRange;
1941 procedure UnMapR5G6B5(var pData: pByte; var Pixel: TglBitmapPixelData);
1945 Temp := pWord(pData)^;
1947 Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
1948 Pixel.Red := Temp shr PIXEL_DESC_R5G6B5.RedShift and PIXEL_DESC_R5G6B5.RedRange;
1949 Pixel.Green := Temp shr PIXEL_DESC_R5G6B5.GreenShift and PIXEL_DESC_R5G6B5.GreenRange;
1950 Pixel.Blue := Temp and PIXEL_DESC_R5G6B5.BlueRange;
1956 procedure UnMapRGB5A1(var pData: pByte; var Pixel: TglBitmapPixelData);
1960 Temp := pWord(pData)^;
1962 Pixel.Alpha := Temp shr PIXEL_DESC_RGB5A1.AlphaShift and PIXEL_DESC_RGB5A1.AlphaRange;
1963 Pixel.Red := Temp shr PIXEL_DESC_RGB5A1.RedShift and PIXEL_DESC_RGB5A1.RedRange;
1964 Pixel.Green := Temp shr PIXEL_DESC_RGB5A1.GreenShift and PIXEL_DESC_RGB5A1.GreenRange;
1965 Pixel.Blue := Temp and PIXEL_DESC_RGB5A1.BlueRange;
1971 procedure UnMapRGB8(var pData: pByte; var Pixel: TglBitmapPixelData);
1973 Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
1975 Pixel.Red := pData^;
1978 Pixel.Green := pData^;
1981 Pixel.Blue := pData^;
1986 procedure UnMapBGR8(var pData: pByte; var Pixel: TglBitmapPixelData);
1988 Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
1990 Pixel.Blue := pData^;
1993 Pixel.Green := pData^;
1996 Pixel.Red := pData^;
2001 procedure UnMapRGBA8(var pData: pByte; var Pixel: TglBitmapPixelData);
2003 Pixel.Red := pData^;
2006 Pixel.Green := pData^;
2009 Pixel.Blue := pData^;
2012 Pixel.Alpha := pData^;
2017 procedure UnMapBGRA8(var pData: pByte; var Pixel: TglBitmapPixelData);
2019 Pixel.Blue := pData^;
2022 Pixel.Green := pData^;
2025 Pixel.Red := pData^;
2028 Pixel.Alpha := pData^;
2033 procedure UnMapRGB10A2(var pData: pByte; var Pixel: TglBitmapPixelData);
2037 Temp := pDWord(pData)^;
2039 Pixel.Alpha := Temp shr PIXEL_DESC_RGB10A2.AlphaShift and PIXEL_DESC_RGB10A2.AlphaRange;
2040 Pixel.Red := Temp shr PIXEL_DESC_RGB10A2.RedShift and PIXEL_DESC_RGB10A2.RedRange;
2041 Pixel.Green := Temp shr PIXEL_DESC_RGB10A2.GreenShift and PIXEL_DESC_RGB10A2.GreenRange;
2042 Pixel.Blue := Temp and PIXEL_DESC_RGB10A2.BlueRange;
2048 function FormatGetUnMapFunc(const aInternalFormat: TglBitmapInternalFormat): TglBitmapUnMapFunc;
2050 case aInternalFormat of
2051 ifAlpha4: result := UnmapAlpha4;
2052 ifAlpha8: result := UnmapAlpha8;
2053 ifAlpha12: result := UnmapAlpha12;
2054 ifAlpha16: result := UnmapAlpha16;
2056 ifLuminance4: result := UnmapLuminance4;
2057 ifLuminance8: result := UnmapLuminance8;
2058 ifLuminance12: result := UnmapLuminance8;
2059 ifLuminance16: result := UnmapLuminance8;
2061 ifLuminance4Alpha4: result := UnmapLuminance4Alpha4;
2062 ifLuminance6Alpha2: result := UnmapLuminance6Alpha2;
2063 ifLuminance8Alpha8: result := UnmapLuminance8Alpha8;
2064 ifLuminance12Alpha4: result := UnmapLuminance12Alpha4;
2065 ifLuminance12Alpha12: result := UnmapLuminance12Alpha12;
2066 ifLuminance16Alpha16: result := UnmapLuminance16Alpha16;
2068 ifR3G3B2: result := UnmapR3G3B2;
2069 ifRGB4: result := UnmapRGB4;
2070 ifRGB5: result := UnmapRGB5;
2071 ifRGB8: result := UnmapRGB8;
2072 ifRGB10: result := UnmapRGB10;
2073 ifRGB12: result := UnmapRGB12;
2074 ifRGB16: result := UnmapRGB16;
2076 ifRGBA2: result := UnmapRGBA2;
2077 ifRGBA4: result := UnmapRGBA4;
2078 ifRGB5A1: result := UnmapRGB5A1;
2079 ifRGBA8: result := UnmapRGBA8;
2080 ifRGB10A2: result := UnmapRGB10A2;
2081 ifRGBA12: result := UnmapRGBA12;
2082 ifRGBA16: result := UnmapRGBA16;
2084 ifDepth16: result := UnmapDepth16;
2085 ifDepth24: result := UnmapDepth24;
2086 ifDepth32: result := UnmapDepth32;
2088 raise EglBitmapUnsupportedInternalFormat.Create('FormatGetMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT);
2096 function FormatGetSize (Format: TglBitmapInternalFormat): Single;
2103 ifAlpha, ifLuminance, ifDepth8, ifDXT3, ifDXT5:
2105 ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5:
2109 ifBGRA8, ifRGBA8, ifRGB10A2:
2112 raise EglBitmapUnsupportedInternalFormat.Create('FormatGetSize - ' + UNSUPPORTED_INTERNAL_FORMAT);
2117 function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
2119 Result := Format in [ifDXT1, ifDXT3, ifDXT5];
2123 function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
2125 Result := Format in [ifAlpha, ifLuminance, ifDepth8, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5, ifBGR8, ifRGB8, ifBGRA8, ifRGBA8, ifRGB10A2];
2129 function FormatIsEmpty(Format: TglBitmapInternalFormat): boolean;
2131 Result := Format = ifEmpty;
2135 function FormatHasAlpha(Format: TglBitmapInternalFormat): Boolean;
2137 Result := Format in [ifDXT1, ifDXT3, ifDXT5 ,ifAlpha, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifBGRA8, ifRGBA8, ifRGB10A2];
2141 procedure FormatPreparePixel(var Pixel: TglBitmapPixelData; Format: TglBitmapInternalFormat);
2143 FillChar(Pixel, SizeOf(Pixel), #0);
2147 Pixel.PixelDesc := PIXEL_DESC_ALPHA;
2149 Pixel.PixelDesc := PIXEL_DESC_LUMINANCE;
2151 Pixel.PixelDesc := PIXEL_DESC_DEPTH8;
2153 Pixel.PixelDesc := PIXEL_DESC_LUMINANCEALPHA;
2155 Pixel.PixelDesc := PIXEL_DESC_RGBA4;
2157 Pixel.PixelDesc := PIXEL_DESC_R5G6B5;
2159 Pixel.PixelDesc := PIXEL_DESC_RGB5A1;
2160 ifDXT1, ifDXT3, ifDXT5, ifBGRA8:
2161 Pixel.PixelDesc := PIXEL_DESC_BGRA8;
2163 Pixel.PixelDesc := PIXEL_DESC_BGR8;
2165 Pixel.PixelDesc := PIXEL_DESC_RGB8;
2167 Pixel.PixelDesc := PIXEL_DESC_RGBA8;
2169 Pixel.PixelDesc := PIXEL_DESC_RGB10A2;
2172 Pixel.Red := Pixel.PixelDesc.RedRange;
2173 Pixel.Green := Pixel.PixelDesc.GreenRange;
2174 Pixel.Blue := Pixel.PixelDesc.BlueRange;
2175 Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
2179 function FormatGetWithoutAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
2183 Result := ifLuminance;
2185 Result := ifLuminance;
2202 function FormatGetWithAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
2206 Result := ifLuminanceAlpha;
2219 function FormatGetUncompressed(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
2234 function FormatGetImageSize(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat): Integer;
2236 if (Size.X = 0) and (Size.Y = 0) then
2239 Result := Trunc(Max(Size.Y, 1) * Max(Size.X, 1) * FormatGetSize(Format));
2243 function FormatGetSupportedFiles(Format: TglBitmapInternalFormat): TglBitmapFileTypes;
2247 {$IFDEF GLB_SUPPORT_PNG_WRITE}
2248 if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifBGR8, ifBGRA8, ifRGB8, ifRGBA8] then
2249 Result := Result + [ftPNG];
2252 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
2253 if Format in [ifLuminance, ifAlpha, ifDepth8, ifRGB8, ifBGR8] then
2254 Result := Result + [ftJPEG];
2257 Result := Result + [ftDDS];
2259 if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifBGR8, ifRGB8, ifBGRA8, ifRGBA8] then
2260 Result := Result + [ftTGA];
2262 if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5, ifRGB8, ifBGR8, ifRGBA8, ifBGRA8, ifRGB10A2] then
2263 Result := Result + [ftBMP];
2267 function FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; Format: TglBitmapInternalFormat): boolean;
2269 Pix: TglBitmapPixelData;
2273 if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) and (AlphaMask = 0) then
2274 raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
2276 FormatPreparePixel(Pix, Format);
2278 with Pix.PixelDesc do begin
2279 if RedMask <> 0 then
2280 if (RedMask <> (RedRange shl RedShift)) then
2283 if GreenMask <> 0 then
2284 if (GreenMask <> (GreenRange shl GreenShift)) then
2287 if BlueMask <> 0 then
2288 if (BlueMask <> (BlueRange shl BlueShift)) then
2291 if AlphaMask <> 0 then
2292 if (AlphaMask <> (AlphaRange shl AlphaShift)) then
2300 function IsPowerOfTwo(Number: Integer): Boolean;
2302 while Number and 1 = 0 do
2303 Number := Number shr 1;
2305 Result := Number = 1;
2309 function GetBitSize(BitSet: Cardinal): Integer;
2313 while BitSet > 0 do begin
2314 if (BitSet and $1) = 1 then
2317 BitSet := BitSet shr 1;
2322 procedure SwapRGB(pData: pByte; Width: Integer; HasAlpha: Boolean);
2325 TRGBPix = array [0..2] of byte;
2329 while Width > 0 do begin
2330 Temp := pRGBPIX(pData)^[0];
2331 pRGBPIX(pData)^[0] := pRGBPIX(pData)^[2];
2332 pRGBPIX(pData)^[2] := Temp;
2345 function CreateGrayPalette: HPALETTE;
2350 GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
2352 Pal.palVersion := $300;
2353 Pal.palNumEntries := 256;
2356 {$DEFINE GLB_TEMPRANGECHECK}
2360 for Idx := 0 to 256 - 1 do begin
2361 Pal.palPalEntry[Idx].peRed := Idx;
2362 Pal.palPalEntry[Idx].peGreen := Idx;
2363 Pal.palPalEntry[Idx].peBlue := Idx;
2364 Pal.palPalEntry[Idx].peFlags := 0;
2367 {$IFDEF GLB_TEMPRANGECHECK}
2368 {$UNDEF GLB_TEMPRANGECHECK}
2372 Result := CreatePalette(Pal^);
2379 {$IFDEF GLB_SDL_IMAGE}
2380 function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
2382 Result := TStream(context^.unknown.data1).Seek(offset, whence);
2386 function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
2388 Result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
2392 function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
2394 Result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
2398 function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
2404 function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
2406 Result := SDL_AllocRW;
2408 if Result = nil then
2409 raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
2411 Result^.seek := glBitmapRWseek;
2412 Result^.read := glBitmapRWread;
2413 Result^.write := glBitmapRWwrite;
2414 Result^.close := glBitmapRWclose;
2415 Result^.unknown.data1 := Stream;
2423 function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
2425 glBitmap: TglBitmap2D;
2431 if Instance = 0 then
2432 Instance := HInstance;
2434 if (LoadFromRes) then
2435 glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName)
2438 glBitmap := TglBitmap2D.Create(FileName);
2441 glBitmap.DeleteTextureOnFree := False;
2442 glBitmap.FreeDataAfterGenTexture := False;
2443 glBitmap.GenTexture(True);
2444 if (glBitmap.ID > 0) then begin
2445 Texture := glBitmap.ID;
2454 function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
2456 CM: TglBitmapCubeMap;
2461 if Instance = 0 then
2462 Instance := HInstance;
2465 CM := TglBitmapCubeMap.Create;
2467 CM.DeleteTextureOnFree := False;
2471 if (LoadFromRes) then
2472 CM.LoadFromResource(Instance, PositiveX)
2475 CM.LoadFromFile(PositiveX);
2476 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
2479 if (LoadFromRes) then
2480 CM.LoadFromResource(Instance, NegativeX)
2483 CM.LoadFromFile(NegativeX);
2484 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
2487 if (LoadFromRes) then
2488 CM.LoadFromResource(Instance, PositiveY)
2491 CM.LoadFromFile(PositiveY);
2492 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
2495 if (LoadFromRes) then
2496 CM.LoadFromResource(Instance, NegativeY)
2499 CM.LoadFromFile(NegativeY);
2500 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
2503 if (LoadFromRes) then
2504 CM.LoadFromResource(Instance, PositiveZ)
2507 CM.LoadFromFile(PositiveZ);
2508 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
2511 if (LoadFromRes) then
2512 CM.LoadFromResource(Instance, NegativeZ)
2515 CM.LoadFromFile(NegativeZ);
2516 CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
2526 function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
2528 NM: TglBitmapNormalMap;
2532 NM := TglBitmapNormalMap.Create;
2534 NM.DeleteTextureOnFree := False;
2535 NM.GenerateNormalMap(Size);
2545 procedure glBitmapSetDefaultFormat(Format: TglBitmapFormat);
2547 glBitmapDefaultFormat := Format;
2551 procedure glBitmapSetDefaultDeleteTextureOnFree(DeleteTextureOnFree: Boolean);
2553 glBitmapDefaultDeleteTextureOnFree := DeleteTextureOnFree;
2557 procedure glBitmapSetDefaultFilter(Min, Mag: Integer);
2559 glBitmapDefaultFilterMin := Min;
2560 glBitmapDefaultFilterMag := Mag;
2564 procedure glBitmapSetDefaultWrap(S: Integer; T: Integer; R: Integer);
2566 glBitmapDefaultWrapS := S;
2567 glBitmapDefaultWrapT := T;
2568 glBitmapDefaultWrapR := R;
2572 procedure glBitmapSetDefaultFreeDataAfterGenTexture(FreeData: Boolean);
2574 glBitmapDefaultFreeDataAfterGenTextures := FreeData;
2578 function glBitmapGetDefaultFormat: TglBitmapFormat;
2580 Result := glBitmapDefaultFormat;
2584 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
2586 Result := glBitmapDefaultDeleteTextureOnFree;
2590 procedure glBitmapGetDefaultFilter(var Min, Mag: Integer);
2592 Min := glBitmapDefaultFilterMin;
2593 Mag := glBitmapDefaultFilterMag;
2597 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Integer);
2599 S := glBitmapDefaultWrapS;
2600 T := glBitmapDefaultWrapT;
2601 R := glBitmapDefaultWrapR;
2605 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
2607 Result := glBitmapDefaultFreeDataAfterGenTextures;
2613 procedure TglBitmap.AfterConstruction;
2619 fMipMap := mmMipmap;
2620 fIsResident := False;
2623 fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
2624 fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
2626 fFormat := glBitmapGetDefaultFormat;
2628 glBitmapGetDefaultFilter(fFilterMin, fFilterMag);
2629 glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
2633 procedure TglBitmap.BeforeDestruction;
2635 SetDataPointer(nil, ifEmpty);
2637 if ((ID > 0) and (fDeleteTextureOnFree)) then
2638 glDeleteTextures(1, @ID);
2644 constructor TglBitmap.Create;
2646 {$IFNDEF GLB_NO_NATIVE_GL}
2647 ReadOpenGLExtensions;
2650 if (ClassType = TglBitmap) then
2651 raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
2657 constructor TglBitmap.Create(FileName: String);
2660 LoadFromFile(FileName);
2664 constructor TglBitmap.Create(Stream: TStream);
2667 LoadFromStream(Stream);
2672 constructor TglBitmap.CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar);
2675 LoadFromResource(Instance, Resource, ResType);
2679 constructor TglBitmap.Create(Instance: Cardinal; Resource: String; ResType: PChar);
2682 LoadFromResource(Instance, Resource, ResType);
2687 constructor TglBitmap.Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar);
2690 LoadFromResourceID(Instance, ResourceID, ResType);
2695 constructor TglBitmap.Create(Size: TglBitmapPixelPosition;
2696 Format: TglBitmapInternalFormat);
2703 ImageSize := FormatGetImageSize(Size, Format);
2704 GetMem(Image, ImageSize);
2706 FillChar(Image^, ImageSize, #$FF);
2708 SetDataPointer(Image, Format, Size.X, Size.Y);
2716 constructor TglBitmap.Create(Size: TglBitmapPixelPosition;
2717 Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer);
2720 LoadFromFunc(Size, Func, Format, CustomData);
2724 function TglBitmap.Clone: TglBitmap;
2730 Temp := ClassType.Create as TglBitmap;
2732 // copy texture data if assigned
2733 if Assigned(Data) then begin
2734 Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat);
2736 GetMem(TempPtr, Size);
2738 Move(Data^, TempPtr^, Size);
2739 Temp.SetDataPointer(TempPtr, InternalFormat, Width, Height);
2745 Temp.SetDataPointer(nil, InternalFormat, Width, Height);
2749 Temp.fTarget := Target;
2750 Temp.fFormat := Format;
2751 Temp.fMipMap := MipMap;
2752 Temp.fAnisotropic := Anisotropic;
2753 Temp.fBorderColor := fBorderColor;
2754 Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
2755 Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
2756 Temp.fFilterMin := fFilterMin;
2757 Temp.fFilterMag := fFilterMag;
2758 Temp.fWrapS := fWrapS;
2759 Temp.fWrapT := fWrapT;
2760 Temp.fWrapR := fWrapR;
2761 Temp.fFilename := fFilename;
2762 Temp.fCustomName := fCustomName;
2763 Temp.fCustomNameW := fCustomNameW;
2764 Temp.fCustomDataPointer := fCustomDataPointer;
2774 procedure TglBitmap.LoadFromFile(FileName: String);
2778 fFilename := FileName;
2780 FS := TFileStream.Create(FileName, fmOpenRead);
2791 procedure TglBitmap.LoadFromStream(Stream: TStream);
2793 {$IFDEF GLB_SUPPORT_PNG_READ}
2794 if not LoadPNG(Stream) then
2796 {$IFDEF GLB_SUPPORT_JPEG_READ}
2797 if not LoadJPEG(Stream) then
2799 if not LoadDDS(Stream) then
2800 if not LoadTGA(Stream) then
2801 if not LoadBMP(Stream) then
2802 raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
2807 procedure TglBitmap.LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar);
2809 RS: TResourceStream;
2814 if Assigned(ResType) then
2815 TempResType := ResType
2818 TempPos := Pos('.', Resource);
2819 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
2820 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
2821 TempResType := PChar(ResTypeStr);
2824 RS := TResourceStream.Create(Instance, Resource, TempResType);
2833 procedure TglBitmap.LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar);
2835 RS: TResourceStream;
2837 RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
2848 procedure TglBitmap.LoadFromFunc(Size: TglBitmapPixelPosition;
2849 Func: TglBitmapFunction; Format: TglBitmapInternalFormat; CustomData: Pointer);
2854 ImageSize := FormatGetImageSize(Size, Format);
2855 GetMem(Image, ImageSize);
2857 FillChar(Image^, ImageSize, #$FF);
2859 SetDataPointer(Image, Format, Size.X, Size.Y);
2865 AddFunc(Self, Func, False, Format, CustomData)
2869 procedure TglBitmap.SaveToFile(FileName: String; FileType: TglBitmapFileType);
2873 FS := TFileStream.Create(FileName, fmCreate);
2876 SaveToStream(FS, FileType);
2883 procedure TglBitmap.SaveToStream(Stream: TStream; FileType: TglBitmapFileType);
2886 {$IFDEF GLB_SUPPORT_PNG_WRITE}
2887 ftPNG: SavePng(Stream);
2889 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
2890 ftJPEG: SaveJPEG(Stream);
2892 ftDDS: SaveDDS(Stream);
2893 ftTGA: SaveTGA(Stream);
2894 ftBMP: SaveBMP(Stream);
2900 function TglBitmap.AssignToSurface(out Surface: PSDL_Surface): boolean;
2902 Row, RowSize: Integer;
2903 pSource, pData: PByte;
2905 Pix: TglBitmapPixelData;
2907 function GetRowPointer(Row: Integer): pByte;
2909 Result := Surface.pixels;
2910 Inc(Result, Row * RowSize);
2916 if not FormatIsUncompressed(InternalFormat) then
2917 raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
2919 if Assigned(Data) then begin
2920 case Trunc(FormatGetSize(InternalFormat)) of
2926 raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
2929 FormatPreparePixel(Pix, InternalFormat);
2931 with Pix.PixelDesc do
2932 Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth, RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift);
2935 RowSize := Trunc(FileWidth * FormatGetSize(InternalFormat));
2937 for Row := 0 to FileHeight -1 do begin
2938 pData := GetRowPointer(Row);
2940 if Assigned(pData) then begin
2941 Move(pSource^, pData^, RowSize);
2942 Inc(pSource, RowSize);
2951 function TglBitmap.AssignFromSurface(const Surface: PSDL_Surface): boolean;
2953 pSource, pData, pTempData: PByte;
2954 Row, RowSize, TempWidth, TempHeight: Integer;
2955 IntFormat: TglBitmapInternalFormat;
2957 function GetRowPointer(Row: Integer): pByte;
2959 Result := Surface^.pixels;
2960 Inc(Result, Row * RowSize);
2966 if (Assigned(Surface)) then begin
2967 with Surface^.format^ do begin
2968 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminance) then
2969 IntFormat := ifLuminance
2972 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminanceAlpha) then
2973 IntFormat := ifLuminanceAlpha
2976 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA4) then
2977 IntFormat := ifRGBA4
2980 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifR5G6B5) then
2981 IntFormat := ifR5G6B5
2984 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB5A1) then
2985 IntFormat := ifRGB5A1
2988 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGR8) then
2992 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB8) then
2996 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGRA8) then
2997 IntFormat := ifBGRA8
3000 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA8) then
3001 IntFormat := ifRGBA8
3004 if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB10A2) then
3005 IntFormat := ifRGB10A2
3007 raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
3010 TempWidth := Surface^.w;
3011 TempHeight := Surface^.h;
3013 RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
3015 GetMem(pData, TempHeight * RowSize);
3019 for Row := 0 to TempHeight -1 do begin
3020 pSource := GetRowPointer(Row);
3022 if (Assigned(pSource)) then begin
3023 Move(pSource^, pTempData^, RowSize);
3024 Inc(pTempData, RowSize);
3028 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
3039 function TglBitmap.AssignAlphaToSurface(out Surface: PSDL_Surface): boolean;
3041 Row, Col, AlphaInterleave: Integer;
3042 pSource, pDest: PByte;
3044 function GetRowPointer(Row: Integer): pByte;
3046 Result := Surface.pixels;
3047 Inc(Result, Row * Width);
3053 if Assigned(Data) then begin
3054 if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifBGRA8, ifRGBA8] then begin
3055 Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
3057 case InternalFormat of
3059 AlphaInterleave := 1;
3061 AlphaInterleave := 3;
3063 AlphaInterleave := 0;
3069 for Row := 0 to Height -1 do begin
3070 pDest := GetRowPointer(Row);
3072 if Assigned(pDest) then begin
3073 for Col := 0 to Width -1 do begin
3074 Inc(pSource, AlphaInterleave);
3088 function TglBitmap.AddAlphaFromSurface(Surface: PSDL_Surface; Func: TglBitmapFunction; CustomData: Pointer): boolean;
3090 glBitmap: TglBitmap2D;
3092 glBitmap := TglBitmap2D.Create;
3094 glBitmap.AssignFromSurface(Surface);
3096 Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
3105 function TglBitmap.AssignFromBitmap(const Bitmap: TBitmap): boolean;
3107 pSource, pData, pTempData: PByte;
3108 Row, RowSize, TempWidth, TempHeight: Integer;
3109 IntFormat: TglBitmapInternalFormat;
3113 if (Assigned(Bitmap)) then begin
3114 case Bitmap.PixelFormat of
3116 IntFormat := ifLuminance;
3118 IntFormat := ifRGB5A1;
3120 IntFormat := ifR5G6B5;
3122 IntFormat := ifBGR8;
3124 IntFormat := ifBGRA8;
3126 raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
3129 TempWidth := Bitmap.Width;
3130 TempHeight := Bitmap.Height;
3132 RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
3134 GetMem(pData, TempHeight * RowSize);
3138 for Row := 0 to TempHeight -1 do begin
3139 pSource := Bitmap.Scanline[Row];
3141 if (Assigned(pSource)) then begin
3142 Move(pSource^, pTempData^, RowSize);
3143 Inc(pTempData, RowSize);
3147 SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
3158 function TglBitmap.AssignToBitmap(const Bitmap: TBitmap): boolean;
3161 pSource, pData: PByte;
3165 if Assigned(Data) then begin
3166 if Assigned(Bitmap) then begin
3167 Bitmap.Width := Width;
3168 Bitmap.Height := Height;
3170 case InternalFormat of
3171 ifAlpha, ifLuminance, ifDepth8:
3173 Bitmap.PixelFormat := pf8bit;
3174 Bitmap.Palette := CreateGrayPalette;
3177 Bitmap.PixelFormat := pf15bit;
3179 Bitmap.PixelFormat := pf16bit;
3181 Bitmap.PixelFormat := pf24bit;
3183 Bitmap.PixelFormat := pf32bit;
3185 raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
3189 for Row := 0 to FileHeight -1 do begin
3190 pData := Bitmap.Scanline[Row];
3192 Move(pSource^, pData^, fRowSize);
3193 Inc(pSource, fRowSize);
3195 // swap RGB(A) to BGR(A)
3196 if InternalFormat in [ifRGB8, ifRGBA8] then
3197 SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8);
3206 function TglBitmap.AssignAlphaToBitmap(const Bitmap: TBitmap): boolean;
3208 Row, Col, AlphaInterleave: Integer;
3209 pSource, pDest: PByte;
3213 if Assigned(Data) then begin
3214 if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin
3215 if Assigned(Bitmap) then begin
3216 Bitmap.PixelFormat := pf8bit;
3217 Bitmap.Palette := CreateGrayPalette;
3218 Bitmap.Width := Width;
3219 Bitmap.Height := Height;
3221 case InternalFormat of
3223 AlphaInterleave := 1;
3225 AlphaInterleave := 3;
3227 AlphaInterleave := 0;
3233 for Row := 0 to Height -1 do begin
3234 pDest := Bitmap.Scanline[Row];
3236 if Assigned(pDest) then begin
3237 for Col := 0 to Width -1 do begin
3238 Inc(pSource, AlphaInterleave);
3253 function TglBitmap.AddAlphaFromBitmap(Bitmap: TBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean;
3255 glBitmap: TglBitmap2D;
3257 glBitmap := TglBitmap2D.Create;
3259 glBitmap.AssignFromBitmap(Bitmap);
3261 Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
3269 function TglBitmap.AddAlphaFromFile(FileName: String; Func: TglBitmapFunction; CustomData: Pointer): boolean;
3273 FS := TFileStream.Create(FileName, fmOpenRead);
3275 Result := AddAlphaFromStream(FS, Func, CustomData);
3282 function TglBitmap.AddAlphaFromStream(Stream: TStream; Func: TglBitmapFunction; CustomData: Pointer): boolean;
3284 glBitmap: TglBitmap2D;
3286 glBitmap := TglBitmap2D.Create(Stream);
3288 Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
3296 function TglBitmap.AddAlphaFromResource(Instance: Cardinal; Resource: String;
3297 ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean;
3299 RS: TResourceStream;
3304 if Assigned(ResType) then
3305 TempResType := ResType
3308 TempPos := Pos('.', Resource);
3309 ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
3310 Resource := UpperCase(Copy(Resource, 0, TempPos -1));
3311 TempResType := PChar(ResTypeStr);
3314 RS := TResourceStream.Create(Instance, Resource, TempResType);
3316 Result := AddAlphaFromStream(RS, Func, CustomData);
3323 function TglBitmap.AddAlphaFromResourceID(Instance: Cardinal; ResourceID: Integer;
3324 ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean;
3326 RS: TResourceStream;
3328 RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
3330 Result := AddAlphaFromStream(RS, Func, CustomData);
3338 procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3340 with FuncRec do begin
3341 Dest.Red := Source.Red;
3342 Dest.Green := Source.Green;
3343 Dest.Blue := Source.Blue;
3345 with TglBitmapPixelData(CustomData^) do
3346 if ((Dest.Red <= Red ) and (Dest.Red >= PixelDesc.RedRange ) and
3347 (Dest.Green <= Green) and (Dest.Green >= PixelDesc.GreenRange) and
3348 (Dest.Blue <= Blue ) and (Dest.Blue >= PixelDesc.BlueRange )) then
3351 Dest.Alpha := Dest.PixelDesc.AlphaRange;
3356 function TglBitmap.AddAlphaFromColorKey(Red, Green, Blue: Byte; Deviation: Byte
3359 Result := AddAlphaFromColorKeyFloat(Red / $FF, Green / $FF, Blue / $FF, Deviation / $FF);
3363 function TglBitmap.AddAlphaFromColorKeyRange(Red, Green, Blue: Cardinal; Deviation: Cardinal = 0): Boolean;
3365 PixelData: TglBitmapPixelData;
3367 FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
3369 Result := AddAlphaFromColorKeyFloat(
3370 Red / PixelData.PixelDesc.RedRange,
3371 Green / PixelData.PixelDesc.GreenRange,
3372 Blue / PixelData.PixelDesc.BlueRange,
3373 Deviation / Max(PixelData.PixelDesc.RedRange, Max(PixelData.PixelDesc.GreenRange, PixelData.PixelDesc.BlueRange)));
3377 function TglBitmap.AddAlphaFromColorKeyFloat(Red, Green, Blue: Single; Deviation: Single = 0): Boolean;
3379 TempR, TempG, TempB: Cardinal;
3380 PixelData: TglBitmapPixelData;
3382 FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
3384 // Calculate Colorrange
3385 with PixelData.PixelDesc do begin
3386 TempR := Trunc(RedRange * Deviation);
3387 TempG := Trunc(GreenRange * Deviation);
3388 TempB := Trunc(BlueRange * Deviation);
3390 PixelData.Red := Min(RedRange, Trunc(RedRange * Red) + TempR);
3391 RedRange := Max(0, Trunc(RedRange * Red) - TempR);
3392 PixelData.Green := Min(GreenRange, Trunc(GreenRange * Green) + TempG);
3393 GreenRange := Max(0, Trunc(GreenRange * Green) - TempG);
3394 PixelData.Blue := Min(BlueRange, Trunc(BlueRange * Blue) + TempB);
3395 BlueRange := Max(0, Trunc(BlueRange * Blue) - TempB);
3396 PixelData.Alpha := 0;
3400 Result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
3404 procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
3406 with FuncRec do begin
3407 Dest.Red := Source.Red;
3408 Dest.Green := Source.Green;
3409 Dest.Blue := Source.Blue;
3411 with TglBitmapPixelData(CustomData^) do
3412 Dest.Alpha := Alpha;
3417 function TglBitmap.AddAlphaFromValue(Alpha: Byte): Boolean;
3419 Result := AddAlphaFromValueFloat(Alpha / $FF);
3423 function TglBitmap.AddAlphaFromValueFloat(Alpha: Single): Boolean;
3425 PixelData: TglBitmapPixelData;
3427 FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
3429 with PixelData.PixelDesc do
3430 PixelData.Alpha := Min(AlphaRange, Max(0, Round(AlphaRange * Alpha)));
3432 Result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData);
3436 function TglBitmap.AddAlphaFromValueRange(Alpha: Cardinal): Boolean;
3438 PixelData: TglBitmapPixelData;
3440 FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
3442 Result := AddAlphaFromValueFloat(Alpha / PixelData.PixelDesc.AlphaRange);
3446 procedure glBitmapInvertFunc(var FuncRec: TglBitmapFunctionRec);
3448 with FuncRec do begin
3449 Dest.Red := Source.Red;
3450 Dest.Green := Source.Green;
3451 Dest.Blue := Source.Blue;
3452 Dest.Alpha := Source.Alpha;
3454 if (Integer(CustomData) and $1 > 0) then begin
3455 Dest.Red := Dest.Red xor Dest.PixelDesc.RedRange;
3456 Dest.Green := Dest.Green xor Dest.PixelDesc.GreenRange;
3457 Dest.Blue := Dest.Blue xor Dest.PixelDesc.BlueRange;
3460 if (Integer(CustomData) and $2 > 0) then begin
3461 Dest.Alpha := Dest.Alpha xor Dest.PixelDesc.AlphaRange;
3467 procedure TglBitmap.Invert(UseRGB: Boolean; UseAlpha: Boolean);
3469 if ((UseRGB) or (UseAlpha)) then
3470 AddFunc(glBitmapInvertFunc, False, Pointer(Integer(UseAlpha) shl 1 or Integer(UseRGB)));
3474 procedure TglBitmap.SetFilter(Min, Mag: Integer);
3478 fFilterMin := GL_NEAREST;
3480 fFilterMin := GL_LINEAR;
3481 GL_NEAREST_MIPMAP_NEAREST:
3482 fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
3483 GL_LINEAR_MIPMAP_NEAREST:
3484 fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
3485 GL_NEAREST_MIPMAP_LINEAR:
3486 fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
3487 GL_LINEAR_MIPMAP_LINEAR:
3488 fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
3490 raise EglBitmapException.Create('SetFilter - Unknow Minfilter.');
3495 fFilterMag := GL_NEAREST;
3497 fFilterMag := GL_LINEAR;
3499 raise EglBitmapException.Create('SetFilter - Unknow Magfilter.');
3502 // If texture is created then assign filter
3503 if ID > 0 then begin
3506 glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
3508 if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE_ARB) then begin
3510 GL_NEAREST, GL_LINEAR:
3511 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
3512 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
3513 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3514 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
3515 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3518 glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
3523 procedure TglBitmap.SetWrap(S: Integer; T: Integer; R: Integer);
3529 fWrapS := GL_REPEAT;
3532 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
3533 fWrapS := GL_CLAMP_TO_EDGE
3539 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
3540 fWrapS := GL_CLAMP_TO_BORDER
3546 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
3547 fWrapS := GL_MIRRORED_REPEAT
3549 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
3552 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).');
3559 fWrapT := GL_REPEAT;
3562 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
3563 fWrapT := GL_CLAMP_TO_EDGE
3569 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
3570 fWrapT := GL_CLAMP_TO_BORDER
3576 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
3577 fWrapT := GL_MIRRORED_REPEAT
3579 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (T).');
3582 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (T).');
3589 fWrapR := GL_REPEAT;
3592 if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
3593 fWrapR := GL_CLAMP_TO_EDGE
3599 if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
3600 fWrapR := GL_CLAMP_TO_BORDER
3606 if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
3607 fWrapR := GL_MIRRORED_REPEAT
3609 raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (R).');
3612 raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (R).');
3615 if ID > 0 then begin
3617 glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
3618 glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
3619 glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
3624 procedure TglBitmap.SetDataPointer(NewData: pByte;
3625 Format: TglBitmapInternalFormat; Width: Integer; Height: Integer);
3628 if Data <> NewData then begin
3635 if Data = nil then begin
3636 fInternalFormat := ifEmpty;
3640 if Width <> -1 then begin
3641 fDimension.Fields := fDimension.Fields + [ffX];
3642 fDimension.X := Width;
3645 if Height <> -1 then begin
3646 fDimension.Fields := fDimension.Fields + [ffY];
3647 fDimension.Y := Height;
3650 fInternalFormat := Format;
3651 fPixelSize := Trunc(FormatGetSize(InternalFormat));
3652 fRowSize := Trunc(FormatGetSize(InternalFormat) * Self.Width);
3656 {$IFDEF GLB_SUPPORT_PNG_READ}
3657 {$IFDEF GLB_LIB_PNG}
3658 procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
3660 TStream(png_get_io_ptr(png)).Read(buffer^, size);
3665 function TglBitmap.LoadPNG(Stream: TStream): Boolean;
3666 {$IFDEF GLB_SDL_IMAGE}
3668 Surface: PSDL_Surface;
3673 RWops := glBitmapCreateRWops(Stream);
3675 if IMG_isPNG(RWops) > 0 then begin
3676 Surface := IMG_LoadPNG_RW(RWops);
3678 AssignFromSurface(Surface);
3681 SDL_FreeSurface(Surface);
3689 {$IFDEF GLB_LIB_PNG}
3692 signature: array [0..7] of byte;
3694 png_info: png_infop;
3696 TempHeight, TempWidth: Integer;
3697 Format: TglBitmapInternalFormat;
3700 png_rows: array of pByte;
3701 Row, LineSize: Integer;
3705 if not init_libPNG then
3706 raise Exception.Create('LoadPNG - unable to initialize libPNG.');
3710 StreamPos := Stream.Position;
3711 Stream.Read(signature, 8);
3712 Stream.Position := StreamPos;
3714 if png_check_sig(@signature, 8) <> 0 then begin
3716 png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
3718 raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
3721 png_info := png_create_info_struct(png);
3722 if png_info = nil then begin
3723 png_destroy_read_struct(@png, nil, nil);
3724 raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
3727 // set read callback
3728 png_set_read_fn(png, stream, glBitmap_libPNG_read_func);
3730 // read informations
3731 png_read_info(png, png_info);
3734 TempHeight := png_get_image_height(png, png_info);
3735 TempWidth := png_get_image_width(png, png_info);
3738 case png_get_color_type(png, png_info) of
3739 PNG_COLOR_TYPE_GRAY:
3740 Format := ifLuminance;
3741 PNG_COLOR_TYPE_GRAY_ALPHA:
3742 Format := ifLuminanceAlpha;
3745 PNG_COLOR_TYPE_RGB_ALPHA:
3748 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
3751 // cut upper 8 bit from 16 bit formats
3752 if png_get_bit_depth(png, png_info) > 8 then
3753 png_set_strip_16(png);
3755 // expand bitdepth smaller than 8
3756 if png_get_bit_depth(png, png_info) < 8 then
3757 png_set_expand(png);
3759 // allocating mem for scanlines
3760 LineSize := png_get_rowbytes(png, png_info);
3761 GetMem(png_data, TempHeight * LineSize);
3763 SetLength(png_rows, TempHeight);
3764 for Row := Low(png_rows) to High(png_rows) do begin
3765 png_rows[Row] := png_data;
3766 Inc(png_rows[Row], Row * LineSize);
3769 // read complete image into scanlines
3770 png_read_image(png, @png_rows[0]);
3773 png_read_end(png, png_info);
3775 // destroy read struct
3776 png_destroy_read_struct(@png, @png_info, nil);
3778 SetLength(png_rows, 0);
3781 SetDataPointer(png_data, Format, TempWidth, TempHeight);
3794 {$IFDEF GLB_PNGIMAGE}
3798 Header: Array[0..7] of Byte;
3799 Row, Col, PixSize, LineSize: Integer;
3800 NewImage, pSource, pDest, pAlpha: pByte;
3801 Format: TglBitmapInternalFormat;
3804 PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10);
3809 StreamPos := Stream.Position;
3810 Stream.Read(Header[0], SizeOf(Header));
3811 Stream.Position := StreamPos;
3813 {Test if the header matches}
3814 if Header = PngHeader then begin
3815 Png := TPNGObject.Create;
3817 Png.LoadFromStream(Stream);
3819 case Png.Header.ColorType of
3821 Format := ifLuminance;
3822 COLOR_GRAYSCALEALPHA:
3823 Format := ifLuminanceAlpha;
3829 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
3832 PixSize := Trunc(FormatGetSize(Format));
3833 LineSize := Integer(Png.Header.Width) * PixSize;
3835 GetMem(NewImage, LineSize * Integer(Png.Header.Height));
3839 case Png.Header.ColorType of
3840 COLOR_RGB, COLOR_GRAYSCALE:
3842 for Row := 0 to Png.Height -1 do begin
3843 Move (Png.Scanline[Row]^, pDest^, LineSize);
3844 Inc(pDest, LineSize);
3847 COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
3849 PixSize := PixSize -1;
3851 for Row := 0 to Png.Height -1 do begin
3852 pSource := Png.Scanline[Row];
3853 pAlpha := pByte(Png.AlphaScanline[Row]);
3855 for Col := 0 to Png.Width -1 do begin
3856 Move (pSource^, pDest^, PixSize);
3857 Inc(pSource, PixSize);
3858 Inc(pDest, PixSize);
3867 raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
3870 SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height);
3886 {$IFDEF GLB_LIB_JPEG}
3888 glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
3889 glBitmap_libJPEG_source_mgr = record
3890 pub: jpeg_source_mgr;
3893 SrcBuffer: array [1..4096] of byte;
3897 glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
3898 glBitmap_libJPEG_dest_mgr = record
3899 pub: jpeg_destination_mgr;
3901 DestStream: TStream;
3902 DestBuffer: array [1..4096] of byte;
3907 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
3911 // SetLength(Msg, 256);
3912 // cinfo^.err^.format_message(cinfo, pChar(Msg));
3914 // Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
3916 // cinfo^.global_state := 0;
3918 // jpeg_abort(cinfo);
3922 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
3926 // SetLength(Msg, 256);
3927 // cinfo^.err^.format_message(cinfo, pChar(Msg));
3929 // Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
3931 // cinfo^.global_state := 0;
3935 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
3940 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
3942 src: glBitmap_libJPEG_source_mgr_ptr;
3945 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
3947 bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
3948 if (bytes <= 0) then begin
3949 src^.SrcBuffer[1] := $FF;
3950 src^.SrcBuffer[2] := JPEG_EOI;
3954 src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
3955 src^.pub.bytes_in_buffer := bytes;
3961 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
3963 src: glBitmap_libJPEG_source_mgr_ptr;
3965 src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
3967 if num_bytes > 0 then begin
3968 // wanted byte isn't in buffer so set stream position and read buffer
3969 if num_bytes > src^.pub.bytes_in_buffer then begin
3970 src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
3971 src^.pub.fill_input_buffer(cinfo);
3973 // wanted byte is in buffer so only skip
3974 inc(src^.pub.next_input_byte, num_bytes);
3975 dec(src^.pub.bytes_in_buffer, num_bytes);
3981 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
3986 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
3991 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
3993 dest: glBitmap_libJPEG_dest_mgr_ptr;
3995 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
3997 if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
3998 // write complete buffer
3999 dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
4002 dest^.pub.next_output_byte := @dest^.DestBuffer[1];
4003 dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
4010 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
4013 dest: glBitmap_libJPEG_dest_mgr_ptr;
4015 dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
4017 for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
4018 // check for endblock
4019 if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
4021 dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
4026 dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
4032 {$IFDEF GLB_SUPPORT_JPEG_READ}
4033 function TglBitmap.LoadJPEG(Stream: TStream): Boolean;
4034 {$IFDEF GLB_SDL_IMAGE}
4036 Surface: PSDL_Surface;
4041 RWops := glBitmapCreateRWops(Stream);
4043 if IMG_isJPG(RWops) > 0 then begin
4044 Surface := IMG_LoadJPG_RW(RWops);
4046 AssignFromSurface(Surface);
4049 SDL_FreeSurface(Surface);
4057 {$IFDEF GLB_LIB_JPEG}
4060 Temp: array[0..1]of Byte;
4062 jpeg: jpeg_decompress_struct;
4063 jpeg_err: jpeg_error_mgr;
4065 IntFormat: TglBitmapInternalFormat;
4067 TempHeight, TempWidth: Integer;
4074 if not init_libJPEG then
4075 raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
4078 // reading first two bytes to test file and set cursor back to begin
4079 StreamPos := Stream.Position;
4080 Stream.Read(Temp[0], 2);
4081 Stream.Position := StreamPos;
4083 // if Bitmap then read file.
4084 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
4085 FillChar(jpeg, SizeOf(jpeg_decompress_struct), $00);
4086 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
4089 jpeg.err := jpeg_std_error(@jpeg_err);
4090 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
4091 jpeg_err.output_message := glBitmap_libJPEG_output_message;
4093 // decompression struct
4094 jpeg_create_decompress(@jpeg);
4096 // allocation space for streaming methods
4097 jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
4099 // seeting up custom functions
4100 with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
4101 pub.init_source := glBitmap_libJPEG_init_source;
4102 pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
4103 pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
4104 pub.resync_to_restart := jpeg_resync_to_restart; // use default method
4105 pub.term_source := glBitmap_libJPEG_term_source;
4107 pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
4108 pub.next_input_byte := nil; // until buffer loaded
4110 SrcStream := Stream;
4113 // set global decoding state
4114 jpeg.global_state := DSTATE_START;
4116 // read header of jpeg
4117 jpeg_read_header(@jpeg, False);
4119 // setting output parameter
4120 case jpeg.jpeg_color_space of
4123 jpeg.out_color_space := JCS_GRAYSCALE;
4124 IntFormat := ifLuminance;
4127 jpeg.out_color_space := JCS_RGB;
4128 IntFormat := ifRGB8;
4132 jpeg_start_decompress(@jpeg);
4134 TempHeight := jpeg.output_height;
4135 TempWidth := jpeg.output_width;
4137 // creating new image
4138 GetMem(pImage, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
4142 for Row := 0 to TempHeight -1 do begin
4143 jpeg_read_scanlines(@jpeg, @pTemp, 1);
4144 Inc(pTemp, Trunc(FormatGetSize(IntFormat) * TempWidth));
4147 // finish decompression
4148 jpeg_finish_decompress(@jpeg);
4150 // destroy decompression
4151 jpeg_destroy_decompress(@jpeg);
4153 SetDataPointer(pImage, IntFormat, TempWidth, TempHeight);
4166 {$IFDEF GLB_DELPHI_JPEG}
4171 Temp: array[0..1]of Byte;
4175 // reading first two bytes to test file and set cursor back to begin
4176 StreamPos := Stream.Position;
4177 Stream.Read(Temp[0], 2);
4178 Stream.Position := StreamPos;
4180 // if Bitmap then read file.
4181 if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
4182 bmp := TBitmap.Create;
4184 jpg := TJPEGImage.Create;
4186 jpg.LoadFromStream(Stream);
4188 Result := AssignFromBitmap(bmp);
4207 BMP_COMP_BITFIELDS = 3;
4210 TBMPHeader = packed record
4215 bfOffBits: Cardinal;
4218 TBMPInfo = packed record
4224 biCompression: Cardinal;
4225 biSizeImage: Cardinal;
4226 biXPelsPerMeter: Longint;
4227 biYPelsPerMeter: Longint;
4228 biClrUsed: Cardinal;
4229 biClrImportant: Cardinal;
4232 TBMPInfoOS = packed record
4240 // TBMPPalette = record
4242 // True : (Colors: array[Byte] of TRGBQUAD);
4243 // False: (redMask, greenMask, blueMask: Cardinal);
4246 function TglBitmap.LoadBMP(Stream: TStream): Boolean;
4251 NewImage, pData: pByte;
4253 Format: TglBitmapInternalFormat;
4254 LineSize, Padding, LineIdx: Integer;
4255 RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
4257 PaddingBuff: Cardinal;
4260 function GetLineWidth : Integer;
4262 Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
4275 StreamPos := Stream.Position;
4276 Stream.Read(Header, SizeOf(Header));
4278 if Header.bfType = BMP_MAGIC then begin
4279 Stream.Read(Info, SizeOf(Info));
4281 // Check for Compression
4282 if Info.biCompression <> BMP_COMP_RGB then begin
4283 if Info.biCompression = BMP_COMP_BITFIELDS then begin
4284 // Read Bitmasks for 16 or 32 Bit (24 Bit dosn't support Bitmasks!)
4285 if (Info.biBitCount = 16) or (Info.biBitCount = 32) then begin
4286 Stream.Read(RedMask, SizeOf(Cardinal));
4287 Stream.Read(GreenMask, SizeOf(Cardinal));
4288 Stream.Read(BlueMask, SizeOf(Cardinal));
4289 Stream.Read(AlphaMask, SizeOf(Cardinal));
4292 // RLE compression is unsupported
4293 Stream.Position := StreamPos;
4300 if Info.biBitCount < 16 then
4301 Stream.Position := Stream.Position + Info.biClrUsed * 4;
4304 Stream.Position := StreamPos + Header.bfOffBits;
4307 case Info.biBitCount of
4308 8 : Format := ifLuminance;
4311 if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin
4314 if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifLuminanceAlpha) then
4315 Format := ifLuminanceAlpha;
4317 if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGBA4) then
4320 if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifRGB5A1) then
4323 if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifR5G6B5) then
4327 24: Format := ifBGR8;
4330 if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin
4333 if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGBA8) then
4336 if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifBGRA8) then
4339 if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGB10A2) then
4340 Format := ifRGB10A2;
4345 if Format <> ifEmpty then begin
4346 LineSize := Trunc(Info.biWidth * FormatGetSize(Format));
4347 Padding := GetLineWidth - LineSize;
4350 GetMem(NewImage, Info.biHeight * LineSize);
4352 FillChar(NewImage^, Info.biHeight * LineSize, $FF);
4354 // Set pData to last Line
4356 Inc(pData, LineSize * (Info.biHeight -1));
4359 for LineIdx := 0 to Info.biHeight - 1 do begin
4360 Stream.Read(pData^, LineSize);
4361 Dec(pData, LineSize);
4363 Stream.Read(PaddingBuff, Padding);
4367 SetDataPointer(NewImage, Format, Info.biWidth, Info.biHeight);
4376 else Stream.Position := StreamPos;
4381 DDS_MAGIC = $20534444;
4383 // DDS_header.dwFlags
4384 DDSD_CAPS = $00000001;
4385 DDSD_HEIGHT = $00000002;
4386 DDSD_WIDTH = $00000004;
4387 DDSD_PITCH = $00000008;
4388 DDSD_PIXELFORMAT = $00001000;
4389 DDSD_MIPMAPCOUNT = $00020000;
4390 DDSD_LINEARSIZE = $00080000;
4391 DDSD_DEPTH = $00800000;
4393 // DDS_header.sPixelFormat.dwFlags
4394 DDPF_ALPHAPIXELS = $00000001;
4395 DDPF_FOURCC = $00000004;
4396 DDPF_INDEXED = $00000020;
4397 DDPF_RGB = $00000040;
4399 // DDS_header.sCaps.dwCaps1
4400 DDSCAPS_COMPLEX = $00000008;
4401 DDSCAPS_TEXTURE = $00001000;
4402 DDSCAPS_MIPMAP = $00400000;
4404 // DDS_header.sCaps.dwCaps2
4405 DDSCAPS2_CUBEMAP = $00000200;
4406 DDSCAPS2_CUBEMAP_POSITIVEX = $00000400;
4407 DDSCAPS2_CUBEMAP_NEGATIVEX = $00000800;
4408 DDSCAPS2_CUBEMAP_POSITIVEY = $00001000;
4409 DDSCAPS2_CUBEMAP_NEGATIVEY = $00002000;
4410 DDSCAPS2_CUBEMAP_POSITIVEZ = $00004000;
4411 DDSCAPS2_CUBEMAP_NEGATIVEZ = $00008000;
4412 DDSCAPS2_VOLUME = $00200000;
4414 D3DFMT_DXT1 = $31545844;
4415 D3DFMT_DXT3 = $33545844;
4416 D3DFMT_DXT5 = $35545844;
4419 TDDSPixelFormat = packed record
4423 dwRGBBitCount: Cardinal;
4424 dwRBitMask: Cardinal;
4425 dwGBitMask: Cardinal;
4426 dwBBitMask: Cardinal;
4427 dwAlphaBitMask: Cardinal;
4430 TDDSCaps = packed record
4434 dwReserved: Cardinal;
4437 TDDSHeader = packed record
4443 dwPitchOrLinearSize: Cardinal;
4445 dwMipMapCount: Cardinal;
4446 dwReserved: array[0..10] of Cardinal;
4447 PixelFormat: TDDSPixelFormat;
4449 dwReserved2: Cardinal;
4452 procedure TglBitmap.SetCustomData(const aValue: Pointer);
4454 if fCustomData = aValue then Exit;
4455 fCustomData := aValue;
4458 procedure TglBitmap.SetCustomName(const aValue: String);
4460 if fCustomName = aValue then Exit;
4461 fCustomName := aValue;
4464 procedure TglBitmap.SetCustomNameW(const aValue: WideString);
4466 if fCustomNameW = aValue then Exit;
4467 fCustomNameW := aValue;
4470 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
4472 if fDeleteTextureOnFree = aValue then Exit;
4473 fDeleteTextureOnFree := aValue;
4476 procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
4478 if fFormat = aValue then Exit;
4482 procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
4484 if fFreeDataAfterGenTexture = aValue then Exit;
4485 fFreeDataAfterGenTexture := aValue;
4488 procedure TglBitmap.SetID(const aValue: Cardinal);
4490 if fID = aValue then Exit;
4494 procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
4496 if fMipMap = aValue then Exit;
4500 procedure TglBitmap.SetTarget(const aValue: Cardinal);
4502 if fTarget = aValue then Exit;
4506 function TglBitmap.LoadDDS(Stream: TStream): Boolean;
4510 Y, LineSize: Cardinal;
4512 // MipMapCount, X, Y, XSize, YSize: Cardinal;
4514 NewImage, pData: pByte;
4515 Format: TglBitmapInternalFormat;
4518 function RaiseEx : Exception;
4520 Result := EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
4524 function GetInternalFormat: TglBitmapInternalFormat;
4526 with Header.PixelFormat do begin
4528 if (dwFlags and DDPF_FOURCC) > 0 then begin
4529 case Header.PixelFormat.dwFourCC of
4530 D3DFMT_DXT1: Result := ifDXT1;
4531 D3DFMT_DXT3: Result := ifDXT3;
4532 D3DFMT_DXT5: Result := ifDXT5;
4539 if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
4540 case dwRGBBitCount of
4543 if dwFlags and DDPF_ALPHAPIXELS > 0 then
4546 Result := ifLuminance;
4550 if dwFlags and DDPF_ALPHAPIXELS > 0 then begin
4552 case GetBitSize(dwRBitMask) of
4553 5: Result := ifRGB5A1;
4554 4: Result := ifRGBA4;
4556 Result := ifLuminanceAlpha;
4565 if dwRBitMask > dwBBitMask then
4572 if GetBitSize(dwRBitMask) = 10 then
4576 if dwRBitMask > dwBBitMask then
4593 StreamPos := Stream.Position;
4594 Stream.Read(Header, sizeof(Header));
4596 if ((Header.dwMagic <> DDS_MAGIC) or (Header.dwSize <> 124) or
4597 ((Header.dwFlags and DDSD_PIXELFORMAT) = 0) or ((Header.dwFlags and DDSD_CAPS) = 0)) then begin
4598 Stream.Position := StreamPos;
4603 // if Header.dwFlags and DDSD_MIPMAPCOUNT <> 0
4604 // then MipMapCount := Header.dwMipMapCount
4605 // else MipMapCount := 1;
4607 Format := GetInternalFormat;
4608 LineSize := Trunc(Header.dwWidth * FormatGetSize(Format));
4610 GetMem(NewImage, Header.dwHeight * LineSize);
4615 if (Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0 then begin
4616 RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
4618 for Y := 0 to Header.dwHeight -1 do begin
4619 Stream.Read(pData^, RowSize);
4620 Inc(pData, LineSize);
4625 if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
4626 RowSize := Header.dwPitchOrLinearSize;
4628 for Y := 0 to Header.dwHeight -1 do begin
4629 Stream.Read(pData^, RowSize);
4630 Inc(pData, LineSize);
4635 SetDataPointer(NewImage, Format, Header.dwWidth, Header.dwHeight);
4646 TTGAHeader = packed record
4650 ColorMapSpec: Array[0..4] of Byte;
4660 TGA_UNCOMPRESSED_RGB = 2;
4661 TGA_UNCOMPRESSED_GRAY = 3;
4662 TGA_COMPRESSED_RGB = 10;
4663 TGA_COMPRESSED_GRAY = 11;
4667 function TglBitmap.LoadTGA(Stream: TStream): Boolean;
4670 NewImage, pData: PByte;
4672 PixelSize, LineSize, YStart, YEnd, YInc: Integer;
4673 Format: TglBitmapInternalFormat;
4678 procedure ReadUncompressed;
4682 RowSize := Header.Width * PixelSize;
4684 // copy line by line
4685 while YStart <> YEnd + YInc do begin
4687 Inc(pData, YStart * LineSize);
4689 Stream.Read(pData^, RowSize);
4695 procedure ReadCompressed;
4697 HeaderWidth, HeaderHeight: Integer;
4698 LinePixelsRead, ImgPixelsRead, ImgPixelsToRead: Integer;
4701 CacheSize, CachePos: Integer;
4704 TempBuf: Array [0..15] of Byte;
4706 PixelRepeat: Boolean;
4707 PixelToRead, TempPixels: Integer;
4710 procedure CheckLine;
4712 if LinePixelsRead >= HeaderWidth then begin
4713 LinePixelsRead := 0;
4716 Inc(pData, YStart * LineSize);
4721 procedure CachedRead(var Buffer; Count: Integer);
4725 if (CachePos + Count) > CacheSize then begin
4729 if CacheSize - CachePos > 0 then begin
4730 BytesRead := CacheSize - CachePos;
4732 Move(pByteArray(Cache)^[CachePos], Buffer, BytesRead);
4733 Inc(CachePos, BytesRead);
4737 CacheSize := Min(CACHE_SIZE, Stream.Size - Stream.Position);
4738 Stream.Read(Cache^, CacheSize);
4742 if Count - BytesRead > 0 then begin
4743 Move(pByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
4744 Inc(CachePos, Count - BytesRead);
4747 Move(pByteArray(Cache)^[CachePos], Buffer, Count);
4748 Inc(CachePos, Count);
4757 HeaderWidth := Header.Width;
4758 HeaderHeight := Header.Height;
4760 GetMem(Cache, CACHE_SIZE); // 16K Buffer
4762 ImgPixelsToRead := HeaderWidth * HeaderHeight;
4764 LinePixelsRead := 0;
4767 Inc(pData, YStart * LineSize);
4769 // Read until all Pixels
4771 CachedRead(Temp, 1);
4773 PixelRepeat := Temp and $80 > 0;
4774 PixelToRead := (Temp and $7F) + 1;
4776 Inc(ImgPixelsRead, PixelToRead);
4778 if PixelRepeat then begin
4779 // repeat one pixel x times
4780 CachedRead(TempBuf[0], PixelSize);
4783 while PixelToRead > 0 do begin
4786 TempPixels := HeaderWidth - LinePixelsRead;
4787 if PixelToRead < TempPixels then
4788 TempPixels := PixelToRead;
4790 Inc(LinePixelsRead, TempPixels);
4791 Dec(PixelToRead, TempPixels);
4793 while TempPixels > 0 do begin
4797 pData^ := TempBuf[0];
4802 pWord(pData)^ := pWord(@TempBuf[0])^;
4807 pWord(pData)^ := pWord(@TempBuf[0])^;
4809 pData^ := TempBuf[2];
4814 pDWord(pData)^ := pDWord(@TempBuf[0])^;
4824 while PixelToRead > 0 do begin
4827 TempPixels := HeaderWidth - LinePixelsRead;
4828 if PixelToRead < TempPixels then
4829 TempPixels := PixelToRead;
4831 CachedRead(pData^, PixelSize * TempPixels);
4832 Inc(pData, PixelSize * TempPixels);
4834 Inc(LinePixelsRead, TempPixels);
4836 Dec(PixelToRead, TempPixels);
4839 until ImgPixelsRead >= ImgPixelsToRead;
4848 // reading header to test file and set cursor back to begin
4849 StreamPos := Stream.Position;
4850 Stream.Read(Header, SizeOf(Header));
4852 // no colormapped files
4853 if (Header.ColorMapType = 0) then begin
4854 if Header.ImageType in [TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY] then begin
4856 8: Format := ifAlpha;
4857 16: Format := ifLuminanceAlpha;
4858 24: Format := ifBGR8;
4859 32: Format := ifBGRA8;
4861 raise EglBitmapException.Create('LoadTga - unsupported BitsPerPixel found.');
4865 if Header.ImageID <> 0 then
4866 Stream.Position := Stream.Position + Header.ImageID;
4868 PixelSize := Trunc(FormatGetSize(Format));
4869 LineSize := Trunc(Header.Width * PixelSize);
4871 GetMem(NewImage, LineSize * Header.Height);
4874 if (Header.ImageDes and $20 > 0) then begin
4876 YEnd := Header.Height -1;
4879 YStart := Header.Height -1;
4885 case Header.ImageType of
4886 TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
4888 TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
4892 SetDataPointer(NewImage, Format, Header.Width, Header.Height);
4900 else Stream.Position := StreamPos;
4902 else Stream.Position := StreamPos;
4906 {$IFDEF GLB_SUPPORT_PNG_WRITE}
4907 {$IFDEF GLB_LIB_PNG}
4908 procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
4910 TStream(png_get_io_ptr(png)).Write(buffer^, size);
4914 procedure TglBitmap.SavePNG(Stream: TStream);
4915 {$IFDEF GLB_LIB_PNG}
4918 png_info: png_infop;
4919 png_rows: array of pByte;
4924 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
4925 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
4927 if not init_libPNG then
4928 raise Exception.Create('SavePNG - unable to initialize libPNG.');
4931 case FInternalFormat of
4932 ifAlpha, ifLuminance, ifDepth8:
4933 ColorType := PNG_COLOR_TYPE_GRAY;
4935 ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
4937 ColorType := PNG_COLOR_TYPE_RGB;
4939 ColorType := PNG_COLOR_TYPE_RGBA;
4941 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
4944 LineSize := Trunc(FormatGetSize(FInternalFormat) * Width);
4946 // creating array for scanline
4947 SetLength(png_rows, Height);
4949 for Row := 0 to Height - 1 do begin
4950 png_rows[Row] := Data;
4951 Inc(png_rows[Row], Row * LineSize)
4955 png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
4957 raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
4960 png_info := png_create_info_struct(png);
4961 if png_info = nil then begin
4962 png_destroy_write_struct(@png, nil);
4963 raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
4966 // set read callback
4967 png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil);
4970 png_set_compression_level(png, 6);
4972 if InternalFormat in [ifBGR8, ifBGRA8] then
4976 png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
4979 png_write_info(png, png_info);
4982 png_write_image(png, @png_rows[0]);
4985 png_write_end(png, png_info);
4987 // destroy write struct
4988 png_destroy_write_struct(@png, @png_info);
4990 SetLength(png_rows, 0);
4997 {$IFDEF GLB_PNGIMAGE}
5001 pSource, pDest: pByte;
5002 X, Y, PixSize: Integer;
5003 ColorType: Cardinal;
5009 if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
5010 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5012 case FInternalFormat of
5013 ifAlpha, ifLuminance, ifDepth8:
5015 ColorType := COLOR_GRAYSCALE;
5021 ColorType := COLOR_GRAYSCALEALPHA;
5027 ColorType := COLOR_RGB;
5033 ColorType := COLOR_RGBALPHA;
5038 raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
5041 Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
5045 for Y := 0 to Height -1 do begin
5046 pDest := png.ScanLine[Y];
5048 for X := 0 to Width -1 do begin
5049 Move(pSource^, pDest^, PixSize);
5051 Inc(pDest, PixSize);
5052 Inc(pSource, PixSize);
5055 png.AlphaScanline[Y]^[X] := pSource^;
5060 // convert RGB line to BGR
5061 if InternalFormat in [ifRGB8, ifRGBA8] then begin
5062 pTemp := png.ScanLine[Y];
5064 for X := 0 to Width -1 do begin
5065 Temp := pByteArray(pTemp)^[0];
5066 pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
5067 pByteArray(pTemp)^[2] := Temp;
5075 Png.CompressionLevel := 6;
5076 Png.SaveToStream(Stream);
5085 procedure TglBitmap.SaveDDS(Stream: TStream);
5088 Pix: TglBitmapPixelData;
5090 if not FormatIsUncompressed(InternalFormat) then
5091 raise EglBitmapUnsupportedInternalFormat.Create('SaveDDS - ' + UNSUPPORTED_INTERNAL_FORMAT);
5093 if InternalFormat = ifAlpha then
5094 FormatPreparePixel(Pix, ifLuminance)
5096 FormatPreparePixel(Pix, InternalFormat);
5099 FillChar(Header, SizeOf(Header), 0);
5101 Header.dwMagic := DDS_MAGIC;
5102 Header.dwSize := 124;
5103 Header.dwFlags := DDSD_PITCH or DDSD_CAPS or DDSD_PIXELFORMAT;
5105 if Width > 0 then begin
5106 Header.dwWidth := Width;
5107 Header.dwFlags := Header.dwFlags or DDSD_WIDTH;
5110 if Height > 0 then begin
5111 Header.dwHeight := Height;
5112 Header.dwFlags := Header.dwFlags or DDSD_HEIGHT;
5115 Header.dwPitchOrLinearSize := fRowSize;
5116 Header.dwMipMapCount := 1;
5119 Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
5122 Header.PixelFormat.dwSize := Sizeof(Header.PixelFormat);
5123 Header.PixelFormat.dwFlags := DDPF_RGB;
5125 if FormatHasAlpha(InternalFormat) and (InternalFormat <> ifAlpha)
5126 then Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
5128 Header.PixelFormat.dwRGBBitCount := Trunc(FormatGetSize(InternalFormat) * 8);
5129 Header.PixelFormat.dwRBitMask := Pix.PixelDesc.RedRange shl Pix.PixelDesc.RedShift;
5130 Header.PixelFormat.dwGBitMask := Pix.PixelDesc.GreenRange shl Pix.PixelDesc.GreenShift;
5131 Header.PixelFormat.dwBBitMask := Pix.PixelDesc.BlueRange shl Pix.PixelDesc.BlueShift;
5132 Header.PixelFormat.dwAlphaBitMask := Pix.PixelDesc.AlphaRange shl Pix.PixelDesc.AlphaShift;
5135 Stream.Write(Header, SizeOf(Header));
5137 Stream.Write(Data^, FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat));
5141 procedure TglBitmap.SaveTGA(Stream: TStream);
5148 procedure ConvertData(pTemp: pByte);
5150 Idx, PixelSize: Integer;
5153 PixelSize := fPixelSize;
5155 for Idx := 1 to Height * Width do begin
5156 Temp := pByteArray(pTemp)^[2];
5157 pByteArray(pTemp)^[2] := pByteArray(pTemp)^[0];
5158 pByteArray(pTemp)^[0] := Temp;
5160 Inc(pTemp, PixelSize);
5166 if not (ftTGA in FormatGetSupportedFiles (InternalFormat)) then
5167 raise EglBitmapUnsupportedInternalFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT);
5169 FillChar(Header, SizeOf(Header), 0);
5171 case InternalFormat of
5172 ifAlpha, ifLuminance, ifDepth8:
5174 Header.ImageType := TGA_UNCOMPRESSED_GRAY;
5179 Header.ImageType := TGA_UNCOMPRESSED_GRAY;
5184 Header.ImageType := TGA_UNCOMPRESSED_RGB;
5189 Header.ImageType := TGA_UNCOMPRESSED_RGB;
5193 raise EglBitmapUnsupportedInternalFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT);
5196 Header.Width := Width;
5197 Header.Height := Height;
5198 Header.ImageDes := $20;
5200 if FormatHasAlpha(InternalFormat) then
5201 Header.ImageDes := Header.ImageDes or $08;
5203 Stream.Write(Header, SizeOf(Header));
5205 // convert RGB(A) to BGR(A)
5206 Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat);
5207 if InternalFormat in [ifRGB8, ifRGBA8] then begin
5208 GetMem(pTemp, Size);
5214 if InternalFormat in [ifRGB8, ifRGBA8] then begin
5215 Move(Data^, pTemp^, Size);
5220 Stream.Write(pTemp^, Size);
5223 if InternalFormat in [ifRGB8, ifRGBA8] then
5229 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
5230 procedure TglBitmap.SaveJPEG(Stream: TStream);
5231 {$IFDEF GLB_LIB_JPEG}
5233 jpeg: jpeg_compress_struct;
5234 jpeg_err: jpeg_error_mgr;
5236 pTemp, pTemp2: pByte;
5239 procedure CopyRow(pDest, pSource: pByte);
5243 for X := 0 to Width - 1 do begin
5244 pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
5245 pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
5246 pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
5254 if not (ftJPEG in FormatGetSupportedFiles(InternalFormat)) then
5255 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
5257 if not init_libJPEG then
5258 raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
5261 FillChar(jpeg, SizeOf(jpeg_compress_struct), $00);
5262 FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
5265 jpeg.err := jpeg_std_error(@jpeg_err);
5266 jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
5267 jpeg_err.output_message := glBitmap_libJPEG_output_message;
5269 // compression struct
5270 jpeg_create_compress(@jpeg);
5272 // allocation space for streaming methods
5273 jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
5275 // seeting up custom functions
5276 with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
5277 pub.init_destination := glBitmap_libJPEG_init_destination;
5278 pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
5279 pub.term_destination := glBitmap_libJPEG_term_destination;
5281 pub.next_output_byte := @DestBuffer[1];
5282 pub.free_in_buffer := Length(DestBuffer);
5284 DestStream := Stream;
5287 // very important state
5288 jpeg.global_state := CSTATE_START;
5290 jpeg.image_width := Width;
5291 jpeg.image_height := Height;
5292 case InternalFormat of
5293 ifAlpha, ifLuminance, ifDepth8:
5295 jpeg.input_components := 1;
5296 jpeg.in_color_space := JCS_GRAYSCALE;
5300 jpeg.input_components := 3;
5301 jpeg.in_color_space := JCS_RGB;
5306 jpeg_set_defaults(@jpeg);
5308 // compression quality
5309 jpeg_set_quality(@jpeg, 95, True);
5311 // start compression
5312 jpeg_start_compress(@jpeg, true);
5318 if InternalFormat = ifBGR8 then
5319 GetMem(pTemp2, fRowSize)
5324 for Row := 0 to jpeg.image_height -1 do begin
5326 if InternalFormat = ifBGR8 then
5327 CopyRow(pTemp2, pTemp)
5332 jpeg_write_scanlines(@jpeg, @pTemp2, 1);
5333 inc(pTemp, fRowSize);
5337 if InternalFormat = ifBGR8 then
5341 // finish compression
5342 jpeg_finish_compress(@jpeg);
5344 // destroy compression
5345 jpeg_destroy_compress(@jpeg);
5351 {$IFDEF GLB_DELPHI_JPEG}
5356 if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then
5357 raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
5359 Bmp := TBitmap.Create;
5361 Jpg := TJPEGImage.Create;
5363 AssignToBitmap(Bmp);
5365 if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
5366 Jpg.Grayscale := True;
5367 Jpg.PixelFormat := jf8Bit;
5372 Jpg.SaveToStream(Stream);
5384 procedure TglBitmap.SaveBMP(Stream: TStream);
5388 pData, pTemp: pByte;
5390 PixelFormat: TglBitmapPixelData;
5391 ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer;
5392 Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
5394 PaddingBuff: Cardinal;
5397 function GetLineWidth : Integer;
5399 Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
5404 if not (ftBMP in FormatGetSupportedFiles(InternalFormat)) then
5405 raise EglBitmapUnsupportedInternalFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT);
5407 ImageSize := Trunc(Width * Height * FormatGetSize(InternalFormat));
5409 Header.bfType := BMP_MAGIC;
5410 Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
5411 Header.bfReserved1 := 0;
5412 Header.bfReserved2 := 0;
5413 Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
5415 FillChar(Info, SizeOf(Info), 0);
5416 Info.biSize := SizeOf(Info);
5417 Info.biWidth := Width;
5418 Info.biHeight := Height;
5420 Info.biCompression := BMP_COMP_RGB;
5421 Info.biSizeImage := ImageSize;
5422 case InternalFormat of
5423 ifAlpha, ifLuminance, ifDepth8:
5425 Info.biBitCount := 8;
5427 Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
5428 Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal);
5430 Info.biClrUsed := 256;
5431 Info.biClrImportant := 256;
5433 ifLuminanceAlpha, ifRGBA4, ifR5G6B5, ifRGB5A1:
5435 Info.biBitCount := 16;
5436 Info.biCompression := BMP_COMP_BITFIELDS;
5439 Info.biBitCount := 24;
5440 ifBGRA8, ifRGBA8, ifRGB10A2:
5442 Info.biBitCount := 32;
5443 Info.biCompression := BMP_COMP_BITFIELDS;
5446 raise EglBitmapUnsupportedInternalFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT);
5448 Info.biXPelsPerMeter := 2835;
5449 Info.biYPelsPerMeter := 2835;
5452 if Info.biCompression = BMP_COMP_BITFIELDS then begin
5453 Info.biSize := Info.biSize + 4 * SizeOf(Cardinal);
5454 Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
5455 Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
5457 FormatPreparePixel(PixelFormat, InternalFormat);
5459 with PixelFormat.PixelDesc do begin
5460 RedMask := RedRange shl RedShift;
5461 GreenMask := GreenRange shl GreenShift;
5462 BlueMask := BlueRange shl BlueShift;
5463 AlphaMask := AlphaRange shl AlphaShift;
5468 Stream.Write(Header, SizeOf(Header));
5469 Stream.Write(Info, SizeOf(Info));
5472 if Info.biBitCount = 8 then begin
5474 for ColorIdx := Low(Byte) to High(Byte) do begin
5475 Stream.Write(Temp, 4);
5476 Temp := Temp + $00010101;
5481 if Info.biCompression = BMP_COMP_BITFIELDS then begin
5482 Stream.Write(RedMask, SizeOf(Cardinal));
5483 Stream.Write(GreenMask, SizeOf(Cardinal));
5484 Stream.Write(BlueMask, SizeOf(Cardinal));
5485 Stream.Write(AlphaMask, SizeOf(Cardinal));
5489 LineSize := Trunc(Width * FormatGetSize(InternalFormat));
5490 Padding := GetLineWidth - LineSize;
5494 Inc(pData, (Height -1) * LineSize);
5496 // prepare row buffer. But only for RGB because RGBA supports color masks
5497 // so it's possible to change color within the image.
5498 if InternalFormat = ifRGB8 then
5499 GetMem(pTemp, fRowSize)
5505 for LineIdx := 0 to Height - 1 do begin
5507 if InternalFormat = ifRGB8 then begin
5508 Move(pData^, pTemp^, fRowSize);
5509 SwapRGB(pTemp, Width, False);
5513 Stream.Write(pTemp^, LineSize);
5515 Dec(pData, LineSize);
5518 Stream.Write(PaddingBuff, Padding);
5521 // destroy row buffer
5522 if InternalFormat = ifRGB8 then
5528 procedure TglBitmap.Bind(EnableTextureUnit: Boolean);
5530 if EnableTextureUnit then
5534 glBindTexture(Target, ID);
5538 procedure TglBitmap.Unbind(DisableTextureUnit: Boolean);
5540 if DisableTextureUnit then
5543 glBindTexture(Target, 0);
5547 procedure TglBitmap.GetPixel(const Pos: TglBitmapPixelPosition;
5548 var Pixel: TglBitmapPixelData);
5550 if Assigned (fGetPixelFunc) then
5551 fGetPixelFunc(Pos, Pixel);
5555 procedure TglBitmap.SetPixel (const Pos: TglBitmapPixelPosition;
5556 const Pixel: TglBitmapPixelData);
5558 if Assigned (fSetPixelFunc) then
5559 fSetPixelFunc(Pos, Pixel);
5563 procedure TglBitmap.CreateID;
5567 glDeleteTextures(1, @ID);
5569 glGenTextures(1, @ID);
5575 procedure TglBitmap.SetupParameters(var BuildWithGlu: Boolean);
5577 // Set up parameters
5578 SetWrap(fWrapS, fWrapT, fWrapR);
5579 SetFilter(fFilterMin, fFilterMag);
5580 SetAnisotropic(fAnisotropic);
5581 SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
5583 // Mip Maps generation Mode
5584 BuildWithGlu := False;
5586 if (MipMap = mmMipmap) then begin
5587 if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
5588 glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
5590 BuildWithGlu := True;
5592 if (MipMap = mmMipmapGlu) then
5593 BuildWithGlu := True;
5597 procedure TglBitmap.SelectFormat(DataFormat: TglBitmapInternalFormat; var glFormat, glInternalFormat, glType: Cardinal; CanConvertImage: Boolean = True);
5601 if not GL_VERSION_1_2 then
5602 raise EglBitmapUnsupportedInternalFormat.Create('SelectFormat - You need at least OpenGL 1.2 to support these format.');
5606 glType := GL_UNSIGNED_BYTE;
5611 glFormat := GL_ALPHA;
5613 glFormat := GL_LUMINANCE;
5615 glFormat := GL_DEPTH_COMPONENT;
5617 glFormat := GL_LUMINANCE_ALPHA;
5620 if (GL_VERSION_1_2 or GL_EXT_bgra) then begin
5623 if CanConvertImage then
5630 if (GL_VERSION_1_2 or GL_EXT_bgra) then begin
5631 glFormat := GL_BGRA;
5633 if CanConvertImage then
5635 glFormat := GL_RGBA;
5641 glFormat := GL_RGBA;
5645 glFormat := GL_BGRA;
5646 glType := GL_UNSIGNED_SHORT_4_4_4_4_REV;
5651 glFormat := GL_BGRA;
5652 glType := GL_UNSIGNED_SHORT_1_5_5_5_REV;
5657 glFormat := GL_BGRA;
5658 glType := GL_UNSIGNED_INT_2_10_10_10_REV;
5664 glType := GL_UNSIGNED_SHORT_5_6_5;
5670 // Selecting InternalFormat
5672 ifDXT1, ifDXT3, ifDXT5:
5674 if GL_EXT_texture_compression_s3tc then begin
5677 glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
5679 glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
5681 glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
5684 // Compression isn't supported so convert to RGBA
5685 if CanConvertImage then
5687 glFormat := GL_RGBA;
5688 glInternalFormat := GL_RGBA8;
5695 glInternalFormat := GL_ALPHA4;
5697 glInternalFormat := GL_ALPHA8;
5700 if (GL_ARB_texture_compression or GL_VERSION_1_3) then
5701 glInternalFormat := GL_COMPRESSED_ALPHA
5703 glInternalFormat := GL_ALPHA;
5706 glInternalFormat := GL_ALPHA;
5713 glInternalFormat := GL_LUMINANCE4;
5715 glInternalFormat := GL_LUMINANCE8;
5718 if (GL_ARB_texture_compression or GL_VERSION_1_3) then
5719 glInternalFormat := GL_COMPRESSED_LUMINANCE
5721 glInternalFormat := GL_LUMINANCE;
5724 glInternalFormat := GL_LUMINANCE;
5729 glInternalFormat := GL_DEPTH_COMPONENT;
5735 glInternalFormat := GL_LUMINANCE4_ALPHA4;
5737 glInternalFormat := GL_LUMINANCE8_ALPHA8;
5740 if (GL_ARB_texture_compression or GL_VERSION_1_3) then
5741 glInternalFormat := GL_COMPRESSED_LUMINANCE_ALPHA
5743 glInternalFormat := GL_LUMINANCE_ALPHA;
5746 glInternalFormat := GL_LUMINANCE_ALPHA;
5753 glInternalFormat := GL_RGB4;
5755 glInternalFormat := GL_RGB8;
5758 if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin
5759 glInternalFormat := GL_COMPRESSED_RGB
5761 if (GL_EXT_texture_compression_s3tc) then
5762 glInternalFormat := GL_COMPRESSED_RGB_S3TC_DXT1_EXT
5764 glInternalFormat := GL_RGB;
5768 glInternalFormat := GL_RGB;
5771 ifBGRA8, ifRGBA8, ifRGBA4, ifRGB5A1, ifRGB10A2, ifR5G6B5:
5775 glInternalFormat := GL_RGBA4;
5777 glInternalFormat := GL_RGBA8;
5780 if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin
5781 glInternalFormat := GL_COMPRESSED_RGBA
5783 if (GL_EXT_texture_compression_s3tc) then
5784 glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
5786 glInternalFormat := GL_RGBA;
5790 glInternalFormat := GL_RGBA;
5797 function TglBitmap.FlipHorz: Boolean;
5803 function TglBitmap.FlipVert: Boolean;
5809 procedure TglBitmap.FreeData;
5811 SetDataPointer(nil, ifEmpty);
5815 procedure glBitmapFillWithColorFunc(var FuncRec: TglBitmapFunctionRec);
5817 PglBitmapPixelData = ^TglBitmapPixelData;
5819 with FuncRec do begin
5820 Dest.Red := PglBitmapPixelData(CustomData)^.Red;
5821 Dest.Green := PglBitmapPixelData(CustomData)^.Green;
5822 Dest.Blue := PglBitmapPixelData(CustomData)^.Blue;
5823 Dest.Alpha := PglBitmapPixelData(CustomData)^.Alpha;
5828 procedure TglBitmap.FillWithColor(Red, Green, Blue: Byte; Alpha: Byte);
5830 FillWithColorFloat(Red / $FF, Green / $FF, Blue / $FF, Alpha / $FF);
5834 procedure TglBitmap.FillWithColorFloat(Red, Green, Blue: Single; Alpha: Single);
5836 PixelData: TglBitmapPixelData;
5838 FormatPreparePixel(PixelData, InternalFormat);
5840 PixelData.Red := Max(0, Min(PixelData.PixelDesc.RedRange, Trunc(PixelData.PixelDesc.RedRange * Red)));
5841 PixelData.Green := Max(0, Min(PixelData.PixelDesc.GreenRange, Trunc(PixelData.PixelDesc.GreenRange * Green)));
5842 PixelData.Blue := Max(0, Min(PixelData.PixelDesc.BlueRange, Trunc(PixelData.PixelDesc.BlueRange * Blue)));
5843 PixelData.Alpha := Max(0, Min(PixelData.PixelDesc.AlphaRange, Trunc(PixelData.PixelDesc.AlphaRange * Alpha)));
5845 AddFunc(glBitmapFillWithColorFunc, False, @PixelData);
5849 procedure TglBitmap.FillWithColorRange(Red, Green, Blue: Cardinal;
5852 PixelData: TglBitmapPixelData;
5854 FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
5857 Red / PixelData.PixelDesc.RedRange,
5858 Green / PixelData.PixelDesc.GreenRange,
5859 Blue / PixelData.PixelDesc.BlueRange,
5860 Alpha / PixelData.PixelDesc.AlphaRange);
5864 procedure TglBitmap.SetAnisotropic(const aValue: Integer);
5868 fAnisotropic := Value;
5870 if (ID > 0) then begin
5871 if GL_EXT_texture_filter_anisotropic then begin
5872 if fAnisotropic > 0 then begin
5875 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAniso);
5877 if Value > MaxAniso then
5878 fAnisotropic := MaxAniso;
5880 glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
5889 procedure TglBitmap.SetInternalFormat(const aValue: TglBitmapInternalFormat);
5891 if InternalFormat <> Value then begin
5892 if FormatGetSize(Value) <> FormatGetSize(InternalFormat) then
5893 raise EglBitmapUnsupportedInternalFormat.Create('SetInternalFormat - ' + UNSUPPORTED_INTERNAL_FORMAT);
5896 SetDataPointer(Data, Value);
5901 function TglBitmap.AddFunc(Func: TglBitmapFunction; CreateTemp: Boolean;
5902 CustomData: Pointer): boolean;
5904 Result := AddFunc(Self, Func, CreateTemp, InternalFormat, CustomData);
5908 function TglBitmap.AddFunc(Source: TglBitmap; Func: TglBitmapFunction;
5909 CreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer): boolean;
5911 pDest, NewImage, pSource: pByte;
5912 TempHeight, TempWidth: Integer;
5913 MapFunc: TglBitmapMapFunc;
5914 UnMapFunc: TglBitmapUnMapFunc;
5916 FuncRec: TglBitmapFunctionRec;
5918 Assert(Assigned(Data));
5919 Assert(Assigned(Source));
5920 Assert(Assigned(Source.Data));
5924 if Assigned (Source.Data) and FormatIsUncompressed(Format) and
5925 ((Source.Height > 0) or (Source.Width > 0)) then begin
5927 // inkompatible Formats so CreateTemp
5928 if FormatGetSize(Format) <> FormatGetSize(InternalFormat) then
5932 TempHeight := Max(1, Source.Height);
5933 TempWidth := Max(1, Source.Width);
5935 FuncRec.Sender := Self;
5936 FuncRec.CustomData := CustomData;
5940 if CreateTemp then begin
5941 GetMem(NewImage, Trunc(FormatGetSize(Format) * TempHeight * TempWidth));
5948 MapFunc := FormatGetMapFunc(Format);
5949 FormatPreparePixel(FuncRec.Dest, Format);
5950 FormatPreparePixel(FuncRec.Source, Source.InternalFormat);
5952 FuncRec.Size := Source.Dimension;
5953 FuncRec.Position.Fields := FuncRec.Size.Fields;
5955 if FormatIsUncompressed(Source.InternalFormat) then begin
5956 // Uncompressed Images
5957 pSource := Source.Data;
5958 UnMapFunc := FormatGetUnMapFunc(Source.InternalFormat);
5960 FuncRec.Position.Y := 0;
5961 while FuncRec.Position.Y < TempHeight do begin
5962 FuncRec.Position.X := 0;
5963 while FuncRec.Position.X < TempWidth do begin
5965 UnMapFunc(pSource, FuncRec.Source);
5969 MapFunc(FuncRec.Dest, pDest);
5970 Inc(FuncRec.Position.X);
5972 Inc(FuncRec.Position.Y);
5975 // Compressed Images
5976 FuncRec.Position.Y := 0;
5977 while FuncRec.Position.Y < TempHeight do begin
5978 FuncRec.Position.X := 0;
5979 while FuncRec.Position.X < TempWidth do begin
5981 fGetPixelFunc(FuncRec.Position, FuncRec.Source);
5985 MapFunc(FuncRec.Dest, pDest);
5986 Inc(FuncRec.Position.X);
5988 Inc(FuncRec.Position.Y);
5992 // Updating Image or InternalFormat
5994 SetDataPointer(NewImage, Format)
5997 if Format <> InternalFormat then
5998 SetInternalFormat(Format);
6003 then FreeMem(NewImage);
6010 procedure glBitmapConvertCopyFunc(var FuncRec: TglBitmapFunctionRec);
6012 with FuncRec do begin
6013 if Source.PixelDesc.RedRange > 0 then
6014 Dest.Red := Source.Red;
6016 if Source.PixelDesc.GreenRange > 0 then
6017 Dest.Green := Source.Green;
6019 if Source.PixelDesc.BlueRange > 0 then
6020 Dest.Blue := Source.Blue;
6022 if Source.PixelDesc.AlphaRange > 0 then
6023 Dest.Alpha := Source.Alpha;
6028 procedure glBitmapConvertCalculateRGBAFunc(var FuncRec: TglBitmapFunctionRec);
6030 with FuncRec do begin
6031 if Source.PixelDesc.RedRange > 0 then
6032 Dest.Red := Round(Dest.PixelDesc.RedRange * Source.Red / Source.PixelDesc.RedRange);
6034 if Source.PixelDesc.GreenRange > 0 then
6035 Dest.Green := Round(Dest.PixelDesc.GreenRange * Source.Green / Source.PixelDesc.GreenRange);
6037 if Source.PixelDesc.BlueRange > 0 then
6038 Dest.Blue := Round(Dest.PixelDesc.BlueRange * Source.Blue / Source.PixelDesc.BlueRange);
6040 if Source.PixelDesc.AlphaRange > 0 then
6041 Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Source.Alpha / Source.PixelDesc.AlphaRange);
6046 procedure glBitmapConvertShiftRGBAFunc(var FuncRec: TglBitmapFunctionRec);
6049 with TglBitmapPixelDesc(CustomData^) do begin
6050 if Source.PixelDesc.RedRange > 0 then
6051 Dest.Red := Source.Red shr RedShift;
6053 if Source.PixelDesc.GreenRange > 0 then
6054 Dest.Green := Source.Green shr GreenShift;
6056 if Source.PixelDesc.BlueRange > 0 then
6057 Dest.Blue := Source.Blue shr BlueShift;
6059 if Source.PixelDesc.AlphaRange > 0 then
6060 Dest.Alpha := Source.Alpha shr AlphaShift;
6065 function TglBitmap.ConvertTo(NewFormat: TglBitmapInternalFormat): boolean;
6067 Source, Dest: TglBitmapPixelData;
6068 PixelDesc: TglBitmapPixelDesc;
6070 function CopyDirect: Boolean;
6073 ((Source.PixelDesc.RedRange = Dest.PixelDesc.RedRange) or (Source.PixelDesc.RedRange = 0) or (Dest.PixelDesc.RedRange = 0)) and
6074 ((Source.PixelDesc.GreenRange = Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and
6075 ((Source.PixelDesc.BlueRange = Dest.PixelDesc.BlueRange) or (Source.PixelDesc.BlueRange = 0) or (Dest.PixelDesc.BlueRange = 0)) and
6076 ((Source.PixelDesc.AlphaRange = Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0));
6079 function CanShift: Boolean;
6082 ((Source.PixelDesc.RedRange >= Dest.PixelDesc.RedRange ) or (Source.PixelDesc.RedRange = 0) or (Dest.PixelDesc.RedRange = 0)) and
6083 ((Source.PixelDesc.GreenRange >= Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and
6084 ((Source.PixelDesc.BlueRange >= Dest.PixelDesc.BlueRange ) or (Source.PixelDesc.BlueRange = 0) or (Dest.PixelDesc.BlueRange = 0)) and
6085 ((Source.PixelDesc.AlphaRange >= Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0));
6088 function GetShift(Source, Dest: Cardinal) : ShortInt;
6092 while (Source > Dest) and (Source > 0) do begin
6094 Source := Source shr 1;
6099 if NewFormat <> InternalFormat then begin
6100 FormatPreparePixel(Source, InternalFormat);
6101 FormatPreparePixel(Dest, NewFormat);
6104 Result := AddFunc(Self, glBitmapConvertCopyFunc, False, NewFormat)
6106 if CanShift then begin
6107 PixelDesc.RedShift := GetShift(Source.PixelDesc.RedRange, Dest.PixelDesc.RedRange);
6108 PixelDesc.GreenShift := GetShift(Source.PixelDesc.GreenRange, Dest.PixelDesc.GreenRange);
6109 PixelDesc.BlueShift := GetShift(Source.PixelDesc.BlueRange, Dest.PixelDesc.BlueRange);
6110 PixelDesc.AlphaShift := GetShift(Source.PixelDesc.AlphaRange, Dest.PixelDesc.AlphaRange);
6112 Result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, False, NewFormat, @PixelDesc);
6114 else Result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, False, NewFormat);
6116 else Result := True;
6120 function TglBitmap.RemoveAlpha: Boolean;
6124 if (Assigned(Data)) then begin
6125 if not (FormatIsUncompressed(InternalFormat) or FormatHasAlpha(InternalFormat)) then
6126 raise EglBitmapUnsupportedInternalFormat.Create('RemoveAlpha - ' + UNSUPPORTED_INTERNAL_FORMAT);
6128 Result := ConvertTo(FormatGetWithoutAlpha(InternalFormat));
6133 function TglBitmap.AddAlphaFromFunc(Func: TglBitmapFunction; CustomData: Pointer): boolean;
6135 if not FormatIsUncompressed(InternalFormat) then
6136 raise EglBitmapUnsupportedInternalFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_INTERNAL_FORMAT);
6138 Result := AddFunc(Self, Func, False, FormatGetWithAlpha(InternalFormat), CustomData);
6142 function TglBitmap.GetHeight: Integer;
6144 if ffY in fDimension.Fields then
6145 Result := fDimension.Y
6151 function TglBitmap.GetWidth: Integer;
6153 if ffX in fDimension.Fields then
6154 Result := fDimension.X
6160 function TglBitmap.GetFileHeight: Integer;
6162 Result := Max(1, Height);
6166 function TglBitmap.GetFileWidth: Integer;
6168 Result := Max(1, Width);
6172 procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
6176 with FuncRec do begin
6178 Source.Red / Source.PixelDesc.RedRange * 0.3 +
6179 Source.Green / Source.PixelDesc.GreenRange * 0.59 +
6180 Source.Blue / Source.PixelDesc.BlueRange * 0.11;
6182 Dest.Alpha := Round (Dest.PixelDesc.AlphaRange * Temp);
6187 function TglBitmap.AddAlphaFromglBitmap(glBitmap: TglBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean;
6189 pDest, pDest2, pSource: pByte;
6190 TempHeight, TempWidth: Integer;
6191 MapFunc: TglBitmapMapFunc;
6192 DestUnMapFunc, UnMapFunc: TglBitmapUnMapFunc;
6194 FuncRec: TglBitmapFunctionRec;
6198 assert(Assigned(Data));
6199 assert(Assigned(glBitmap));
6200 assert(Assigned(glBitmap.Data));
6202 if ((glBitmap.Width = Width) and (glBitmap.Height = Height)) then begin
6203 // Convert to Data with Alpha
6204 Result := ConvertTo(FormatGetWithAlpha(FormatGetUncompressed(InternalFormat)));
6206 if not Assigned(Func) then
6207 Func := glBitmapAlphaFunc;
6210 TempHeight := glBitmap.FileHeight;
6211 TempWidth := glBitmap.FileWidth;
6213 FuncRec.Sender := Self;
6214 FuncRec.CustomData := CustomData;
6218 pSource := glBitmap.Data;
6221 FormatPreparePixel(FuncRec.Dest, InternalFormat);
6222 FormatPreparePixel(FuncRec.Source, glBitmap.InternalFormat);
6223 MapFunc := FormatGetMapFunc(InternalFormat);
6224 DestUnMapFunc := FormatGetUnMapFunc(InternalFormat);
6225 UnMapFunc := FormatGetUnMapFunc(glBitmap.InternalFormat);
6227 FuncRec.Size := Dimension;
6228 FuncRec.Position.Fields := FuncRec.Size.Fields;
6230 FuncRec.Position.Y := 0;
6231 while FuncRec.Position.Y < TempHeight do begin
6232 FuncRec.Position.X := 0;
6233 while FuncRec.Position.X < TempWidth do begin
6235 UnMapFunc(pSource, FuncRec.Source);
6236 DestUnMapFunc(pDest2, FuncRec.Dest);
6240 MapFunc(FuncRec.Dest, pDest);
6241 Inc(FuncRec.Position.X);
6243 Inc(FuncRec.Position.Y);
6249 procedure TglBitmap.SetBorderColor(Red, Green, Blue, Alpha: Single);
6251 fBorderColor[0] := Red;
6252 fBorderColor[1] := Green;
6253 fBorderColor[2] := Blue;
6254 fBorderColor[3] := Alpha;
6256 if ID > 0 then begin
6259 glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
6266 procedure TglBitmap2D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
6268 Idx, LineWidth: Integer;
6273 if FormatIsUncompressed(Format) then begin
6274 fUnmapFunc := FormatGetUnMapFunc(Format);
6275 fGetPixelFunc := GetPixel2DUnmap;
6277 fMapFunc := FormatGetMapFunc(Format);
6278 fSetPixelFunc := SetPixel2DUnmap;
6281 if Assigned(Data) then begin
6282 SetLength(fLines, GetHeight);
6284 LineWidth := Trunc(GetWidth * FormatGetSize(InternalFormat));
6286 for Idx := 0 to GetHeight -1 do begin
6287 fLines[Idx] := Data;
6288 Inc(fLines[Idx], Idx * LineWidth);
6291 else SetLength(fLines, 0);
6293 SetLength(fLines, 0);
6295 fSetPixelFunc := nil;
6299 fGetPixelFunc := GetPixel2DDXT1;
6301 fGetPixelFunc := GetPixel2DDXT3;
6303 fGetPixelFunc := GetPixel2DDXT5;
6305 fGetPixelFunc := nil;
6311 procedure TglBitmap2D.GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
6313 PDXT1Chunk = ^TDXT1Chunk;
6314 TDXT1Chunk = packed record
6317 Pixels: array [0..3] of byte;
6321 BasePtr: pDXT1Chunk;
6323 Colors: array [0..3] of TRGBQuad;
6325 BasePtr := pDXT1Chunk(pData);
6327 PixPos := BasePtr^.Pixels[relY] shr (relX * 2) and $3;
6329 if PixPos in [0, 2, 3] then begin
6330 Colors[0].rgbRed := BasePtr^.Color1 and $F800 shr 8;
6331 Colors[0].rgbGreen := BasePtr^.Color1 and $07E0 shr 3;
6332 Colors[0].rgbBlue := BasePtr^.Color1 and $001F shl 3;
6333 Colors[0].rgbReserved := 255;
6336 if PixPos in [1, 2, 3] then begin
6337 Colors[1].rgbRed := BasePtr^.Color2 and $F800 shr 8;
6338 Colors[1].rgbGreen := BasePtr^.Color2 and $07E0 shr 3;
6339 Colors[1].rgbBlue := BasePtr^.Color2 and $001F shl 3;
6340 Colors[1].rgbReserved := 255;
6343 if PixPos = 2 then begin
6344 Colors[2].rgbRed := (Colors[0].rgbRed * 67 + Colors[1].rgbRed * 33) div 100;
6345 Colors[2].rgbGreen := (Colors[0].rgbGreen * 67 + Colors[1].rgbGreen * 33) div 100;
6346 Colors[2].rgbBlue := (Colors[0].rgbBlue * 67 + Colors[1].rgbBlue * 33) div 100;
6347 Colors[2].rgbReserved := 255;
6350 if PixPos = 3 then begin
6351 Colors[3].rgbRed := (Colors[0].rgbRed * 33 + Colors[1].rgbRed * 67) div 100;
6352 Colors[3].rgbGreen := (Colors[0].rgbGreen * 33 + Colors[1].rgbGreen * 67) div 100;
6353 Colors[3].rgbBlue := (Colors[0].rgbBlue * 33 + Colors[1].rgbBlue * 67) div 100;
6354 if BasePtr^.Color1 > BasePtr^.Color2 then
6355 Colors[3].rgbReserved := 255
6357 Colors[3].rgbReserved := 0;
6360 Pixel.Red := Colors[PixPos].rgbRed;
6361 Pixel.Green := Colors[PixPos].rgbGreen;
6362 Pixel.Blue := Colors[PixPos].rgbBlue;
6363 Pixel.Alpha := Colors[PixPos].rgbReserved;
6367 procedure TglBitmap2D.GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
6370 PosX, PosY: Integer;
6374 if (Pos.Y <= Height) and (Pos.X <= Width) then begin
6375 PosX := Pos.X div 4;
6376 PosY := Pos.Y div 4;
6379 Inc(BasePtr, (PosY * Width div 4 + PosX) * 8);
6381 GetDXTColorBlock(BasePtr, Pos.X - PosX * 4, Pos.Y - PosY * 4, Pixel);
6386 procedure TglBitmap2D.GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
6388 PDXT3AlphaChunk = ^TDXT3AlphaChunk;
6389 TDXT3AlphaChunk = array [0..3] of WORD;
6393 AlphaPtr: PDXT3AlphaChunk;
6394 PosX, PosY, relX, relY: Integer;
6398 if (Pos.Y <= Height) and (Pos.X <= Width) then begin
6399 PosX := Pos.X div 4;
6400 PosY := Pos.Y div 4;
6401 relX := Pos.X - PosX * 4;
6402 relY := Pos.Y - PosY * 4;
6405 AlphaPtr := PDXT3AlphaChunk(Data);
6406 Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2);
6408 ColorPtr := pByte(AlphaPtr);
6411 GetDXTColorBlock(ColorPtr, relX, relY, Pixel);
6414 Pixel.Alpha := AlphaPtr^[relY] shr (4 * relX) and $0F shl 4;
6419 procedure TglBitmap2D.GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
6423 PixPos, PosX, PosY, relX, relY: Integer;
6424 Alpha0, Alpha1: Byte;
6428 if (Pos.Y <= Height) and (Pos.X <= Width) then begin
6429 PosX := Pos.X div 4;
6430 PosY := Pos.Y div 4;
6431 relX := Pos.X - PosX * 4;
6432 relY := Pos.Y - PosY * 4;
6435 AlphaPtr := PInt64(Data);
6436 Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2);
6438 ColorPtr := pByte(AlphaPtr);
6441 GetDXTColorBlock(ColorPtr, relX, relY, Pixel);
6444 Alpha0 := AlphaPtr^ and $FF;
6445 Alpha1 := AlphaPtr^ shr 8 and $FF;
6447 PixPos := AlphaPtr^ shr (16 + (relY * 4 + relX) * 3) and $07;
6450 if PixPos = 0 then begin
6451 Pixel.Alpha := Alpha0;
6455 if PixPos = 1 then begin
6456 Pixel.Alpha := Alpha1;
6459 // alpha interpolate 7 Steps
6460 if Alpha0 > Alpha1 then begin
6461 Pixel.Alpha := ((8 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 7;
6464 // alpha is 100% transparent or not transparent
6465 if PixPos >= 6 then begin
6472 // alpha interpolate 5 Steps
6474 Pixel.Alpha := ((6 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 5;
6480 procedure TglBitmap2D.GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
6484 pTemp := fLines[Pos.Y];
6485 Inc(pTemp, Pos.X * fPixelSize);
6487 fUnmapFunc(pTemp, Pixel);
6491 procedure TglBitmap2D.SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
6495 pTemp := fLines[Pos.Y];
6496 Inc(pTemp, Pos.X * fPixelSize);
6498 fMapFunc(Pixel, pTemp);
6502 function TglBitmap2D.FlipHorz: Boolean;
6505 pTempDest, pDest, pSource: pByte;
6508 Result := Inherited FlipHorz;
6510 if Assigned(Data) then begin
6512 ImgSize := Height * fRowSize;
6514 GetMem(pDest, ImgSize);
6518 Dec(pTempDest, fRowSize + fPixelSize);
6519 for Row := 0 to Height -1 do begin
6520 Inc(pTempDest, fRowSize * 2);
6521 for Col := 0 to Width -1 do begin
6522 Move(pSource^, pTempDest^, fPixelSize);
6524 Inc(pSource, fPixelSize);
6525 Dec(pTempDest, fPixelSize);
6529 SetDataPointer(pDest, InternalFormat);
6540 function TglBitmap2D.FlipVert: Boolean;
6543 pTempDest, pDest, pSource: pByte;
6545 Result := Inherited FlipVert;
6547 if Assigned(Data) then begin
6549 GetMem(pDest, Height * fRowSize);
6553 Inc(pTempDest, Width * (Height -1) * fPixelSize);
6555 for Row := 0 to Height -1 do begin
6556 Move(pSource^, pTempDest^, fRowSize);
6558 Dec(pTempDest, fRowSize);
6559 Inc(pSource, fRowSize);
6562 SetDataPointer(pDest, InternalFormat);
6573 procedure TglBitmap2D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
6575 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6578 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
6579 glCompressedTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Trunc(Width * Height * FormatGetSize(Self.InternalFormat)), Data)
6582 if BuildWithGlu then
6583 gluBuild2DMipmaps(Target, InternalFormat, Width, Height, Format, Typ, Data)
6585 glTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Format, Typ, Data);
6588 if (FreeDataAfterGenTexture) then
6593 procedure TglBitmap2D.GenTexture(TestTextureSize: Boolean);
6595 BuildWithGlu, PotTex, TexRec: Boolean;
6596 glFormat, glInternalFormat, glType: Cardinal;
6599 if Assigned(Data) then begin
6600 // Check Texture Size
6601 if (TestTextureSize) then begin
6602 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
6604 if ((Height > TexSize) or (Width > TexSize)) then
6605 raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
6607 PotTex := IsPowerOfTwo (Height) and IsPowerOfTwo (Width);
6608 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
6609 (Target = GL_TEXTURE_RECTANGLE_ARB);
6611 if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
6612 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
6617 SetupParameters(BuildWithGlu);
6618 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
6620 UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
6623 glAreTexturesResident(1, @ID, @fIsResident);
6628 procedure TglBitmap2D.AfterConstruction;
6632 Target := GL_TEXTURE_2D;
6637 TMatrixItem = record
6642 PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
6643 TglBitmapToNormalMapRec = Record
6645 Heights: array of Single;
6646 MatrixU : array of TMatrixItem;
6647 MatrixV : array of TMatrixItem;
6651 oneover255 = 1 / 255;
6653 procedure glBitmapToNormalMapPrepareFunc (var FuncRec: TglBitmapFunctionRec);
6657 with FuncRec do begin
6658 Val := Source.Red * 0.3 + Source.Green * 0.59 + Source.Blue * 0.11;
6659 PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Val * oneover255;
6664 procedure glBitmapToNormalMapPrepareAlphaFunc (var FuncRec: TglBitmapFunctionRec);
6667 PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Source.Alpha * oneover255;
6671 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
6673 TVec = Array[0..2] of Single;
6680 function GetHeight(X, Y: Integer): Single;
6682 with FuncRec do begin
6683 X := Max(0, Min(Size.X -1, X));
6684 Y := Max(0, Min(Size.Y -1, Y));
6686 Result := PglBitmapToNormalMapRec (CustomData)^.Heights[Y * Size.X + X];
6691 with FuncRec do begin
6692 with PglBitmapToNormalMapRec (CustomData)^ do begin
6694 for Idx := Low(MatrixU) to High(MatrixU) do
6695 du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
6698 for Idx := Low(MatrixU) to High(MatrixU) do
6699 dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
6701 Vec[0] := -du * Scale;
6702 Vec[1] := -dv * Scale;
6707 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
6708 if Len <> 0 then begin
6709 Vec[0] := Vec[0] * Len;
6710 Vec[1] := Vec[1] * Len;
6711 Vec[2] := Vec[2] * Len;
6715 Dest.Red := Trunc((Vec[0] + 1) * 127.5);
6716 Dest.Green := Trunc((Vec[1] + 1) * 127.5);
6717 Dest.Blue := Trunc((Vec[2] + 1) * 127.5);
6722 procedure TglBitmap2D.ToNormalMap(Func: TglBitmapNormalMapFunc; Scale: Single; UseAlpha: Boolean);
6724 Rec: TglBitmapToNormalMapRec;
6726 procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
6728 if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
6729 Matrix[Index].X := X;
6730 Matrix[Index].Y := Y;
6731 Matrix[Index].W := W;
6736 if not FormatIsUncompressed(InternalFormat) then
6737 raise EglBitmapUnsupportedInternalFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_INTERNAL_FORMAT);
6742 if Scale < -100 then
6747 SetLength(Rec.Heights, Width * Height);
6752 SetLength(Rec.MatrixU, 2);
6753 SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
6754 SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
6756 SetLength(Rec.MatrixV, 2);
6757 SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
6758 SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
6762 SetLength(Rec.MatrixU, 6);
6763 SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
6764 SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
6765 SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
6766 SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
6767 SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
6768 SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
6770 SetLength(Rec.MatrixV, 6);
6771 SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
6772 SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
6773 SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
6774 SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
6775 SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
6776 SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
6780 SetLength(Rec.MatrixU, 6);
6781 SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
6782 SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
6783 SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
6784 SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
6785 SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
6786 SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
6788 SetLength(Rec.MatrixV, 6);
6789 SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
6790 SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
6791 SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
6792 SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
6793 SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
6794 SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
6798 SetLength(Rec.MatrixU, 20);
6799 SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
6800 SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
6801 SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
6802 SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
6803 SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
6804 SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
6805 SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
6806 SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
6807 SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
6808 SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
6809 SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
6810 SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
6811 SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
6812 SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
6813 SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
6814 SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
6815 SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
6816 SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
6817 SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
6818 SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
6820 SetLength(Rec.MatrixV, 20);
6821 SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
6822 SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
6823 SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
6824 SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
6825 SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
6826 SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
6827 SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
6828 SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
6829 SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
6830 SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
6831 SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
6832 SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
6833 SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
6834 SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
6835 SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
6836 SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
6837 SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
6838 SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
6839 SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
6840 SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
6845 if UseAlpha and FormatHasAlpha(InternalFormat) then
6846 AddFunc(glBitmapToNormalMapPrepareAlphaFunc, False, @Rec)
6848 AddFunc(glBitmapToNormalMapPrepareFunc, False, @Rec);
6850 // Neues Bild berechnen
6851 AddFunc(glBitmapToNormalMapFunc, False, @Rec);
6853 SetLength(Rec.Heights, 0);
6858 procedure TglBitmap2D.GrabScreen(Top, Left, Right, Bottom: Integer; Format: TglBitmapInternalFormat);
6862 glFormat, glInternalFormat, glType: Cardinal;
6864 if not FormatIsUncompressed(Format) then
6865 raise EglBitmapUnsupportedInternalFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_INTERNAL_FORMAT);
6867 // Only to select Formats
6868 SelectFormat(Format, glFormat, glInternalFormat, glType, False);
6870 Size := FormatGetImageSize(glBitmapPosition(Right - Left, Bottom - Top), Format);
6873 glPixelStorei(GL_PACK_ALIGNMENT, 1);
6874 glReadPixels(Left, Top, Right - Left, Bottom - Top, glFormat, glType, Temp);
6877 SetDataPointer(Temp, Format, Right - Left, Bottom - Top);
6888 procedure TglBitmap2D.GetDataFromTexture;
6891 TempWidth, TempHeight, RedSize, GreenSize, BlueSize, AlphaSize, LumSize: Integer;
6892 TempType, TempIntFormat: Cardinal;
6893 IntFormat: TglBitmapInternalFormat;
6898 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
6899 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
6900 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
6902 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_RED_SIZE, @RedSize);
6903 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_GREEN_SIZE, @GreenSize);
6904 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_BLUE_SIZE, @BlueSize);
6905 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_ALPHA_SIZE, @AlphaSize);
6906 glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_LUMINANCE_SIZE, @LumSize);
6908 // Get glBitmapInternalFormat from TempIntFormat
6909 TempType := GL_UNSIGNED_BYTE;
6910 case TempIntFormat of
6912 IntFormat := ifAlpha;
6914 IntFormat := ifLuminance;
6916 IntFormat := ifLuminanceAlpha;
6919 IntFormat := ifR5G6B5;
6920 TempIntFormat := GL_RGB;
6921 TempType := GL_UNSIGNED_SHORT_5_6_5;
6924 IntFormat := ifRGB8;
6925 GL_RGBA, GL_RGBA4, GL_RGBA8:
6927 if (RedSize = 4) and (BlueSize = 4) and (GreenSize = 4) and (AlphaSize = 4) then begin
6928 IntFormat := ifRGBA4;
6929 TempIntFormat := GL_BGRA;
6930 TempType := GL_UNSIGNED_SHORT_4_4_4_4_REV;
6932 if (RedSize = 5) and (BlueSize = 5) and (GreenSize = 5) and (AlphaSize = 1) then begin
6933 IntFormat := ifRGB5A1;
6934 TempIntFormat := GL_BGRA;
6935 TempType := GL_UNSIGNED_SHORT_1_5_5_5_REV;
6937 IntFormat := ifRGBA8;
6941 IntFormat := ifBGR8;
6943 IntFormat := ifBGRA8;
6944 GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
6945 IntFormat := ifDXT1;
6946 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
6947 IntFormat := ifDXT1;
6948 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
6949 IntFormat := ifDXT3;
6950 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
6951 IntFormat := ifDXT5;
6953 IntFormat := ifEmpty;
6956 // Getting data from OpenGL
6957 GetMem(Temp, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
6959 if FormatIsCompressed(IntFormat) and (GL_VERSION_1_3 or GL_ARB_texture_compression) then
6960 glGetCompressedTexImage(Target, 0, Temp)
6962 glGetTexImage(Target, 0, TempIntFormat, TempType, Temp);
6964 SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
6972 function TglBitmap2D.GetScanline(Index: Integer): Pointer;
6974 if (Index >= Low(fLines)) and (Index <= High(fLines)) then
6975 Result := fLines[Index]
6983 procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
6988 if Height > 1 then begin
6989 // extract first line of the data
6990 Size := FormatGetImageSize(glBitmapPosition(Width), Format);
6991 GetMem(pTemp, Size);
6993 Move(Data^, pTemp^, Size);
7000 inherited SetDataPointer(pTemp, Format, Width);
7002 if FormatIsUncompressed(Format) then begin
7003 fUnmapFunc := FormatGetUnMapFunc(Format);
7004 fGetPixelFunc := GetPixel1DUnmap;
7009 procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
7014 Inc(pTemp, Pos.X * fPixelSize);
7016 fUnmapFunc(pTemp, Pixel);
7020 function TglBitmap1D.FlipHorz: Boolean;
7023 pTempDest, pDest, pSource: pByte;
7025 Result := Inherited FlipHorz;
7027 if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin
7030 GetMem(pDest, fRowSize);
7034 Inc(pTempDest, fRowSize);
7035 for Col := 0 to Width -1 do begin
7036 Move(pSource^, pTempDest^, fPixelSize);
7038 Inc(pSource, fPixelSize);
7039 Dec(pTempDest, fPixelSize);
7042 SetDataPointer(pDest, InternalFormat);
7052 procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
7055 if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
7056 glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data)
7060 if BuildWithGlu then
7061 gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data)
7063 glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data);
7066 if (FreeDataAfterGenTexture) then
7071 procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean);
7073 BuildWithGlu, TexRec: Boolean;
7074 glFormat, glInternalFormat, glType: Cardinal;
7077 if Assigned(Data) then begin
7078 // Check Texture Size
7079 if (TestTextureSize) then begin
7080 glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
7082 if (Width > TexSize) then
7083 raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
7085 TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
7086 (Target = GL_TEXTURE_RECTANGLE_ARB);
7088 if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
7089 raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
7094 SetupParameters(BuildWithGlu);
7095 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
7097 UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
7100 glAreTexturesResident(1, @ID, @fIsResident);
7105 procedure TglBitmap1D.AfterConstruction;
7109 Target := GL_TEXTURE_1D;
7113 { TglBitmapCubeMap }
7115 procedure TglBitmapCubeMap.AfterConstruction;
7119 if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
7120 raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
7122 SetWrap; // set all to GL_CLAMP_TO_EDGE
7123 Target := GL_TEXTURE_CUBE_MAP;
7124 fGenMode := GL_REFLECTION_MAP;
7128 procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean);
7130 inherited Bind (EnableTextureUnit);
7132 if EnableTexCoordsGen then begin
7133 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
7134 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
7135 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
7136 glEnable(GL_TEXTURE_GEN_S);
7137 glEnable(GL_TEXTURE_GEN_T);
7138 glEnable(GL_TEXTURE_GEN_R);
7143 procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean);
7145 glFormat, glInternalFormat, glType: Cardinal;
7146 BuildWithGlu: Boolean;
7149 // Check Texture Size
7150 if (TestTextureSize) then begin
7151 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
7153 if ((Height > TexSize) or (Width > TexSize)) then
7154 raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
7156 if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
7157 raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
7161 if ID = 0 then begin
7163 SetupParameters(BuildWithGlu);
7166 SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
7168 UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu);
7172 procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean);
7174 Assert(False, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
7178 procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen,
7179 DisableTextureUnit: Boolean);
7181 inherited Unbind (DisableTextureUnit);
7183 if DisableTexCoordsGen then begin
7184 glDisable(GL_TEXTURE_GEN_S);
7185 glDisable(GL_TEXTURE_GEN_T);
7186 glDisable(GL_TEXTURE_GEN_R);
7191 { TglBitmapNormalMap }
7194 TVec = Array[0..2] of Single;
7195 TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7197 PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
7198 TglBitmapNormalMapRec = record
7200 Func: TglBitmapNormalMapGetVectorFunc;
7204 procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7207 Vec[1] := - (Position.Y + 0.5 - HalfSize);
7208 Vec[2] := - (Position.X + 0.5 - HalfSize);
7212 procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7214 Vec[0] := - HalfSize;
7215 Vec[1] := - (Position.Y + 0.5 - HalfSize);
7216 Vec[2] := Position.X + 0.5 - HalfSize;
7220 procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7222 Vec[0] := Position.X + 0.5 - HalfSize;
7224 Vec[2] := Position.Y + 0.5 - HalfSize;
7228 procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7230 Vec[0] := Position.X + 0.5 - HalfSize;
7231 Vec[1] := - HalfSize;
7232 Vec[2] := - (Position.Y + 0.5 - HalfSize);
7236 procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7238 Vec[0] := Position.X + 0.5 - HalfSize;
7239 Vec[1] := - (Position.Y + 0.5 - HalfSize);
7244 procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
7246 Vec[0] := - (Position.X + 0.5 - HalfSize);
7247 Vec[1] := - (Position.Y + 0.5 - HalfSize);
7248 Vec[2] := - HalfSize;
7252 procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
7257 with FuncRec do begin
7258 with PglBitmapNormalMapRec (CustomData)^ do begin
7259 Func(Vec, Position, HalfSize);
7262 Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
7263 if Len <> 0 then begin
7264 Vec[0] := Vec[0] * Len;
7265 Vec[1] := Vec[1] * Len;
7266 Vec[2] := Vec[2] * Len;
7269 // Scale Vector and AddVectro
7270 Vec[0] := Vec[0] * 0.5 + 0.5;
7271 Vec[1] := Vec[1] * 0.5 + 0.5;
7272 Vec[2] := Vec[2] * 0.5 + 0.5;
7276 Dest.Red := Round(Vec[0] * 255);
7277 Dest.Green := Round(Vec[1] * 255);
7278 Dest.Blue := Round(Vec[2] * 255);
7283 procedure TglBitmapNormalMap.AfterConstruction;
7287 fGenMode := GL_NORMAL_MAP;
7291 procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer;
7292 TestTextureSize: Boolean);
7294 Rec: TglBitmapNormalMapRec;
7295 SizeRec: TglBitmapPixelPosition;
7297 Rec.HalfSize := Size div 2;
7299 FreeDataAfterGenTexture := False;
7301 SizeRec.Fields := [ffX, ffY];
7306 Rec.Func := glBitmapNormalMapPosX;
7307 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
7308 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize);
7311 Rec.Func := glBitmapNormalMapNegX;
7312 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
7313 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize);
7316 Rec.Func := glBitmapNormalMapPosY;
7317 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
7318 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize);
7321 Rec.Func := glBitmapNormalMapNegY;
7322 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
7323 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize);
7326 Rec.Func := glBitmapNormalMapPosZ;
7327 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
7328 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize);
7331 Rec.Func := glBitmapNormalMapNegZ;
7332 LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
7333 GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize);
7339 glBitmapSetDefaultFormat(tfDefault);
7340 glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
7341 glBitmapSetDefaultWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
7343 glBitmapSetDefaultFreeDataAfterGenTexture(True);
7344 glBitmapSetDefaultDeleteTextureOnFree(True);