You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6826 lines
185 KiB

  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. ------------------------------------------------------------
  11. Version 2.0.3
  12. ------------------------------------------------------------
  13. History
  14. 21-03-2010
  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)
  20. 10-08-2008
  21. - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson)
  22. - Additional Datapointer for functioninterface now has the name CustomData
  23. 24-07-2008
  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)
  30. 27-05-2008
  31. - RLE TGAs loaded much faster
  32. 26-05-2008
  33. - fixed some problem with reading RLE TGAs.
  34. 21-05-2008
  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.
  37. 01-05-2008
  38. - It's possible to set the id of the texture
  39. - define GLB_NO_NATIVE_GL deactivated by default
  40. 27-04-2008
  41. - Now supports the following libraries
  42. - SDL and SDL_image
  43. - libPNG
  44. - libJPEG
  45. - Linux compatibillity via free pascal compatibility (delphi sources optional)
  46. - BMPs now loaded manuel
  47. - Large restructuring
  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
  52. 24-10-2007
  53. - ImageID flag of TGAs was ignored. (Thanks Zwoetzen)
  54. 15-11-2006
  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
  58. 29-06-2006
  59. - pngimage now disabled by default like all other versions.
  60. 26-06-2006
  61. - Setting up an anisotropic filter of 0 isnt allowed by nvidia (Thanks Ogridi)
  62. 22-06-2006
  63. - Fixed some Problem with Delphi 5
  64. - Now uses the newest version of pngimage. Makes saving pngs much easier.
  65. 22-03-2006
  66. - Property IsCompressed and Size removed. Not really supported by Spec (Thanks Ogridi)
  67. 09-03-2006
  68. - Internal Format ifDepth8 added
  69. - function GrabScreen now supports all uncompressed formats
  70. 31-01-2006
  71. - AddAlphaFromglBitmap implemented
  72. 29-12-2005
  73. - LoadFromResource and LoadFromResourceId now needs an Instance and an ResourceType (for ID)
  74. 28-12-2005
  75. - Width, Height and Depth internal changed to TglBitmapPixelPosition.
  76. property Width, Height, Depth are still existing and new property Dimension are avail
  77. 11-12-2005
  78. - Added native OpenGL Support. Breaking the dglOpenGL "barrier".
  79. 19-10-2005
  80. - Added function GrabScreen to class TglBitmap2D
  81. 18-10-2005
  82. - Added support to Save images
  83. - Added function Clone to Clone Instance
  84. 11-10-2005
  85. - Functions now works with Cardinals for each channel. Up to 32 Bits per channel.
  86. Usefull for Future
  87. - Several speed optimizations
  88. 09-10-2005
  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
  93. 06-10-2005
  94. - Added Support to decompress DXT3 and DXT5 compressed Images.
  95. - Added Mapping to convert data from one format into an other.
  96. 05-10-2005
  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
  101. 04-10-2005
  102. - Added Support for compressed DDSs
  103. - Added new internal formats (DXT1, DXT3, DXT5)
  104. 29-09-2005
  105. - Parameter Components renamed to InternalFormat
  106. 23-09-2005
  107. - Some AllocMem replaced with GetMem (little speed change)
  108. - better exception handling. Better protection from memory leaks.
  109. 22-09-2005
  110. - Added support for Direct Draw Surfaces (.DDS) (uncompressed images only)
  111. - Added new internal formats (RGB8, RGBA8, RGBA4, RGB5A1, RGB10A2, R5G6B5)
  112. 07-09-2005
  113. - Added support for Grayscale textures
  114. - Added internal formats (Alpha, Luminance, LuminanceAlpha, BGR8, BGRA8)
  115. 10-07-2005
  116. - Added support for GL_VERSION_2_0
  117. - Added support for GL_EXT_texture_filter_anisotropic
  118. 04-07-2005
  119. - Function FillWithColor fills the Image with one Color
  120. - Function LoadNormalMap added
  121. 30-06-2005
  122. - ToNormalMap allows to Create an NormalMap from the Alphachannel
  123. - ToNormalMap now supports Sobel (nmSobel) function.
  124. 29-06-2005
  125. - support for RLE Compressed RGB TGAs added
  126. 28-06-2005
  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)
  130. 16-06-2005
  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
  134. 12-06-2005
  135. - now support DescriptionFlag in LoadTga. Allows vertical flipped images to be loaded as normal
  136. 10-06-2005
  137. - little enhancement for IsPowerOfTwo
  138. - TglBitmap1D.GenTexture now tests NPOT Textures
  139. 06-06-2005
  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.
  142. 03-06-2005
  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.
  145. 02-06-2005
  146. - added support for GL_ARB_texture_rectangle, GL_EXT_texture_rectangle and GL_NV_texture_rectangle
  147. 25-04-2005
  148. - Function Unbind added
  149. - call of SetFilter or SetTextureWrap if TextureID exists results in setting properties to opengl texture.
  150. 21-04-2005
  151. - class TglBitmapCubeMap added (allows to Create Cubemaps)
  152. 29-03-2005
  153. - Added Support for PNG Images. (http://pngdelphi.sourceforge.net/)
  154. To Enable png's use the define pngimage
  155. 22-03-2005
  156. - New Functioninterface added
  157. - Function GetPixel added
  158. 27-11-2004
  159. - Property BuildMipMaps renamed to MipMap
  160. 21-11-2004
  161. - property Name removed.
  162. - BuildMipMaps is now a set of 3 values. None, GluBuildMipmaps and SGIS_generate_mipmap
  163. 22-05-2004
  164. - property name added. Only used in glForms!
  165. 26-11-2003
  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)
  170. 29-09-2003
  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
  177. 12-09-2003
  178. - TglBitmap dosn't delete data if class was destroyed (fixed)
  179. 09-09-2003
  180. - Bind now enables TextureUnits (by params)
  181. - GenTextures can leave data (by param)
  182. - LoadTextures now optimal
  183. 03-09-2003
  184. - Performance optimization in AddFunc
  185. - procedure Bind moved to subclasses
  186. - Added new Class TglBitmap1D to support real OpenGL 1D Textures
  187. 19-08-2003
  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
  195. 18-08-2003
  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
  200. 16-08-2003
  201. - Added function FlipHorz
  202. 15-08-2003
  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
  206. 29-07-2003
  207. - Added Alphafunctions to calculate alpha per function
  208. - Added Alpha from ColorKey using alphafunctions
  209. 28-07-2003
  210. - First full functionally Version of glBitmap
  211. - Support for 24Bit and 32Bit TGA Pictures added
  212. 25-07-2003
  213. - begin of programming
  214. ***********************************************************}
  215. unit glBitmap;
  216. {$message warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
  217. // Please uncomment the defines below to configure the glBitmap to your preferences.
  218. // If you have configured the unit you can uncomment the warning above.
  219. // ###### Start of preferences ################################################
  220. {.$define GLB_NO_NATIVE_GL}
  221. // To enable the dglOpenGL.pas Header
  222. // With native GL then bindings are staticlly declared to support other headers
  223. // or use the glBitmap inside of DLLs (minimize codesize).
  224. {.$define GLB_SDL}
  225. // To enable the support for SDL_surfaces
  226. {.$define GLB_DELPHI}
  227. // To enable the support for TBitmap from Delphi (not lazarus)
  228. // *** image libs ***
  229. {.$define GLB_SDL_IMAGE}
  230. // To enable the support of SDL_image to load files. (READ ONLY)
  231. // If you enable SDL_image all other libraries will be ignored!
  232. {.$define GLB_PNGIMAGE}
  233. // to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/
  234. // if you enable pngimage the libPNG will be ignored
  235. {.$define GLB_LIB_PNG}
  236. // to use the libPNG http://www.libpng.org/
  237. // You will need an aditional header.
  238. // http://www.opengl24.de/index.php?cat=header&file=libpng
  239. {.$define GLB_DELPHI_JPEG}
  240. // if you enable delphi jpegs the libJPEG will be ignored
  241. {.$define GLB_LIB_JPEG}
  242. // to use the libJPEG http://www.ijg.org/
  243. // You will need an aditional header.
  244. // http://www.opengl24.de/index.php?cat=header&file=libjpeg
  245. // ###### End of preferences ##################################################
  246. // ###### PRIVATE. Do not change anything. ####################################
  247. // *** old defines for compatibility ***
  248. {$ifdef NO_NATIVE_GL}
  249. {$define GLB_NO_NATIVE_GL}
  250. {$endif}
  251. {$ifdef pngimage}
  252. {$definde GLB_PNGIMAGE}
  253. {$endif}
  254. // *** Delphi Versions ***
  255. {$ifdef fpc}
  256. {$MODE Delphi}
  257. {$ifdef CPUI386}
  258. {$define CPU386}
  259. {$asmmode INTEL}
  260. {$endif}
  261. {$ifndef WIN32}
  262. {$linklib c}
  263. {$endif}
  264. {$endif}
  265. // *** checking define combinations ***
  266. {$ifdef GLB_SDL_IMAGE}
  267. {$ifndef GLB_SDL}
  268. {$message warn 'SDL_image won''t work without SDL. SDL will be activated.'}
  269. {$define GLB_SDL}
  270. {$endif}
  271. {$ifdef GLB_PNGIMAGE}
  272. {$message warn 'The unit pngimage will be ignored because you are using SDL_image.'}
  273. {$undef GLB_PNGIMAGE}
  274. {$endif}
  275. {$ifdef GLB_DELPHI_JPEG}
  276. {$message warn 'The unit JPEG will be ignored because you are using SDL_image.'}
  277. {$undef GLB_DELPHI_JPEG}
  278. {$endif}
  279. {$ifdef GLB_LIB_PNG}
  280. {$message warn 'The library libPNG will be ignored because you are using SDL_image.'}
  281. {$undef GLB_LIB_PNG}
  282. {$endif}
  283. {$ifdef GLB_LIB_JPEG}
  284. {$message warn 'The library libJPEG will be ignored because you are using SDL_image.'}
  285. {$undef GLB_LIB_JPEG}
  286. {$endif}
  287. {$define GLB_SUPPORT_PNG_READ}
  288. {$define GLB_SUPPORT_JPEG_READ}
  289. {$endif}
  290. {$ifdef GLB_PNGIMAGE}
  291. {$ifdef GLB_LIB_PNG}
  292. {$message warn 'The library libPNG will be ignored if you are using pngimage.'}
  293. {$undef GLB_LIB_PNG}
  294. {$endif}
  295. {$define GLB_SUPPORT_PNG_READ}
  296. {$define GLB_SUPPORT_PNG_WRITE}
  297. {$endif}
  298. {$ifdef GLB_LIB_PNG}
  299. {$define GLB_SUPPORT_PNG_READ}
  300. {$define GLB_SUPPORT_PNG_WRITE}
  301. {$endif}
  302. {$ifdef GLB_DELPHI_JPEG}
  303. {$ifdef GLB_LIB_JPEG}
  304. {$message warn 'The library libJPEG will be ignored if you are using the unit JPEG.'}
  305. {$undef GLB_LIB_JPEG}
  306. {$endif}
  307. {$define GLB_SUPPORT_JPEG_READ}
  308. {$define GLB_SUPPORT_JPEG_WRITE}
  309. {$endif}
  310. {$ifdef GLB_LIB_JPEG}
  311. {$define GLB_SUPPORT_JPEG_READ}
  312. {$define GLB_SUPPORT_JPEG_WRITE}
  313. {$endif}
  314. // *** general options ***
  315. {$EXTENDEDSYNTAX ON}
  316. {$LONGSTRINGS ON}
  317. {$ALIGN ON}
  318. {$ifndef fpc}
  319. {$OPTIMIZATION ON}
  320. {$endif}
  321. interface
  322. uses
  323. {$ifdef GLB_NO_NATIVE_GL} dglOpenGL, {$endif}
  324. {$ifdef GLB_SDL} SDL, {$endif}
  325. {$ifdef GLB_DELPHI} Dialogs, Windows, Graphics, {$endif}
  326. {$ifdef GLB_SDL_IMAGE} SDL_image, {$endif}
  327. {$ifdef GLB_PNGIMAGE} pngimage, {$endif}
  328. {$ifdef GLB_LIB_PNG} libPNG, {$endif}
  329. {$ifdef GLB_DELPHI_JPEG} JPEG, {$endif}
  330. {$ifdef GLB_LIB_JPEG} libJPEG, {$endif}
  331. Classes, SysUtils;
  332. {$ifndef GLB_DELPHI}
  333. type
  334. HGLRC = Cardinal;
  335. DWORD = Cardinal;
  336. PDWORD = ^DWORD;
  337. TRGBQuad = packed record
  338. rgbBlue: Byte;
  339. rgbGreen: Byte;
  340. rgbRed: Byte;
  341. rgbReserved: Byte;
  342. end;
  343. {$endif}
  344. {$ifndef GLB_NO_NATIVE_GL}
  345. // Native OpenGL Implementation
  346. type
  347. PByteBool = ^ByteBool;
  348. {$ifdef GLB_DELPHI}
  349. var
  350. gLastContext: HGLRC;
  351. {$endif}
  352. const
  353. // Generell
  354. GL_VERSION = $1F02;
  355. GL_EXTENSIONS = $1F03;
  356. GL_TRUE = 1;
  357. GL_FALSE = 0;
  358. GL_TEXTURE_1D = $0DE0;
  359. GL_TEXTURE_2D = $0DE1;
  360. GL_MAX_TEXTURE_SIZE = $0D33;
  361. GL_PACK_ALIGNMENT = $0D05;
  362. GL_UNPACK_ALIGNMENT = $0CF5;
  363. // Textureformats
  364. GL_RGB = $1907;
  365. GL_RGB4 = $804F;
  366. GL_RGB8 = $8051;
  367. GL_RGBA = $1908;
  368. GL_RGBA4 = $8056;
  369. GL_RGBA8 = $8058;
  370. GL_BGR = $80E0;
  371. GL_BGRA = $80E1;
  372. GL_ALPHA4 = $803B;
  373. GL_ALPHA8 = $803C;
  374. GL_LUMINANCE4 = $803F;
  375. GL_LUMINANCE8 = $8040;
  376. GL_LUMINANCE4_ALPHA4 = $8043;
  377. GL_LUMINANCE8_ALPHA8 = $8045;
  378. GL_DEPTH_COMPONENT = $1902;
  379. GL_UNSIGNED_BYTE = $1401;
  380. GL_ALPHA = $1906;
  381. GL_LUMINANCE = $1909;
  382. GL_LUMINANCE_ALPHA = $190A;
  383. GL_TEXTURE_WIDTH = $1000;
  384. GL_TEXTURE_HEIGHT = $1001;
  385. GL_TEXTURE_INTERNAL_FORMAT = $1003;
  386. GL_TEXTURE_RED_SIZE = $805C;
  387. GL_TEXTURE_GREEN_SIZE = $805D;
  388. GL_TEXTURE_BLUE_SIZE = $805E;
  389. GL_TEXTURE_ALPHA_SIZE = $805F;
  390. GL_TEXTURE_LUMINANCE_SIZE = $8060;
  391. // Dataformats
  392. GL_UNSIGNED_SHORT_5_6_5 = $8363;
  393. GL_UNSIGNED_SHORT_5_6_5_REV = $8364;
  394. GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365;
  395. GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366;
  396. GL_UNSIGNED_INT_2_10_10_10_REV = $8368;
  397. // Filter
  398. GL_NEAREST = $2600;
  399. GL_LINEAR = $2601;
  400. GL_NEAREST_MIPMAP_NEAREST = $2700;
  401. GL_LINEAR_MIPMAP_NEAREST = $2701;
  402. GL_NEAREST_MIPMAP_LINEAR = $2702;
  403. GL_LINEAR_MIPMAP_LINEAR = $2703;
  404. GL_TEXTURE_MAG_FILTER = $2800;
  405. GL_TEXTURE_MIN_FILTER = $2801;
  406. // Wrapmodes
  407. GL_TEXTURE_WRAP_S = $2802;
  408. GL_TEXTURE_WRAP_T = $2803;
  409. GL_CLAMP = $2900;
  410. GL_REPEAT = $2901;
  411. GL_CLAMP_TO_EDGE = $812F;
  412. GL_CLAMP_TO_BORDER = $812D;
  413. GL_TEXTURE_WRAP_R = $8072;
  414. GL_MIRRORED_REPEAT = $8370;
  415. // Border Color
  416. GL_TEXTURE_BORDER_COLOR = $1004;
  417. // Texgen
  418. GL_NORMAL_MAP = $8511;
  419. GL_REFLECTION_MAP = $8512;
  420. GL_S = $2000;
  421. GL_T = $2001;
  422. GL_R = $2002;
  423. GL_TEXTURE_GEN_MODE = $2500;
  424. GL_TEXTURE_GEN_S = $0C60;
  425. GL_TEXTURE_GEN_T = $0C61;
  426. GL_TEXTURE_GEN_R = $0C62;
  427. // Cubemaps
  428. GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C;
  429. GL_TEXTURE_CUBE_MAP = $8513;
  430. GL_TEXTURE_BINDING_CUBE_MAP = $8514;
  431. GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515;
  432. GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516;
  433. GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517;
  434. GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518;
  435. GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519;
  436. GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A;
  437. GL_TEXTURE_RECTANGLE_ARB = $84F5;
  438. // GL_SGIS_generate_mipmap
  439. GL_GENERATE_MIPMAP = $8191;
  440. // GL_EXT_texture_compression_s3tc
  441. GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0;
  442. GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1;
  443. GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2;
  444. GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3;
  445. // GL_EXT_texture_filter_anisotropic
  446. GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE;
  447. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF;
  448. // GL_ARB_texture_compression
  449. GL_COMPRESSED_RGB = $84ED;
  450. GL_COMPRESSED_RGBA = $84EE;
  451. GL_COMPRESSED_ALPHA = $84E9;
  452. GL_COMPRESSED_LUMINANCE = $84EA;
  453. GL_COMPRESSED_LUMINANCE_ALPHA = $84EB;
  454. // Extensions
  455. var
  456. GL_VERSION_1_2,
  457. GL_VERSION_1_3,
  458. GL_VERSION_1_4,
  459. GL_VERSION_2_0,
  460. GL_ARB_texture_border_clamp,
  461. GL_ARB_texture_cube_map,
  462. GL_ARB_texture_compression,
  463. GL_ARB_texture_non_power_of_two,
  464. GL_ARB_texture_rectangle,
  465. GL_ARB_texture_mirrored_repeat,
  466. GL_EXT_bgra,
  467. GL_EXT_texture_edge_clamp,
  468. GL_EXT_texture_cube_map,
  469. GL_EXT_texture_compression_s3tc,
  470. GL_EXT_texture_filter_anisotropic,
  471. GL_EXT_texture_rectangle,
  472. GL_NV_texture_rectangle,
  473. GL_IBM_texture_mirrored_repeat,
  474. GL_SGIS_generate_mipmap: Boolean;
  475. // Funtions
  476. const
  477. {$ifdef LINUX}
  478. libglu = 'libGLU.so.1';
  479. libopengl = 'libGL.so.1';
  480. {$else}
  481. libglu = 'glu32.dll';
  482. libopengl = 'opengl32.dll';
  483. {$endif}
  484. {$ifdef LINUX}
  485. function glXGetProcAddress(ProcName: PAnsiChar): Pointer; cdecl; external libopengl;
  486. {$else}
  487. function wglGetProcAddress(ProcName: PAnsiChar): Pointer; stdcall; external libopengl;
  488. {$endif}
  489. function glGetString(name: Cardinal): PAnsiChar; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  490. procedure glEnable(cap: Cardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  491. procedure glDisable(cap: Cardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  492. procedure glGetIntegerv(pname: Cardinal; params: PInteger); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  493. procedure glTexImage1D(target: Cardinal; level, internalformat, width, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  494. procedure glTexImage2D(target: Cardinal; level, internalformat, width, height, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  495. procedure glGenTextures(n: Integer; Textures: PCardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  496. procedure glBindTexture(target: Cardinal; Texture: Cardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  497. procedure glDeleteTextures(n: Integer; const textures: PCardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  498. procedure glReadPixels(x, y: Integer; width, height: Integer; format, atype: Cardinal; pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  499. procedure glPixelStorei(pname: Cardinal; param: Integer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  500. procedure glGetTexImage(target: Cardinal; level: Integer; format: Cardinal; _type: Cardinal; pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  501. function glAreTexturesResident(n: Integer; const Textures: PCardinal; residences: PByteBool): ByteBool; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  502. procedure glTexParameteri(target: Cardinal; pname: Cardinal; param: Integer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  503. procedure glTexParameterfv(target: Cardinal; pname: Cardinal; const params: PSingle); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  504. procedure glGetTexLevelParameteriv(target: Cardinal; level: Integer; pname: Cardinal; params: PInteger); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  505. procedure glTexGeni(coord, pname: Cardinal; param: Integer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl;
  506. function gluBuild1DMipmaps(Target: Cardinal; Components, Width: Integer; Format, atype: Cardinal; Data: Pointer): Integer; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libglu;
  507. function gluBuild2DMipmaps(Target: Cardinal; Components, Width, Height: Integer; Format, aType: Cardinal; Data: Pointer): Integer; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libglu;
  508. var
  509. glCompressedTexImage2D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width, height: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif}
  510. glCompressedTexImage1D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif}
  511. glGetCompressedTexImage : procedure(target: Cardinal; level: Integer; img: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif}
  512. {$endif}
  513. type
  514. // Exception
  515. EglBitmapException = Exception;
  516. EglBitmapSizeToLargeException = EglBitmapException;
  517. EglBitmapNonPowerOfTwoException = EglBitmapException;
  518. EglBitmapUnsupportedInternalFormat = EglBitmapException;
  519. // Functions
  520. TglBitmapPixelDesc = packed record
  521. RedRange: Cardinal;
  522. RedShift: Shortint;
  523. GreenRange: Cardinal;
  524. GreenShift: Shortint;
  525. BlueRange: Cardinal;
  526. BlueShift: Shortint;
  527. AlphaRange: Cardinal;
  528. AlphaShift: Shortint;
  529. end;
  530. TglBitmapPixelData = packed record
  531. Red: Cardinal;
  532. Green: Cardinal;
  533. Blue: Cardinal;
  534. Alpha: Cardinal;
  535. PixelDesc: TglBitmapPixelDesc;
  536. end;
  537. TglBitmapPixelPositionFields = set of (ffX, ffY);
  538. TglBitmapPixelPosition = record
  539. Fields : TglBitmapPixelPositionFields;
  540. X : Word;
  541. Y : Word;
  542. end;
  543. const
  544. cNullSize : TglBitmapPixelPosition = (Fields : []; X: 0; Y: 0);
  545. type
  546. TglBitmap = class;
  547. TglBitmapFunctionRec = record
  548. Sender : TglBitmap;
  549. Size: TglBitmapPixelPosition;
  550. Position: TglBitmapPixelPosition;
  551. Source: TglBitmapPixelData;
  552. Dest: TglBitmapPixelData;
  553. CustomData: Pointer;
  554. end;
  555. TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
  556. TglBitmapGetPixel = procedure (
  557. const Pos: TglBitmapPixelPosition;
  558. var Pixel: TglBitmapPixelData) of object;
  559. TglBitmapSetPixel = procedure (
  560. const Pos: TglBitmapPixelPosition;
  561. const Pixel: TglBitmapPixelData) of object;
  562. // Settings
  563. TglBitmapFileType = (
  564. {$ifdef GLB_SUPPORT_PNG_WRITE} ftPNG, {$endif}
  565. {$ifdef GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$endif}
  566. ftDDS,
  567. ftTGA,
  568. ftBMP);
  569. TglBitmapFileTypes = set of TglBitmapFileType;
  570. TglBitmapFormat = (tfDefault, tf4BitsPerChanel, tf8BitsPerChanel, tfCompressed);
  571. TglBitmapMipMap = (mmNone, mmMipmap, mmMipmapGlu);
  572. TglBitmapNormalMapFunc = (nm4Samples, nmSobel, nm3x3, nm5x5);
  573. TglBitmapInternalFormat = (
  574. ifEmpty,
  575. // 4 Bit
  576. ifDXT1,
  577. // 8 Bit
  578. ifDXT3,
  579. ifDXT5,
  580. ifAlpha,
  581. ifLuminance,
  582. ifDepth8,
  583. // 16 Bit
  584. ifLuminanceAlpha,
  585. ifRGBA4,
  586. ifR5G6B5,
  587. ifRGB5A1,
  588. // 24 Bit
  589. ifBGR8,
  590. ifRGB8,
  591. // 32 Bit
  592. ifBGRA8,
  593. ifRGBA8,
  594. ifRGB10A2
  595. );
  596. // Pixelmapping
  597. TglBitmapMapFunc = procedure (const Pixel: TglBitmapPixelData; var pDest: pByte);
  598. TglBitmapUnMapFunc = procedure (var pData: pByte; var Pixel: TglBitmapPixelData);
  599. // Base Class
  600. TglBitmap = class
  601. protected
  602. fID: Cardinal;
  603. fTarget: Cardinal;
  604. fFormat: TglBitmapFormat;
  605. fMipMap: TglBitmapMipMap;
  606. fAnisotropic: Integer;
  607. fBorderColor: array [0..3] of single;
  608. fDeleteTextureOnFree: Boolean;
  609. fFreeDataAfterGenTexture: Boolean;
  610. // Propertys
  611. fData: pByte;
  612. fInternalFormat: TglBitmapInternalFormat;
  613. fDimension: TglBitmapPixelPosition;
  614. fIsResident: Boolean;
  615. // Mapping
  616. fPixelSize: Integer;
  617. fRowSize: Integer;
  618. fUnmapFunc: TglBitmapUnMapFunc;
  619. fMapFunc: TglBitmapMapFunc;
  620. // Filtering
  621. fFilterMin: Integer;
  622. fFilterMag: Integer;
  623. // Texturwarp
  624. fWrapS: Integer;
  625. fWrapT: Integer;
  626. fWrapR: Integer;
  627. fGetPixelFunc: TglBitmapGetPixel;
  628. fSetPixelFunc: TglBitmapSetPixel;
  629. // custom data
  630. fFilename: String;
  631. fCustomName: String;
  632. fCustomNameW: WideString;
  633. fCustomDataPointer: Pointer;
  634. procedure SetDataPointer(NewData: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); virtual;
  635. {$ifdef GLB_SUPPORT_PNG_READ}
  636. function LoadPNG(Stream: TStream): Boolean; virtual;
  637. {$endif}
  638. {$ifdef GLB_SUPPORT_JPEG_READ}
  639. function LoadJPEG(Stream: TStream): Boolean; virtual;
  640. {$endif}
  641. function LoadDDS(Stream: TStream): Boolean; virtual;
  642. function LoadTGA(Stream: TStream): Boolean; virtual;
  643. function LoadBMP(Stream: TStream): Boolean; virtual;
  644. {$ifdef GLB_SUPPORT_PNG_WRITE}
  645. procedure SavePNG(Stream: TStream); virtual;
  646. {$endif}
  647. {$ifdef GLB_SUPPORT_JPEG_WRITE}
  648. procedure SaveJPEG(Stream: TStream); virtual;
  649. {$endif}
  650. procedure SaveDDS(Stream: TStream); virtual;
  651. procedure SaveTGA(Stream: TStream); virtual;
  652. procedure SaveBMP(Stream: TStream); virtual;
  653. procedure CreateID;
  654. procedure SetupParameters(var BuildWithGlu: Boolean);
  655. procedure SelectFormat(DataFormat: TglBitmapInternalFormat; var glFormat, glInternalFormat, glType: Cardinal; CanConvertImage: Boolean = True);
  656. procedure GenTexture(TestTextureSize: Boolean = True); virtual; abstract;
  657. procedure SetAnisotropic(const Value: Integer);
  658. procedure SetInternalFormat(const Value: TglBitmapInternalFormat);
  659. function FlipHorz: Boolean; virtual;
  660. function FlipVert: Boolean; virtual;
  661. function GetHeight: Integer;
  662. function GetWidth: Integer;
  663. function GetFileHeight: Integer;
  664. function GetFileWidth: Integer;
  665. property Width: Integer read GetWidth;
  666. property Height: Integer read GetHeight;
  667. property FileWidth: Integer read GetFileWidth;
  668. property FileHeight: Integer read GetFileHeight;
  669. public
  670. // propertys
  671. property ID: Cardinal read fID write fID;
  672. property Target: Cardinal read fTarget write fTarget;
  673. property Format: TglBitmapFormat read fFormat write fFormat;
  674. property InternalFormat: TglBitmapInternalFormat read fInternalFormat write SetInternalFormat;
  675. property Dimension: TglBitmapPixelPosition read fDimension;
  676. property Data: pByte read fData;
  677. property MipMap: TglBitmapMipMap read fMipMap write fMipMap;
  678. property Anisotropic: Integer read fAnisotropic write SetAnisotropic;
  679. property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write fDeleteTextureOnFree;
  680. property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write fFreeDataAfterGenTexture;
  681. property IsResident: boolean read fIsResident;
  682. // propertys for custom data
  683. property Filename: String read fFilename;
  684. property CustomName: String read fCustomName write fCustomName;
  685. property CustomNameW: WideString read fCustomNameW write fCustomNameW;
  686. property CustomDataPointer: Pointer read fCustomDataPointer write fCustomDataPointer;
  687. // Construction and Destructions Methods
  688. procedure AfterConstruction; override;
  689. procedure BeforeDestruction; override;
  690. constructor Create(); overload;
  691. constructor Create(FileName: String); overload;
  692. constructor Create(Stream: TStream); overload;
  693. {$ifdef GLB_DELPHI}
  694. constructor CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar = nil);
  695. constructor Create(Instance: Cardinal; Resource: String; ResType: PChar = nil); overload;
  696. constructor Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar); overload;
  697. {$endif}
  698. constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat); overload;
  699. constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer = nil); overload;
  700. function Clone: TglBitmap;
  701. procedure FreeData;
  702. // Loading Methods
  703. procedure LoadFromFile(FileName: String);
  704. procedure LoadFromStream(Stream: TStream); virtual;
  705. {$ifdef GLB_DELPHI}
  706. procedure LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar = nil);
  707. procedure LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar);
  708. {$endif}
  709. procedure LoadFromFunc(Size: TglBitmapPixelPosition; Func: TglBitmapFunction; Format: TglBitmapInternalFormat; CustomData: Pointer = nil);
  710. procedure SaveToFile(FileName: String; FileType: TglBitmapFileType);
  711. procedure SaveToStream(Stream: TStream; FileType: TglBitmapFileType); virtual;
  712. function AddFunc(Source: TglBitmap; Func: TglBitmapFunction; CreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer = nil): boolean; overload;
  713. function AddFunc(Func: TglBitmapFunction; CreateTemp: Boolean; CustomData: Pointer = nil): boolean; overload;
  714. {$ifdef GLB_SDL}
  715. function AssignToSurface(out Surface: PSDL_Surface): boolean;
  716. function AssignFromSurface(const Surface: PSDL_Surface): boolean;
  717. function AssignAlphaToSurface(out Surface: PSDL_Surface): boolean;
  718. function AddAlphaFromSurface(Surface: PSDL_Surface; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean;
  719. {$endif}
  720. {$ifdef GLB_DELPHI}
  721. function AssignToBitmap(const Bitmap: TBitmap): boolean;
  722. function AssignFromBitmap(const Bitmap: TBitmap): boolean;
  723. function AssignAlphaToBitmap(const Bitmap: TBitmap): boolean;
  724. function AddAlphaFromBitmap(Bitmap: TBitmap; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean;
  725. {$endif}
  726. function AddAlphaFromFunc(Func: TglBitmapFunction; CustomData: Pointer = nil): boolean; virtual;
  727. function AddAlphaFromFile(FileName: String; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean;
  728. function AddAlphaFromStream(Stream: TStream; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean;
  729. {$ifdef GLB_DELPHI}
  730. function AddAlphaFromResource(Instance: Cardinal; Resource: String; ResType: PChar = nil; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean;
  731. function AddAlphaFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean;
  732. {$endif}
  733. function AddAlphaFromglBitmap(glBitmap: TglBitmap; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean;
  734. function AddAlphaFromColorKey(Red, Green, Blue: Byte; Deviation: Byte = 0): Boolean;
  735. function AddAlphaFromColorKeyRange(Red, Green, Blue: Cardinal; Deviation: Cardinal = 0): Boolean;
  736. function AddAlphaFromColorKeyFloat(Red, Green, Blue: Single; Deviation: Single = 0): Boolean;
  737. function AddAlphaFromValue(Alpha: Byte): Boolean;
  738. function AddAlphaFromValueRange(Alpha: Cardinal): Boolean;
  739. function AddAlphaFromValueFloat(Alpha: Single): Boolean;
  740. function RemoveAlpha: Boolean; virtual;
  741. function ConvertTo(NewFormat: TglBitmapInternalFormat): boolean; virtual;
  742. // Other
  743. procedure FillWithColor(Red, Green, Blue: Byte; Alpha : Byte = 255);
  744. procedure FillWithColorRange(Red, Green, Blue: Cardinal; Alpha : Cardinal = $FFFFFFFF);
  745. procedure FillWithColorFloat(Red, Green, Blue: Single; Alpha : Single = 1);
  746. procedure Invert(UseRGB: Boolean = true; UseAlpha: Boolean = false);
  747. procedure SetFilter(Min, Mag : Integer);
  748. procedure SetWrap(S: Integer = GL_CLAMP_TO_EDGE;
  749. T: Integer = GL_CLAMP_TO_EDGE; R: Integer = GL_CLAMP_TO_EDGE);
  750. procedure SetBorderColor(Red, Green, Blue, Alpha: Single);
  751. procedure GetPixel (const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); virtual;
  752. procedure SetPixel (const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); virtual;
  753. // Generation
  754. procedure Unbind(DisableTextureUnit: Boolean = True); virtual;
  755. procedure Bind(EnableTextureUnit: Boolean = True); virtual;
  756. end;
  757. TglBitmap2D = class(TglBitmap)
  758. protected
  759. // Bildeinstellungen
  760. fLines: array of PByte;
  761. procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
  762. procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
  763. procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
  764. procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
  765. procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
  766. procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
  767. function GetScanline(Index: Integer): Pointer;
  768. procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override;
  769. procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
  770. public
  771. // propertys
  772. property Width;
  773. property Height;
  774. property Scanline[Index: Integer]: Pointer read GetScanline;
  775. procedure AfterConstruction; override;
  776. procedure GrabScreen(Top, Left, Right, Bottom: Integer; Format: TglBitmapInternalFormat);
  777. procedure GetDataFromTexture;
  778. // Other
  779. function FlipHorz: Boolean; override;
  780. function FlipVert: Boolean; override;
  781. procedure ToNormalMap(Func: TglBitmapNormalMapFunc = nm3x3; Scale: Single = 2; UseAlpha: Boolean = False);
  782. // Generation
  783. procedure GenTexture(TestTextureSize: Boolean = True); override;
  784. end;
  785. TglBitmapCubeMap = class(TglBitmap2D)
  786. protected
  787. fGenMode: Integer;
  788. // Hide GenTexture
  789. procedure GenTexture(TestTextureSize: Boolean = True); reintroduce;
  790. public
  791. procedure AfterConstruction; override;
  792. procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true);
  793. procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = True); reintroduce; virtual;
  794. procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = True); reintroduce; virtual;
  795. end;
  796. TglBitmapNormalMap = class(TglBitmapCubeMap)
  797. public
  798. procedure AfterConstruction; override;
  799. procedure GenerateNormalMap(Size: Integer = 32; TestTextureSize: Boolean = true);
  800. end;
  801. TglBitmap1D = class(TglBitmap)
  802. protected
  803. procedure GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
  804. procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override;
  805. procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
  806. public
  807. // propertys
  808. property Width;
  809. procedure AfterConstruction; override;
  810. // Other
  811. function FlipHorz: Boolean; override;
  812. // Generation
  813. procedure GenTexture(TestTextureSize: Boolean = True); override;
  814. end;
  815. // methods and vars for Defaults
  816. procedure glBitmapSetDefaultFormat(Format: TglBitmapFormat);
  817. procedure glBitmapSetDefaultFilter(Min, Mag: Integer);
  818. procedure glBitmapSetDefaultWrap(S: Integer = GL_CLAMP_TO_EDGE; T: Integer = GL_CLAMP_TO_EDGE; R: Integer = GL_CLAMP_TO_EDGE);
  819. procedure glBitmapSetDefaultDeleteTextureOnFree(DeleteTextureOnFree: Boolean);
  820. procedure glBitmapSetDefaultFreeDataAfterGenTexture(FreeData: Boolean);
  821. function glBitmapGetDefaultFormat: TglBitmapFormat;
  822. procedure glBitmapGetDefaultFilter(var Min, Mag: Integer);
  823. procedure glBitmapGetDefaultTextureWrap(var S, T, R: Integer);
  824. function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
  825. function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
  826. // position / size
  827. function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
  828. // Formatfunctions
  829. function FormatGetSize (Format: TglBitmapInternalFormat): Single;
  830. function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
  831. function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
  832. function FormatIsEmpty(Format: TglBitmapInternalFormat): boolean;
  833. function FormatHasAlpha(Format: TglBitmapInternalFormat): Boolean;
  834. procedure FormatPreparePixel(var Pixel: TglBitmapPixelData; Format: TglBitmapInternalFormat);
  835. function FormatGetWithoutAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
  836. function FormatGetWithAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
  837. function FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; Format: TglBitmapInternalFormat): boolean;
  838. // Call LoadingMethods
  839. function LoadTexture(Filename: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$endif}): Boolean;
  840. function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$endif}): Boolean;
  841. function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
  842. var
  843. glBitmapDefaultFormat: TglBitmapFormat;
  844. glBitmapDefaultFilterMin: Integer;
  845. glBitmapDefaultFilterMag: Integer;
  846. glBitmapDefaultWrapS: Integer;
  847. glBitmapDefaultWrapT: Integer;
  848. glBitmapDefaultWrapR: Integer;
  849. glBitmapDefaultDeleteTextureOnFree: Boolean;
  850. glBitmapDefaultFreeDataAfterGenTextures: Boolean;
  851. {$ifdef GLB_DELPHI}
  852. function CreateGrayPalette: HPALETTE;
  853. {$endif}
  854. implementation
  855. uses
  856. Math;
  857. {$ifndef GLB_NO_NATIVE_GL}
  858. procedure ReadOpenGLExtensions;
  859. var
  860. {$ifdef GLB_DELPHI}
  861. Context: HGLRC;
  862. {$endif}
  863. Buffer: AnsiString;
  864. MajorVersion, MinorVersion: Integer;
  865. procedure TrimVersionString(Buffer: AnsiString; var Major, Minor: Integer);
  866. var
  867. Separator: Integer;
  868. begin
  869. Minor := 0;
  870. Major := 0;
  871. Separator := Pos(AnsiString('.'), Buffer);
  872. if (Separator > 1) and (Separator < Length(Buffer)) and
  873. (Buffer[Separator - 1] in ['0'..'9']) and
  874. (Buffer[Separator + 1] in ['0'..'9']) then begin
  875. Dec(Separator);
  876. while (Separator > 0) and (Buffer[Separator] in ['0'..'9']) do
  877. Dec(Separator);
  878. Delete(Buffer, 1, Separator);
  879. Separator := Pos(AnsiString('.'), Buffer) + 1;
  880. while (Separator <= Length(Buffer)) and (AnsiChar(Buffer[Separator]) in ['0'..'9']) do
  881. Inc(Separator);
  882. Delete(Buffer, Separator, 255);
  883. Separator := Pos(AnsiString('.'), Buffer);
  884. Major := StrToInt(Copy(String(Buffer), 1, Separator - 1));
  885. Minor := StrToInt(Copy(String(Buffer), Separator + 1, 1));
  886. end;
  887. end;
  888. function CheckExtension(const Extension: AnsiString): Boolean;
  889. var
  890. ExtPos: Integer;
  891. begin
  892. ExtPos := Pos(Extension, Buffer);
  893. Result := ExtPos > 0;
  894. if Result then
  895. Result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
  896. end;
  897. function glLoad (aFunc: pAnsiChar): pointer;
  898. begin
  899. {$ifdef LINUX}
  900. Result := glXGetProcAddress(aFunc);
  901. {$else}
  902. Result := wglGetProcAddress(aFunc);
  903. {$endif}
  904. end;
  905. begin
  906. {$ifdef GLB_DELPHI}
  907. Context := wglGetCurrentContext;
  908. if Context <> gLastContext then begin
  909. gLastContext := Context;
  910. {$endif}
  911. // Version
  912. Buffer := glGetString(GL_VERSION);
  913. TrimVersionString(Buffer, MajorVersion, MinorVersion);
  914. GL_VERSION_1_2 := False;
  915. GL_VERSION_1_3 := False;
  916. GL_VERSION_1_4 := False;
  917. GL_VERSION_2_0 := False;
  918. if MajorVersion = 1 then begin
  919. if MinorVersion >= 1 then begin
  920. if MinorVersion >= 2 then
  921. GL_VERSION_1_2 := True;
  922. if MinorVersion >= 3 then
  923. GL_VERSION_1_3 := True;
  924. if MinorVersion >= 4 then
  925. GL_VERSION_1_4 := True;
  926. end;
  927. end;
  928. if MajorVersion >= 2 then begin
  929. GL_VERSION_1_2 := True;
  930. GL_VERSION_1_3 := True;
  931. GL_VERSION_1_4 := True;
  932. GL_VERSION_2_0 := True;
  933. end;
  934. // Extensions
  935. Buffer := glGetString(GL_EXTENSIONS);
  936. GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp');
  937. GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map');
  938. GL_ARB_texture_compression := CheckExtension('GL_ARB_texture_compression');
  939. GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two');
  940. GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle');
  941. GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat');
  942. GL_EXT_bgra := CheckExtension('GL_EXT_bgra');
  943. GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp');
  944. GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map');
  945. GL_EXT_texture_compression_s3tc := CheckExtension('GL_EXT_texture_compression_s3tc');
  946. GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic');
  947. GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle');
  948. GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle');
  949. GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat');
  950. GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap');
  951. // Funtions
  952. if GL_VERSION_1_3 then begin
  953. // Loading Core
  954. glCompressedTexImage1D := glLoad('glCompressedTexImage1D');
  955. glCompressedTexImage2D := glLoad('glCompressedTexImage2D');
  956. glGetCompressedTexImage := glLoad('glGetCompressedTexImage');
  957. end else
  958. begin
  959. // Try loading Extension
  960. glCompressedTexImage1D := glLoad('glCompressedTexImage1DARB');
  961. glCompressedTexImage2D := glLoad('glCompressedTexImage2DARB');
  962. glGetCompressedTexImage := glLoad('glGetCompressedTexImageARB');
  963. end;
  964. {$ifdef GLB_DELPHI}
  965. end;
  966. {$endif}
  967. end;
  968. {$endif}
  969. function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
  970. begin
  971. Result.Fields := [];
  972. if X >= 0 then
  973. Result.Fields := Result.Fields + [ffX];
  974. if Y >= 0 then
  975. Result.Fields := Result.Fields + [ffY];
  976. Result.X := Max(0, X);
  977. Result.Y := Max(0, Y);
  978. end;
  979. const
  980. UNSUPPORTED_INTERNAL_FORMAT = 'the given format isn''t supported by this function.';
  981. PIXEL_DESC_ALPHA : TglBitmapPixelDesc = (
  982. RedRange : $00; RedShift : 0;
  983. GreenRange : $00; GreenShift : 0;
  984. BlueRange : $00; BlueShift : 0;
  985. AlphaRange : $FF; AlphaShift : 0 );
  986. PIXEL_DESC_LUMINANCE : TglBitmapPixelDesc = (
  987. RedRange : $FF; RedShift : 0;
  988. GreenRange : $FF; GreenShift : 0;
  989. BlueRange : $FF; BlueShift : 0;
  990. AlphaRange : $00; AlphaShift : 0 );
  991. PIXEL_DESC_DEPTH8 : TglBitmapPixelDesc = (
  992. RedRange : $FF; RedShift : 0;
  993. GreenRange : $FF; GreenShift : 0;
  994. BlueRange : $FF; BlueShift : 0;
  995. AlphaRange : $00; AlphaShift : 0 );
  996. PIXEL_DESC_LUMINANCEALPHA : TglBitmapPixelDesc = (
  997. RedRange : $FF; RedShift : 0;
  998. GreenRange : $FF; GreenShift : 0;
  999. BlueRange : $FF; BlueShift : 0;
  1000. AlphaRange : $FF; AlphaShift : 8 );
  1001. PIXEL_DESC_RGBA4 : TglBitmapPixelDesc = (
  1002. RedRange : $0F; RedShift : 8;
  1003. GreenRange : $0F; GreenShift : 4;
  1004. BlueRange : $0F; BlueShift : 0;
  1005. AlphaRange : $0F; AlphaShift : 12 );
  1006. PIXEL_DESC_R5G6B5 : TglBitmapPixelDesc = (
  1007. RedRange : $1F; RedShift : 11;
  1008. GreenRange : $3F; GreenShift : 5;
  1009. BlueRange : $1F; BlueShift : 0;
  1010. AlphaRange : $00; AlphaShift : 0 );
  1011. PIXEL_DESC_RGB5A1 : TglBitmapPixelDesc = (
  1012. RedRange : $1F; RedShift : 10;
  1013. GreenRange : $1F; GreenShift : 5;
  1014. BlueRange : $1F; BlueShift : 0;
  1015. AlphaRange : $01; AlphaShift : 15 );
  1016. PIXEL_DESC_RGB8 : TglBitmapPixelDesc = (
  1017. RedRange : $FF; RedShift : 0;
  1018. GreenRange : $FF; GreenShift : 8;
  1019. BlueRange : $FF; BlueShift : 16;
  1020. AlphaRange : $00; AlphaShift : 0 );
  1021. PIXEL_DESC_RGBA8 : TglBitmapPixelDesc = (
  1022. RedRange : $FF; RedShift : 0;
  1023. GreenRange : $FF; GreenShift : 8;
  1024. BlueRange : $FF; BlueShift : 16;
  1025. AlphaRange : $FF; AlphaShift : 24 );
  1026. PIXEL_DESC_BGR8 : TglBitmapPixelDesc = (
  1027. RedRange : $FF; RedShift : 16;
  1028. GreenRange : $FF; GreenShift : 8;
  1029. BlueRange : $FF; BlueShift : 0;
  1030. AlphaRange : $00; AlphaShift : 0 );
  1031. PIXEL_DESC_BGRA8 : TglBitmapPixelDesc = (
  1032. RedRange : $FF; RedShift : 16;
  1033. GreenRange : $FF; GreenShift : 8;
  1034. BlueRange : $FF; BlueShift : 0;
  1035. AlphaRange : $FF; AlphaShift : 24 );
  1036. PIXEL_DESC_RGB10A2 : TglBitmapPixelDesc = (
  1037. RedRange : $3FF; RedShift : 20;
  1038. GreenRange : $3FF; GreenShift : 10;
  1039. BlueRange : $3FF; BlueShift : 0;
  1040. AlphaRange : $003; AlphaShift : 30 );
  1041. {*
  1042. ** Mapping
  1043. *}
  1044. procedure MapAlpha(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1045. begin
  1046. pDest^ := Pixel.Alpha;
  1047. Inc(pDest);
  1048. end;
  1049. procedure MapLuminance(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1050. begin
  1051. pDest^ := Trunc(Pixel.Red * 0.3 + Pixel.Green * 0.59 + Pixel.Blue * 0.11);
  1052. Inc(pDest);
  1053. end;
  1054. procedure MapDepth8(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1055. begin
  1056. pDest^ := (Pixel.Red + Pixel.Green + Pixel.Blue) div 3;
  1057. Inc(pDest);
  1058. end;
  1059. procedure MapLuminanceAlpha(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1060. begin
  1061. pDest^ := Trunc(Pixel.Red * 0.3 + Pixel.Green * 0.59 + Pixel.Blue * 0.11);
  1062. Inc(pDest);
  1063. pDest^ := Pixel.Alpha;
  1064. Inc(pDest);
  1065. end;
  1066. procedure MapRGBA4(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1067. begin
  1068. pWord(pDest)^ :=
  1069. Pixel.Alpha shl PIXEL_DESC_RGBA4.AlphaShift or
  1070. Pixel.Red shl PIXEL_DESC_RGBA4.RedShift or
  1071. Pixel.Green shl PIXEL_DESC_RGBA4.GreenShift or
  1072. Pixel.Blue;
  1073. Inc(pDest, 2);
  1074. end;
  1075. procedure MapR5G6B5(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1076. begin
  1077. pWord(pDest)^ :=
  1078. Pixel.Red shl PIXEL_DESC_R5G6B5.RedShift or
  1079. Pixel.Green shl PIXEL_DESC_R5G6B5.GreenShift or
  1080. Pixel.Blue;
  1081. Inc(pDest, 2);
  1082. end;
  1083. procedure MapRGB5A1(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1084. begin
  1085. pWord(pDest)^ :=
  1086. Pixel.Alpha shl PIXEL_DESC_RGB5A1.AlphaShift or
  1087. Pixel.Red shl PIXEL_DESC_RGB5A1.RedShift or
  1088. Pixel.Green shl PIXEL_DESC_RGB5A1.GreenShift or
  1089. Pixel.Blue;
  1090. Inc(pDest, 2);
  1091. end;
  1092. procedure MapRGB8(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1093. begin
  1094. pDest^ := Pixel.Red;
  1095. Inc(pDest);
  1096. pDest^ := Pixel.Green;
  1097. Inc(pDest);
  1098. pDest^ := Pixel.Blue;
  1099. Inc(pDest);
  1100. end;
  1101. procedure MapBGR8(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1102. begin
  1103. pDest^ := Pixel.Blue;
  1104. Inc(pDest);
  1105. pDest^ := Pixel.Green;
  1106. Inc(pDest);
  1107. pDest^ := Pixel.Red;
  1108. Inc(pDest);
  1109. end;
  1110. procedure MapRGBA8(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1111. begin
  1112. pDWord(pDest)^ :=
  1113. Pixel.Alpha shl PIXEL_DESC_RGBA8.AlphaShift or
  1114. Pixel.Blue shl PIXEL_DESC_RGBA8.BlueShift or
  1115. Pixel.Green shl PIXEL_DESC_RGBA8.GreenShift or
  1116. Pixel.Red;
  1117. Inc(pDest, 4);
  1118. end;
  1119. procedure MapBGRA8(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1120. begin
  1121. pDWord(pDest)^ :=
  1122. Pixel.Alpha shl PIXEL_DESC_BGRA8.AlphaShift or
  1123. Pixel.Red shl PIXEL_DESC_BGRA8.RedShift or
  1124. Pixel.Green shl PIXEL_DESC_BGRA8.GreenShift or
  1125. Pixel.Blue;
  1126. Inc(pDest, 4);
  1127. end;
  1128. procedure MapRGB10A2(const Pixel: TglBitmapPixelData; var pDest: pByte);
  1129. begin
  1130. pDWord(pDest)^ :=
  1131. Pixel.Alpha shl PIXEL_DESC_RGB10A2.AlphaShift or
  1132. Pixel.Red shl PIXEL_DESC_RGB10A2.RedShift or
  1133. Pixel.Green shl PIXEL_DESC_RGB10A2.GreenShift or
  1134. Pixel.Blue;
  1135. Inc(pDest, 4);
  1136. end;
  1137. function FormatGetMapFunc(Format: TglBitmapInternalFormat): TglBitmapMapFunc;
  1138. begin
  1139. case Format of
  1140. ifAlpha: Result := MapAlpha;
  1141. ifLuminance: Result := MapLuminance;
  1142. ifDepth8: Result := MapDepth8;
  1143. ifLuminanceAlpha: Result := MapLuminanceAlpha;
  1144. ifRGBA4: Result := MapRGBA4;
  1145. ifR5G6B5: Result := MapR5G6B5;
  1146. ifRGB5A1: Result := MapRGB5A1;
  1147. ifRGB8: Result := MapRGB8;
  1148. ifBGR8: Result := MapBGR8;
  1149. ifRGBA8: Result := MapRGBA8;
  1150. ifBGRA8: Result := MapBGRA8;
  1151. ifRGB10A2: Result := MapRGB10A2;
  1152. else
  1153. raise EglBitmapUnsupportedInternalFormat.Create('FormatGetMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT);
  1154. end;
  1155. end;
  1156. {*
  1157. ** Unmapping
  1158. *}
  1159. procedure UnMapAlpha(var pData: pByte; var Pixel: TglBitmapPixelData);
  1160. begin
  1161. Pixel.Alpha := pData^;
  1162. Pixel.Red := Pixel.PixelDesc.RedRange;
  1163. Pixel.Green := Pixel.PixelDesc.GreenRange;
  1164. Pixel.Blue := Pixel.PixelDesc.BlueRange;
  1165. Inc(pData);
  1166. end;
  1167. procedure UnMapLuminance(var pData: pByte; var Pixel: TglBitmapPixelData);
  1168. begin
  1169. Pixel.Alpha := 255;
  1170. Pixel.Red := pData^;
  1171. Pixel.Green := pData^;
  1172. Pixel.Blue := pData^;
  1173. Inc(pData);
  1174. end;
  1175. procedure UnMapDepth8(var pData: pByte; var Pixel: TglBitmapPixelData);
  1176. begin
  1177. Pixel.Alpha := 255;
  1178. Pixel.Red := pData^;
  1179. Pixel.Green := pData^;
  1180. Pixel.Blue := pData^;
  1181. Inc(pData);
  1182. end;
  1183. procedure UnMapLuminanceAlpha(var pData: pByte; var Pixel: TglBitmapPixelData);
  1184. begin
  1185. Pixel.Red := pData^;
  1186. Pixel.Green := pData^;
  1187. Pixel.Blue := pData^;
  1188. Inc(pData);
  1189. Pixel.Alpha := pData^;
  1190. Inc(pData);
  1191. end;
  1192. procedure UnMapRGBA4(var pData: pByte; var Pixel: TglBitmapPixelData);
  1193. var
  1194. Temp: Word;
  1195. begin
  1196. Temp := pWord(pData)^;
  1197. Pixel.Alpha := Temp shr PIXEL_DESC_RGBA4.AlphaShift and PIXEL_DESC_RGBA4.AlphaRange;
  1198. Pixel.Red := Temp shr PIXEL_DESC_RGBA4.RedShift and PIXEL_DESC_RGBA4.RedRange;
  1199. Pixel.Green := Temp shr PIXEL_DESC_RGBA4.GreenShift and PIXEL_DESC_RGBA4.GreenRange;
  1200. Pixel.Blue := Temp and PIXEL_DESC_RGBA4.BlueRange;
  1201. Inc(pData, 2);
  1202. end;
  1203. procedure UnMapR5G6B5(var pData: pByte; var Pixel: TglBitmapPixelData);
  1204. var
  1205. Temp: Word;
  1206. begin
  1207. Temp := pWord(pData)^;
  1208. Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
  1209. Pixel.Red := Temp shr PIXEL_DESC_R5G6B5.RedShift and PIXEL_DESC_R5G6B5.RedRange;
  1210. Pixel.Green := Temp shr PIXEL_DESC_R5G6B5.GreenShift and PIXEL_DESC_R5G6B5.GreenRange;
  1211. Pixel.Blue := Temp and PIXEL_DESC_R5G6B5.BlueRange;
  1212. Inc(pData, 2);
  1213. end;
  1214. procedure UnMapRGB5A1(var pData: pByte; var Pixel: TglBitmapPixelData);
  1215. var
  1216. Temp: Word;
  1217. begin
  1218. Temp := pWord(pData)^;
  1219. Pixel.Alpha := Temp shr PIXEL_DESC_RGB5A1.AlphaShift and PIXEL_DESC_RGB5A1.AlphaRange;
  1220. Pixel.Red := Temp shr PIXEL_DESC_RGB5A1.RedShift and PIXEL_DESC_RGB5A1.RedRange;
  1221. Pixel.Green := Temp shr PIXEL_DESC_RGB5A1.GreenShift and PIXEL_DESC_RGB5A1.GreenRange;
  1222. Pixel.Blue := Temp and PIXEL_DESC_RGB5A1.BlueRange;
  1223. Inc(pData, 2);
  1224. end;
  1225. procedure UnMapRGB8(var pData: pByte; var Pixel: TglBitmapPixelData);
  1226. begin
  1227. Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
  1228. Pixel.Red := pData^;
  1229. Inc(pData);
  1230. Pixel.Green := pData^;
  1231. Inc(pData);
  1232. Pixel.Blue := pData^;
  1233. Inc(pData);
  1234. end;
  1235. procedure UnMapBGR8(var pData: pByte; var Pixel: TglBitmapPixelData);
  1236. begin
  1237. Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
  1238. Pixel.Blue := pData^;
  1239. Inc(pData);
  1240. Pixel.Green := pData^;
  1241. Inc(pData);
  1242. Pixel.Red := pData^;
  1243. Inc(pData);
  1244. end;
  1245. procedure UnMapRGBA8(var pData: pByte; var Pixel: TglBitmapPixelData);
  1246. begin
  1247. Pixel.Red := pData^;
  1248. Inc(pData);
  1249. Pixel.Green := pData^;
  1250. Inc(pData);
  1251. Pixel.Blue := pData^;
  1252. Inc(pData);
  1253. Pixel.Alpha := pData^;
  1254. Inc(pData);
  1255. end;
  1256. procedure UnMapBGRA8(var pData: pByte; var Pixel: TglBitmapPixelData);
  1257. begin
  1258. Pixel.Blue := pData^;
  1259. Inc(pData);
  1260. Pixel.Green := pData^;
  1261. Inc(pData);
  1262. Pixel.Red := pData^;
  1263. Inc(pData);
  1264. Pixel.Alpha := pData^;
  1265. Inc(pData);
  1266. end;
  1267. procedure UnMapRGB10A2(var pData: pByte; var Pixel: TglBitmapPixelData);
  1268. var
  1269. Temp: DWord;
  1270. begin
  1271. Temp := pDWord(pData)^;
  1272. Pixel.Alpha := Temp shr PIXEL_DESC_RGB10A2.AlphaShift and PIXEL_DESC_RGB10A2.AlphaRange;
  1273. Pixel.Red := Temp shr PIXEL_DESC_RGB10A2.RedShift and PIXEL_DESC_RGB10A2.RedRange;
  1274. Pixel.Green := Temp shr PIXEL_DESC_RGB10A2.GreenShift and PIXEL_DESC_RGB10A2.GreenRange;
  1275. Pixel.Blue := Temp and PIXEL_DESC_RGB10A2.BlueRange;
  1276. Inc(pData, 4);
  1277. end;
  1278. function FormatGetUnMapFunc(Format: TglBitmapInternalFormat): TglBitmapUnMapFunc;
  1279. begin
  1280. case Format of
  1281. ifAlpha: Result := UnmapAlpha;
  1282. ifLuminance: Result := UnMapLuminance;
  1283. ifDepth8: Result := UnMapDepth8;
  1284. ifLuminanceAlpha: Result := UnMapLuminanceAlpha;
  1285. ifRGBA4: Result := UnMapRGBA4;
  1286. ifR5G6B5: Result := UnMapR5G6B5;
  1287. ifRGB5A1: Result := UnMapRGB5A1;
  1288. ifRGB8: Result := UnMapRGB8;
  1289. ifBGR8: Result := UnMapBGR8;
  1290. ifRGBA8: Result := UnMapRGBA8;
  1291. ifBGRA8: Result := UnMapBGRA8;
  1292. ifRGB10A2: Result := UnMapRGB10A2;
  1293. else
  1294. raise EglBitmapUnsupportedInternalFormat.Create('FormatGetUnMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT);
  1295. end;
  1296. end;
  1297. {*
  1298. ** Tools
  1299. *}
  1300. function FormatGetSize (Format: TglBitmapInternalFormat): Single;
  1301. begin
  1302. case Format of
  1303. ifEmpty:
  1304. Result := 0;
  1305. ifDXT1:
  1306. Result := 0.5;
  1307. ifAlpha, ifLuminance, ifDepth8, ifDXT3, ifDXT5:
  1308. Result := 1;
  1309. ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5:
  1310. Result := 2;
  1311. ifBGR8, ifRGB8:
  1312. Result := 3;
  1313. ifBGRA8, ifRGBA8, ifRGB10A2:
  1314. Result := 4;
  1315. else
  1316. raise EglBitmapUnsupportedInternalFormat.Create('FormatGetSize - ' + UNSUPPORTED_INTERNAL_FORMAT);
  1317. end;
  1318. end;
  1319. function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
  1320. begin
  1321. Result := Format in [ifDXT1, ifDXT3, ifDXT5];
  1322. end;
  1323. function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
  1324. begin
  1325. Result := Format in [ifAlpha, ifLuminance, ifDepth8, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5, ifBGR8, ifRGB8, ifBGRA8, ifRGBA8, ifRGB10A2];
  1326. end;
  1327. function FormatIsEmpty(Format: TglBitmapInternalFormat): boolean;
  1328. begin
  1329. Result := Format = ifEmpty;
  1330. end;
  1331. function FormatHasAlpha(Format: TglBitmapInternalFormat): Boolean;
  1332. begin
  1333. Result := Format in [ifDXT1, ifDXT3, ifDXT5 ,ifAlpha, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifBGRA8, ifRGBA8, ifRGB10A2];
  1334. end;
  1335. procedure FormatPreparePixel(var Pixel: TglBitmapPixelData; Format: TglBitmapInternalFormat);
  1336. begin
  1337. FillChar(Pixel, SizeOf(Pixel), #0);
  1338. case Format of
  1339. ifAlpha:
  1340. Pixel.PixelDesc := PIXEL_DESC_ALPHA;
  1341. ifLuminance:
  1342. Pixel.PixelDesc := PIXEL_DESC_LUMINANCE;
  1343. ifDepth8:
  1344. Pixel.PixelDesc := PIXEL_DESC_DEPTH8;
  1345. ifLuminanceAlpha:
  1346. Pixel.PixelDesc := PIXEL_DESC_LUMINANCEALPHA;
  1347. ifRGBA4:
  1348. Pixel.PixelDesc := PIXEL_DESC_RGBA4;
  1349. ifR5G6B5:
  1350. Pixel.PixelDesc := PIXEL_DESC_R5G6B5;
  1351. ifRGB5A1:
  1352. Pixel.PixelDesc := PIXEL_DESC_RGB5A1;
  1353. ifDXT1, ifDXT3, ifDXT5, ifBGRA8:
  1354. Pixel.PixelDesc := PIXEL_DESC_BGRA8;
  1355. ifBGR8:
  1356. Pixel.PixelDesc := PIXEL_DESC_BGR8;
  1357. ifRGB8:
  1358. Pixel.PixelDesc := PIXEL_DESC_RGB8;
  1359. ifRGBA8:
  1360. Pixel.PixelDesc := PIXEL_DESC_RGBA8;
  1361. ifRGB10A2:
  1362. Pixel.PixelDesc := PIXEL_DESC_RGB10A2;
  1363. end;
  1364. Pixel.Red := Pixel.PixelDesc.RedRange;
  1365. Pixel.Green := Pixel.PixelDesc.GreenRange;
  1366. Pixel.Blue := Pixel.PixelDesc.BlueRange;
  1367. Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
  1368. end;
  1369. function FormatGetWithoutAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
  1370. begin
  1371. case Format of
  1372. ifAlpha:
  1373. Result := ifLuminance;
  1374. ifLuminanceAlpha:
  1375. Result := ifLuminance;
  1376. ifRGBA4:
  1377. Result := ifR5G6B5;
  1378. ifRGB5A1:
  1379. Result := ifR5G6B5;
  1380. ifBGRA8:
  1381. Result := ifBGR8;
  1382. ifRGBA8:
  1383. Result := ifRGB8;
  1384. ifRGB10A2:
  1385. Result := ifRGB8;
  1386. else
  1387. Result := Format;
  1388. end;
  1389. end;
  1390. function FormatGetWithAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
  1391. begin
  1392. case Format of
  1393. ifLuminance:
  1394. Result := ifLuminanceAlpha;
  1395. ifR5G6B5:
  1396. Result := ifRGB5A1;
  1397. ifBGR8:
  1398. Result := ifBGRA8;
  1399. ifRGB8:
  1400. Result := ifRGBA8;
  1401. else
  1402. Result := Format;
  1403. end;
  1404. end;
  1405. function FormatGetUncompressed(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
  1406. begin
  1407. case Format of
  1408. ifDXT1:
  1409. Result := ifRGB5A1;
  1410. ifDXT3:
  1411. Result := ifRGBA8;
  1412. ifDXT5:
  1413. Result := ifRGBA8;
  1414. else
  1415. Result := Format;
  1416. end;
  1417. end;
  1418. function FormatGetImageSize(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat): Integer;
  1419. begin
  1420. if (Size.X = 0) and (Size.Y = 0) then
  1421. Result := 0
  1422. else
  1423. Result := Trunc(Max(Size.Y, 1) * Max(Size.X, 1) * FormatGetSize(Format));
  1424. end;
  1425. function FormatGetSupportedFiles(Format: TglBitmapInternalFormat): TglBitmapFileTypes;
  1426. begin
  1427. Result := [];
  1428. {$ifdef GLB_SUPPORT_PNG_WRITE}
  1429. if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifBGR8, ifBGRA8, ifRGB8, ifRGBA8] then
  1430. Result := Result + [ftPNG];
  1431. {$endif}
  1432. {$ifdef GLB_SUPPORT_JPEG_WRITE}
  1433. if Format in [ifLuminance, ifAlpha, ifDepth8, ifRGB8, ifBGR8] then
  1434. Result := Result + [ftJPEG];
  1435. {$endif}
  1436. Result := Result + [ftDDS];
  1437. if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifBGR8, ifRGB8, ifBGRA8, ifRGBA8] then
  1438. Result := Result + [ftTGA];
  1439. if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5, ifRGB8, ifBGR8, ifRGBA8, ifBGRA8, ifRGB10A2] then
  1440. Result := Result + [ftBMP];
  1441. end;
  1442. function FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; Format: TglBitmapInternalFormat): boolean;
  1443. var
  1444. Pix: TglBitmapPixelData;
  1445. begin
  1446. Result := False;
  1447. if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) and (AlphaMask = 0) then
  1448. raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
  1449. FormatPreparePixel(Pix, Format);
  1450. with Pix.PixelDesc do begin
  1451. if RedMask <> 0 then
  1452. if (RedMask <> (RedRange shl RedShift)) then
  1453. Exit;
  1454. if GreenMask <> 0 then
  1455. if (GreenMask <> (GreenRange shl GreenShift)) then
  1456. Exit;
  1457. if BlueMask <> 0 then
  1458. if (BlueMask <> (BlueRange shl BlueShift)) then
  1459. Exit;
  1460. if AlphaMask <> 0 then
  1461. if (AlphaMask <> (AlphaRange shl AlphaShift)) then
  1462. Exit;
  1463. Result := True;
  1464. end;
  1465. end;
  1466. function IsPowerOfTwo(Number: Integer): Boolean;
  1467. begin
  1468. while Number and 1 = 0 do
  1469. Number := Number shr 1;
  1470. Result := Number = 1;
  1471. end;
  1472. function GetBitSize(BitSet: Cardinal): Integer;
  1473. begin
  1474. Result := 0;
  1475. while BitSet > 0 do begin
  1476. if (BitSet and $1) = 1 then
  1477. Inc(Result);
  1478. BitSet := BitSet shr 1;
  1479. end;
  1480. end;
  1481. procedure SwapRGB(pData: pByte; Width: Integer; HasAlpha: Boolean);
  1482. type
  1483. PRGBPix = ^TRGBPix;
  1484. TRGBPix = array [0..2] of byte;
  1485. var
  1486. Temp: Byte;
  1487. begin
  1488. while Width > 0 do begin
  1489. Temp := pRGBPIX(pData)^[0];
  1490. pRGBPIX(pData)^[0] := pRGBPIX(pData)^[2];
  1491. pRGBPIX(pData)^[2] := Temp;
  1492. if HasAlpha then
  1493. Inc(pData, 4)
  1494. else
  1495. Inc(pData, 3);
  1496. Dec(Width);
  1497. end;
  1498. end;
  1499. {$ifdef GLB_DELPHI}
  1500. function CreateGrayPalette: HPALETTE;
  1501. var
  1502. Idx: Integer;
  1503. Pal: PLogPalette;
  1504. begin
  1505. GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
  1506. Pal.palVersion := $300;
  1507. Pal.palNumEntries := 256;
  1508. {$IFOPT R+}
  1509. {$DEFINE GLB_TEMPRANGECHECK}
  1510. {$R-}
  1511. {$ENDIF}
  1512. for Idx := 0 to 256 - 1 do begin
  1513. Pal.palPalEntry[Idx].peRed := Idx;
  1514. Pal.palPalEntry[Idx].peGreen := Idx;
  1515. Pal.palPalEntry[Idx].peBlue := Idx;
  1516. Pal.palPalEntry[Idx].peFlags := 0;
  1517. end;
  1518. {$IFDEF GLB_TEMPRANGECHECK}
  1519. {$UNDEF GLB_TEMPRANGECHECK}
  1520. {$R+}
  1521. {$ENDIF}
  1522. Result := CreatePalette(Pal^);
  1523. FreeMem(Pal);
  1524. end;
  1525. {$endif}
  1526. {$ifdef GLB_SDL_IMAGE}
  1527. function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
  1528. begin
  1529. Result := TStream(context^.unknown.data1).Seek(offset, whence);
  1530. end;
  1531. function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
  1532. begin
  1533. Result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
  1534. end;
  1535. function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
  1536. begin
  1537. Result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
  1538. end;
  1539. function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
  1540. begin
  1541. Result := 0;
  1542. end;
  1543. function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
  1544. begin
  1545. Result := SDL_AllocRW;
  1546. if Result = nil then
  1547. raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
  1548. Result^.seek := glBitmapRWseek;
  1549. Result^.read := glBitmapRWread;
  1550. Result^.write := glBitmapRWwrite;
  1551. Result^.close := glBitmapRWclose;
  1552. Result^.unknown.data1 := Stream;
  1553. end;
  1554. {$endif}
  1555. {*
  1556. ** Helper functions
  1557. *}
  1558. function LoadTexture(Filename: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$endif}): Boolean;
  1559. var
  1560. glBitmap: TglBitmap2D;
  1561. begin
  1562. Result := false;
  1563. Texture := 0;
  1564. {$ifdef GLB_DELPHI}
  1565. if Instance = 0 then
  1566. Instance := HInstance;
  1567. if (LoadFromRes) then
  1568. glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName)
  1569. else
  1570. {$endif}
  1571. glBitmap := TglBitmap2D.Create(FileName);
  1572. try
  1573. glBitmap.DeleteTextureOnFree := False;
  1574. glBitmap.FreeDataAfterGenTexture := False;
  1575. glBitmap.GenTexture(True);
  1576. if (glBitmap.ID > 0) then begin
  1577. Texture := glBitmap.ID;
  1578. Result := True;
  1579. end;
  1580. finally
  1581. glBitmap.Free;
  1582. end;
  1583. end;
  1584. function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$endif}): Boolean;
  1585. var
  1586. CM: TglBitmapCubeMap;
  1587. begin
  1588. Texture := 0;
  1589. {$ifdef GLB_DELPHI}
  1590. if Instance = 0 then
  1591. Instance := HInstance;
  1592. {$endif}
  1593. CM := TglBitmapCubeMap.Create;
  1594. try
  1595. CM.DeleteTextureOnFree := False;
  1596. // Maps
  1597. {$ifdef GLB_DELPHI}
  1598. if (LoadFromRes) then
  1599. CM.LoadFromResource(Instance, PositiveX)
  1600. else
  1601. {$endif}
  1602. CM.LoadFromFile(PositiveX);
  1603. CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
  1604. {$ifdef GLB_DELPHI}
  1605. if (LoadFromRes) then
  1606. CM.LoadFromResource(Instance, NegativeX)
  1607. else
  1608. {$endif}
  1609. CM.LoadFromFile(NegativeX);
  1610. CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
  1611. {$ifdef GLB_DELPHI}
  1612. if (LoadFromRes) then
  1613. CM.LoadFromResource(Instance, PositiveY)
  1614. else
  1615. {$endif}
  1616. CM.LoadFromFile(PositiveY);
  1617. CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
  1618. {$ifdef GLB_DELPHI}
  1619. if (LoadFromRes) then
  1620. CM.LoadFromResource(Instance, NegativeY)
  1621. else
  1622. {$endif}
  1623. CM.LoadFromFile(NegativeY);
  1624. CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
  1625. {$ifdef GLB_DELPHI}
  1626. if (LoadFromRes) then
  1627. CM.LoadFromResource(Instance, PositiveZ)
  1628. else
  1629. {$endif}
  1630. CM.LoadFromFile(PositiveZ);
  1631. CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
  1632. {$ifdef GLB_DELPHI}
  1633. if (LoadFromRes) then
  1634. CM.LoadFromResource(Instance, NegativeZ)
  1635. else
  1636. {$endif}
  1637. CM.LoadFromFile(NegativeZ);
  1638. CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
  1639. Texture := CM.ID;
  1640. Result := True;
  1641. finally
  1642. CM.Free;
  1643. end;
  1644. end;
  1645. function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
  1646. var
  1647. NM: TglBitmapNormalMap;
  1648. begin
  1649. Texture := 0;
  1650. NM := TglBitmapNormalMap.Create;
  1651. try
  1652. NM.DeleteTextureOnFree := False;
  1653. NM.GenerateNormalMap(Size);
  1654. Texture := NM.ID;
  1655. Result := True;
  1656. finally
  1657. NM.Free;
  1658. end;
  1659. end;
  1660. {*
  1661. ** Defaults
  1662. *}
  1663. procedure glBitmapSetDefaultFormat(Format: TglBitmapFormat);
  1664. begin
  1665. glBitmapDefaultFormat := Format;
  1666. end;
  1667. procedure glBitmapSetDefaultDeleteTextureOnFree(DeleteTextureOnFree: Boolean);
  1668. begin
  1669. glBitmapDefaultDeleteTextureOnFree := DeleteTextureOnFree;
  1670. end;
  1671. procedure glBitmapSetDefaultFilter(Min, Mag: Integer);
  1672. begin
  1673. glBitmapDefaultFilterMin := Min;
  1674. glBitmapDefaultFilterMag := Mag;
  1675. end;
  1676. procedure glBitmapSetDefaultWrap(S: Integer; T: Integer; R: Integer);
  1677. begin
  1678. glBitmapDefaultWrapS := S;
  1679. glBitmapDefaultWrapT := T;
  1680. glBitmapDefaultWrapR := R;
  1681. end;
  1682. procedure glBitmapSetDefaultFreeDataAfterGenTexture(FreeData: Boolean);
  1683. begin
  1684. glBitmapDefaultFreeDataAfterGenTextures := FreeData;
  1685. end;
  1686. function glBitmapGetDefaultFormat: TglBitmapFormat;
  1687. begin
  1688. Result := glBitmapDefaultFormat;
  1689. end;
  1690. function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
  1691. begin
  1692. Result := glBitmapDefaultDeleteTextureOnFree;
  1693. end;
  1694. procedure glBitmapGetDefaultFilter(var Min, Mag: Integer);
  1695. begin
  1696. Min := glBitmapDefaultFilterMin;
  1697. Mag := glBitmapDefaultFilterMag;
  1698. end;
  1699. procedure glBitmapGetDefaultTextureWrap(var S, T, R: Integer);
  1700. begin
  1701. S := glBitmapDefaultWrapS;
  1702. T := glBitmapDefaultWrapT;
  1703. R := glBitmapDefaultWrapR;
  1704. end;
  1705. function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
  1706. begin
  1707. Result := glBitmapDefaultFreeDataAfterGenTextures;
  1708. end;
  1709. { TglBitmap }
  1710. procedure TglBitmap.AfterConstruction;
  1711. begin
  1712. inherited;
  1713. fID := 0;
  1714. fTarget := 0;
  1715. fMipMap := mmMipmap;
  1716. fIsResident := False;
  1717. // get defaults
  1718. fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
  1719. fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
  1720. fFormat := glBitmapGetDefaultFormat;
  1721. glBitmapGetDefaultFilter(fFilterMin, fFilterMag);
  1722. glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
  1723. end;
  1724. procedure TglBitmap.BeforeDestruction;
  1725. begin
  1726. SetDataPointer(nil, ifEmpty);
  1727. if ((ID > 0) and (fDeleteTextureOnFree)) then
  1728. glDeleteTextures(1, @ID);
  1729. inherited;
  1730. end;
  1731. constructor TglBitmap.Create;
  1732. begin
  1733. {$ifndef GLB_NO_NATIVE_GL}
  1734. ReadOpenGLExtensions;
  1735. {$endif}
  1736. if (ClassType = TglBitmap) then
  1737. raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
  1738. inherited Create;
  1739. end;
  1740. constructor TglBitmap.Create(FileName: String);
  1741. begin
  1742. Create;
  1743. LoadFromFile(FileName);
  1744. end;
  1745. constructor TglBitmap.Create(Stream: TStream);
  1746. begin
  1747. Create;
  1748. LoadFromStream(Stream);
  1749. end;
  1750. {$ifdef GLB_DELPHI}
  1751. constructor TglBitmap.CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar);
  1752. begin
  1753. Create;
  1754. LoadFromResource(Instance, Resource, ResType);
  1755. end;
  1756. constructor TglBitmap.Create(Instance: Cardinal; Resource: String; ResType: PChar);
  1757. begin
  1758. Create;
  1759. LoadFromResource(Instance, Resource, ResType);
  1760. end;
  1761. constructor TglBitmap.Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar);
  1762. begin
  1763. Create;
  1764. LoadFromResourceID(Instance, ResourceID, ResType);
  1765. end;
  1766. {$endif}
  1767. constructor TglBitmap.Create(Size: TglBitmapPixelPosition;
  1768. Format: TglBitmapInternalFormat);
  1769. var
  1770. Image: pByte;
  1771. ImageSize: Integer;
  1772. begin
  1773. Create;
  1774. ImageSize := FormatGetImageSize(Size, Format);
  1775. GetMem(Image, ImageSize);
  1776. try
  1777. FillChar(Image^, ImageSize, #$FF);
  1778. SetDataPointer(Image, Format, Size.X, Size.Y);
  1779. except
  1780. FreeMem(Image);
  1781. raise;
  1782. end;
  1783. end;
  1784. constructor TglBitmap.Create(Size: TglBitmapPixelPosition;
  1785. Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer);
  1786. begin
  1787. Create;
  1788. LoadFromFunc(Size, Func, Format, CustomData);
  1789. end;
  1790. function TglBitmap.Clone: TglBitmap;
  1791. var
  1792. Temp: TglBitmap;
  1793. TempPtr: pByte;
  1794. Size: Integer;
  1795. begin
  1796. Temp := ClassType.Create as TglBitmap;
  1797. try
  1798. // copy texture data if assigned
  1799. if Assigned(Data) then begin
  1800. Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat);
  1801. GetMem(TempPtr, Size);
  1802. try
  1803. Move(Data^, TempPtr^, Size);
  1804. Temp.SetDataPointer(TempPtr, InternalFormat, Width, Height);
  1805. except
  1806. FreeMem(TempPtr);
  1807. raise;
  1808. end;
  1809. end else
  1810. Temp.SetDataPointer(nil, InternalFormat, Width, Height);
  1811. // copy properties
  1812. Temp.fID := ID;
  1813. Temp.fTarget := Target;
  1814. Temp.fFormat := Format;
  1815. Temp.fMipMap := MipMap;
  1816. Temp.fAnisotropic := Anisotropic;
  1817. Temp.fBorderColor := fBorderColor;
  1818. Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
  1819. Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
  1820. Temp.fFilterMin := fFilterMin;
  1821. Temp.fFilterMag := fFilterMag;
  1822. Temp.fWrapS := fWrapS;
  1823. Temp.fWrapT := fWrapT;
  1824. Temp.fWrapR := fWrapR;
  1825. Temp.fFilename := fFilename;
  1826. Temp.fCustomName := fCustomName;
  1827. Temp.fCustomNameW := fCustomNameW;
  1828. Temp.fCustomDataPointer := fCustomDataPointer;
  1829. Result := Temp;
  1830. except
  1831. FreeAndNil(Temp);
  1832. raise;
  1833. end;
  1834. end;
  1835. procedure TglBitmap.LoadFromFile(FileName: String);
  1836. var
  1837. FS: TFileStream;
  1838. begin
  1839. fFilename := FileName;
  1840. FS := TFileStream.Create(FileName, fmOpenRead);
  1841. try
  1842. FS.Position := 0;
  1843. LoadFromStream(FS);
  1844. finally
  1845. FS.Free;
  1846. end;
  1847. end;
  1848. procedure TglBitmap.LoadFromStream(Stream: TStream);
  1849. begin
  1850. {$ifdef GLB_SUPPORT_PNG_READ}
  1851. if not LoadPNG(Stream) then
  1852. {$endif}
  1853. {$ifdef GLB_SUPPORT_JPEG_READ}
  1854. if not LoadJPEG(Stream) then
  1855. {$endif}
  1856. if not LoadDDS(Stream) then
  1857. if not LoadTGA(Stream) then
  1858. if not LoadBMP(Stream) then
  1859. raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
  1860. end;
  1861. {$ifdef GLB_DELPHI}
  1862. procedure TglBitmap.LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar);
  1863. var
  1864. RS: TResourceStream;
  1865. TempPos: Integer;
  1866. ResTypeStr: String;
  1867. TempResType: PChar;
  1868. begin
  1869. if Assigned(ResType) then
  1870. TempResType := ResType
  1871. else
  1872. begin
  1873. TempPos := Pos('.', Resource);
  1874. ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
  1875. Resource := UpperCase(Copy(Resource, 0, TempPos -1));
  1876. TempResType := PChar(ResTypeStr);
  1877. end;
  1878. RS := TResourceStream.Create(Instance, Resource, TempResType);
  1879. try
  1880. LoadFromStream(RS);
  1881. finally
  1882. RS.Free;
  1883. end;
  1884. end;
  1885. procedure TglBitmap.LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar);
  1886. var
  1887. RS: TResourceStream;
  1888. begin
  1889. RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
  1890. try
  1891. LoadFromStream(RS);
  1892. finally
  1893. RS.Free;
  1894. end;
  1895. end;
  1896. {$endif}
  1897. procedure TglBitmap.LoadFromFunc(Size: TglBitmapPixelPosition;
  1898. Func: TglBitmapFunction; Format: TglBitmapInternalFormat; CustomData: Pointer);
  1899. var
  1900. Image: pByte;
  1901. ImageSize: Integer;
  1902. begin
  1903. ImageSize := FormatGetImageSize(Size, Format);
  1904. GetMem(Image, ImageSize);
  1905. try
  1906. FillChar(Image^, ImageSize, #$FF);
  1907. SetDataPointer(Image, Format, Size.X, Size.Y);
  1908. except
  1909. FreeMem(Image);
  1910. raise;
  1911. end;
  1912. AddFunc(Self, Func, False, Format, CustomData)
  1913. end;
  1914. procedure TglBitmap.SaveToFile(FileName: String; FileType: TglBitmapFileType);
  1915. var
  1916. FS: TFileStream;
  1917. begin
  1918. FS := TFileStream.Create(FileName, fmCreate);
  1919. try
  1920. FS.Position := 0;
  1921. SaveToStream(FS, FileType);
  1922. finally
  1923. FS.Free;
  1924. end;
  1925. end;
  1926. procedure TglBitmap.SaveToStream(Stream: TStream; FileType: TglBitmapFileType);
  1927. begin
  1928. case FileType of
  1929. {$ifdef GLB_SUPPORT_PNG_WRITE}
  1930. ftPNG: SavePng(Stream);
  1931. {$endif}
  1932. {$ifdef GLB_SUPPORT_JPEG_WRITE}
  1933. ftJPEG: SaveJPEG(Stream);
  1934. {$endif}
  1935. ftDDS: SaveDDS(Stream);
  1936. ftTGA: SaveTGA(Stream);
  1937. ftBMP: SaveBMP(Stream);
  1938. end;
  1939. end;
  1940. {$ifdef GLB_SDL}
  1941. function TglBitmap.AssignToSurface(out Surface: PSDL_Surface): boolean;
  1942. var
  1943. Row, RowSize: Integer;
  1944. pSource, pData: PByte;
  1945. TempDepth: Integer;
  1946. Pix: TglBitmapPixelData;
  1947. function GetRowPointer(Row: Integer): pByte;
  1948. begin
  1949. Result := Surface.pixels;
  1950. Inc(Result, Row * RowSize);
  1951. end;
  1952. begin
  1953. Result := False;
  1954. if not FormatIsUncompressed(InternalFormat) then
  1955. raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
  1956. if Assigned(Data) then begin
  1957. case Trunc(FormatGetSize(InternalFormat)) of
  1958. 1: TempDepth := 8;
  1959. 2: TempDepth := 16;
  1960. 3: TempDepth := 24;
  1961. 4: TempDepth := 32;
  1962. else
  1963. raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
  1964. end;
  1965. FormatPreparePixel(Pix, InternalFormat);
  1966. with Pix.PixelDesc do
  1967. Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth, RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift);
  1968. pSource := Data;
  1969. RowSize := Trunc(FileWidth * FormatGetSize(InternalFormat));
  1970. for Row := 0 to FileHeight -1 do begin
  1971. pData := GetRowPointer(Row);
  1972. if Assigned(pData) then begin
  1973. Move(pSource^, pData^, RowSize);
  1974. Inc(pSource, RowSize);
  1975. end;
  1976. end;
  1977. Result := True;
  1978. end;
  1979. end;
  1980. function TglBitmap.AssignFromSurface(const Surface: PSDL_Surface): boolean;
  1981. var
  1982. pSource, pData, pTempData: PByte;
  1983. Row, RowSize, TempWidth, TempHeight: Integer;
  1984. IntFormat: TglBitmapInternalFormat;
  1985. function GetRowPointer(Row: Integer): pByte;
  1986. begin
  1987. Result := Surface^.pixels;
  1988. Inc(Result, Row * RowSize);
  1989. end;
  1990. begin
  1991. Result := False;
  1992. if (Assigned(Surface)) then begin
  1993. with Surface^.format^ do begin
  1994. if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminance) then
  1995. IntFormat := ifLuminance
  1996. else
  1997. if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminanceAlpha) then
  1998. IntFormat := ifLuminanceAlpha
  1999. else
  2000. if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA4) then
  2001. IntFormat := ifRGBA4
  2002. else
  2003. if FormatCheckFormat(RMask, GMask, BMask, AMask, ifR5G6B5) then
  2004. IntFormat := ifR5G6B5
  2005. else
  2006. if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB5A1) then
  2007. IntFormat := ifRGB5A1
  2008. else
  2009. if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGR8) then
  2010. IntFormat := ifBGR8
  2011. else
  2012. if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB8) then
  2013. IntFormat := ifRGB8
  2014. else
  2015. if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGRA8) then
  2016. IntFormat := ifBGRA8
  2017. else
  2018. if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA8) then
  2019. IntFormat := ifRGBA8
  2020. else
  2021. if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB10A2) then
  2022. IntFormat := ifRGB10A2
  2023. else
  2024. raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
  2025. end;
  2026. TempWidth := Surface^.w;
  2027. TempHeight := Surface^.h;
  2028. RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
  2029. GetMem(pData, TempHeight * RowSize);
  2030. try
  2031. pTempData := pData;
  2032. for Row := 0 to TempHeight -1 do begin
  2033. pSource := GetRowPointer(Row);
  2034. if (Assigned(pSource)) then begin
  2035. Move(pSource^, pTempData^, RowSize);
  2036. Inc(pTempData, RowSize);
  2037. end;
  2038. end;
  2039. SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
  2040. Result := True;
  2041. except
  2042. FreeMem(pData);
  2043. raise;
  2044. end;
  2045. end;
  2046. end;
  2047. function TglBitmap.AssignAlphaToSurface(out Surface: PSDL_Surface): boolean;
  2048. var
  2049. Row, Col, AlphaInterleave: Integer;
  2050. pSource, pDest: PByte;
  2051. function GetRowPointer(Row: Integer): pByte;
  2052. begin
  2053. Result := Surface.pixels;
  2054. Inc(Result, Row * Width);
  2055. end;
  2056. begin
  2057. Result := False;
  2058. if Assigned(Data) then begin
  2059. if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifBGRA8, ifRGBA8] then begin
  2060. Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
  2061. case InternalFormat of
  2062. ifLuminanceAlpha:
  2063. AlphaInterleave := 1;
  2064. ifBGRA8, ifRGBA8:
  2065. AlphaInterleave := 3;
  2066. else
  2067. AlphaInterleave := 0;
  2068. end;
  2069. // Copy Data
  2070. pSource := Data;
  2071. for Row := 0 to Height -1 do begin
  2072. pDest := GetRowPointer(Row);
  2073. if Assigned(pDest) then begin
  2074. for Col := 0 to Width -1 do begin
  2075. Inc(pSource, AlphaInterleave);
  2076. pDest^ := pSource^;
  2077. Inc(pDest);
  2078. Inc(pSource);
  2079. end;
  2080. end;
  2081. end;
  2082. Result := True;
  2083. end;
  2084. end;
  2085. end;
  2086. function TglBitmap.AddAlphaFromSurface(Surface: PSDL_Surface; Func: TglBitmapFunction; CustomData: Pointer): boolean;
  2087. var
  2088. glBitmap: TglBitmap2D;
  2089. begin
  2090. glBitmap := TglBitmap2D.Create;
  2091. try
  2092. glBitmap.AssignFromSurface(Surface);
  2093. Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
  2094. finally
  2095. glBitmap.Free;
  2096. end;
  2097. end;
  2098. {$endif}
  2099. {$ifdef GLB_DELPHI}
  2100. function TglBitmap.AssignFromBitmap(const Bitmap: TBitmap): boolean;
  2101. var
  2102. pSource, pData, pTempData: PByte;
  2103. Row, RowSize, TempWidth, TempHeight: Integer;
  2104. IntFormat: TglBitmapInternalFormat;
  2105. begin
  2106. Result := False;
  2107. if (Assigned(Bitmap)) then begin
  2108. case Bitmap.PixelFormat of
  2109. pf8bit:
  2110. IntFormat := ifLuminance;
  2111. pf15bit:
  2112. IntFormat := ifRGB5A1;
  2113. pf16bit:
  2114. IntFormat := ifR5G6B5;
  2115. pf24bit:
  2116. IntFormat := ifBGR8;
  2117. pf32bit:
  2118. IntFormat := ifBGRA8;
  2119. else
  2120. raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
  2121. end;
  2122. TempWidth := Bitmap.Width;
  2123. TempHeight := Bitmap.Height;
  2124. RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
  2125. GetMem(pData, TempHeight * RowSize);
  2126. try
  2127. pTempData := pData;
  2128. for Row := 0 to TempHeight -1 do begin
  2129. pSource := Bitmap.Scanline[Row];
  2130. if (Assigned(pSource)) then begin
  2131. Move(pSource^, pTempData^, RowSize);
  2132. Inc(pTempData, RowSize);
  2133. end;
  2134. end;
  2135. SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
  2136. Result := True;
  2137. except
  2138. FreeMem(pData);
  2139. raise;
  2140. end;
  2141. end;
  2142. end;
  2143. function TglBitmap.AssignToBitmap(const Bitmap: TBitmap): boolean;
  2144. var
  2145. Row: Integer;
  2146. pSource, pData: PByte;
  2147. begin
  2148. Result := False;
  2149. if Assigned(Data) then begin
  2150. if Assigned(Bitmap) then begin
  2151. Bitmap.Width := Width;
  2152. Bitmap.Height := Height;
  2153. case InternalFormat of
  2154. ifAlpha, ifLuminance, ifDepth8:
  2155. begin
  2156. Bitmap.PixelFormat := pf8bit;
  2157. Bitmap.Palette := CreateGrayPalette;
  2158. end;
  2159. ifRGB5A1:
  2160. Bitmap.PixelFormat := pf15bit;
  2161. ifR5G6B5:
  2162. Bitmap.PixelFormat := pf16bit;
  2163. ifRGB8, ifBGR8:
  2164. Bitmap.PixelFormat := pf24bit;
  2165. ifRGBA8, ifBGRA8:
  2166. Bitmap.PixelFormat := pf32bit;
  2167. else
  2168. raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
  2169. end;
  2170. pSource := Data;
  2171. for Row := 0 to FileHeight -1 do begin
  2172. pData := Bitmap.Scanline[Row];
  2173. Move(pSource^, pData^, fRowSize);
  2174. Inc(pSource, fRowSize);
  2175. // swap RGB(A) to BGR(A)
  2176. if InternalFormat in [ifRGB8, ifRGBA8] then
  2177. SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8);
  2178. end;
  2179. Result := True;
  2180. end;
  2181. end;
  2182. end;
  2183. function TglBitmap.AssignAlphaToBitmap(const Bitmap: TBitmap): boolean;
  2184. var
  2185. Row, Col, AlphaInterleave: Integer;
  2186. pSource, pDest: PByte;
  2187. begin
  2188. Result := False;
  2189. if Assigned(Data) then begin
  2190. if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin
  2191. if Assigned(Bitmap) then begin
  2192. Bitmap.PixelFormat := pf8bit;
  2193. Bitmap.Palette := CreateGrayPalette;
  2194. Bitmap.Width := Width;
  2195. Bitmap.Height := Height;
  2196. case InternalFormat of
  2197. ifLuminanceAlpha:
  2198. AlphaInterleave := 1;
  2199. ifRGBA8, ifBGRA8:
  2200. AlphaInterleave := 3;
  2201. else
  2202. AlphaInterleave := 0;
  2203. end;
  2204. // Copy Data
  2205. pSource := Data;
  2206. for Row := 0 to Height -1 do begin
  2207. pDest := Bitmap.Scanline[Row];
  2208. if Assigned(pDest) then begin
  2209. for Col := 0 to Width -1 do begin
  2210. Inc(pSource, AlphaInterleave);
  2211. pDest^ := pSource^;
  2212. Inc(pDest);
  2213. Inc(pSource);
  2214. end;
  2215. end;
  2216. end;
  2217. Result := True;
  2218. end;
  2219. end;
  2220. end;
  2221. end;
  2222. function TglBitmap.AddAlphaFromBitmap(Bitmap: TBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean;
  2223. var
  2224. glBitmap: TglBitmap2D;
  2225. begin
  2226. glBitmap := TglBitmap2D.Create;
  2227. try
  2228. glBitmap.AssignFromBitmap(Bitmap);
  2229. Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
  2230. finally
  2231. glBitmap.Free;
  2232. end;
  2233. end;
  2234. {$endif}
  2235. function TglBitmap.AddAlphaFromFile(FileName: String; Func: TglBitmapFunction; CustomData: Pointer): boolean;
  2236. var
  2237. FS: TFileStream;
  2238. begin
  2239. FS := TFileStream.Create(FileName, fmOpenRead);
  2240. try
  2241. Result := AddAlphaFromStream(FS, Func, CustomData);
  2242. finally
  2243. FS.Free;
  2244. end;
  2245. end;
  2246. function TglBitmap.AddAlphaFromStream(Stream: TStream; Func: TglBitmapFunction; CustomData: Pointer): boolean;
  2247. var
  2248. glBitmap: TglBitmap2D;
  2249. begin
  2250. glBitmap := TglBitmap2D.Create(Stream);
  2251. try
  2252. Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
  2253. finally
  2254. glBitmap.Free;
  2255. end;
  2256. end;
  2257. {$ifdef GLB_DELPHI}
  2258. function TglBitmap.AddAlphaFromResource(Instance: Cardinal; Resource: String;
  2259. ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean;
  2260. var
  2261. RS: TResourceStream;
  2262. TempPos: Integer;
  2263. ResTypeStr: String;
  2264. TempResType: PChar;
  2265. begin
  2266. if Assigned(ResType) then
  2267. TempResType := ResType
  2268. else
  2269. begin
  2270. TempPos := Pos('.', Resource);
  2271. ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
  2272. Resource := UpperCase(Copy(Resource, 0, TempPos -1));
  2273. TempResType := PChar(ResTypeStr);
  2274. end;
  2275. RS := TResourceStream.Create(Instance, Resource, TempResType);
  2276. try
  2277. Result := AddAlphaFromStream(RS, Func, CustomData);
  2278. finally
  2279. RS.Free;
  2280. end;
  2281. end;
  2282. function TglBitmap.AddAlphaFromResourceID(Instance: Cardinal; ResourceID: Integer;
  2283. ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean;
  2284. var
  2285. RS: TResourceStream;
  2286. begin
  2287. RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
  2288. try
  2289. Result := AddAlphaFromStream(RS, Func, CustomData);
  2290. finally
  2291. RS.Free;
  2292. end;
  2293. end;
  2294. {$endif}
  2295. procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
  2296. begin
  2297. with FuncRec do begin
  2298. Dest.Red := Source.Red;
  2299. Dest.Green := Source.Green;
  2300. Dest.Blue := Source.Blue;
  2301. with TglBitmapPixelData(CustomData^) do
  2302. if ((Dest.Red <= Red ) and (Dest.Red >= PixelDesc.RedRange ) and
  2303. (Dest.Green <= Green) and (Dest.Green >= PixelDesc.GreenRange) and
  2304. (Dest.Blue <= Blue ) and (Dest.Blue >= PixelDesc.BlueRange )) then
  2305. Dest.Alpha := 0
  2306. else
  2307. Dest.Alpha := Dest.PixelDesc.AlphaRange;
  2308. end;
  2309. end;
  2310. function TglBitmap.AddAlphaFromColorKey(Red, Green, Blue, Deviation: Byte): Boolean;
  2311. begin
  2312. Result := AddAlphaFromColorKeyFloat(Red / $FF, Green / $FF, Blue / $FF, Deviation / $FF);
  2313. end;
  2314. function TglBitmap.AddAlphaFromColorKeyRange(Red, Green, Blue: Cardinal; Deviation: Cardinal = 0): Boolean;
  2315. var
  2316. PixelData: TglBitmapPixelData;
  2317. begin
  2318. FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
  2319. Result := AddAlphaFromColorKeyFloat(
  2320. Red / PixelData.PixelDesc.RedRange,
  2321. Green / PixelData.PixelDesc.GreenRange,
  2322. Blue / PixelData.PixelDesc.BlueRange,
  2323. Deviation / Max(PixelData.PixelDesc.RedRange, Max(PixelData.PixelDesc.GreenRange, PixelData.PixelDesc.BlueRange)));
  2324. end;
  2325. function TglBitmap.AddAlphaFromColorKeyFloat(Red, Green, Blue: Single; Deviation: Single = 0): Boolean;
  2326. var
  2327. TempR, TempG, TempB: Cardinal;
  2328. PixelData: TglBitmapPixelData;
  2329. begin
  2330. FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
  2331. // Calculate Colorrange
  2332. with PixelData.PixelDesc do begin
  2333. TempR := Trunc(RedRange * Deviation);
  2334. TempG := Trunc(GreenRange * Deviation);
  2335. TempB := Trunc(BlueRange * Deviation);
  2336. PixelData.Red := Min(RedRange, Trunc(RedRange * Red) + TempR);
  2337. RedRange := Max(0, Trunc(RedRange * Red) - TempR);
  2338. PixelData.Green := Min(GreenRange, Trunc(GreenRange * Green) + TempG);
  2339. GreenRange := Max(0, Trunc(GreenRange * Green) - TempG);
  2340. PixelData.Blue := Min(BlueRange, Trunc(BlueRange * Blue) + TempB);
  2341. BlueRange := Max(0, Trunc(BlueRange * Blue) - TempB);
  2342. PixelData.Alpha := 0;
  2343. AlphaRange := 0;
  2344. end;
  2345. Result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
  2346. end;
  2347. procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
  2348. begin
  2349. with FuncRec do begin
  2350. Dest.Red := Source.Red;
  2351. Dest.Green := Source.Green;
  2352. Dest.Blue := Source.Blue;
  2353. with TglBitmapPixelData(CustomData^) do
  2354. Dest.Alpha := Alpha;
  2355. end;
  2356. end;
  2357. function TglBitmap.AddAlphaFromValue(Alpha: Byte): Boolean;
  2358. begin
  2359. Result := AddAlphaFromValueFloat(Alpha / $FF);
  2360. end;
  2361. function TglBitmap.AddAlphaFromValueFloat(Alpha: Single): Boolean;
  2362. var
  2363. PixelData: TglBitmapPixelData;
  2364. begin
  2365. FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
  2366. with PixelData.PixelDesc do
  2367. PixelData.Alpha := Min(AlphaRange, Max(0, Round(AlphaRange * Alpha)));
  2368. Result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData);
  2369. end;
  2370. function TglBitmap.AddAlphaFromValueRange(Alpha: Cardinal): Boolean;
  2371. var
  2372. PixelData: TglBitmapPixelData;
  2373. begin
  2374. FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
  2375. Result := AddAlphaFromValueFloat(Alpha / PixelData.PixelDesc.AlphaRange);
  2376. end;
  2377. procedure glBitmapInvertFunc(var FuncRec: TglBitmapFunctionRec);
  2378. begin
  2379. with FuncRec do begin
  2380. Dest.Red := Source.Red;
  2381. Dest.Green := Source.Green;
  2382. Dest.Blue := Source.Blue;
  2383. Dest.Alpha := Source.Alpha;
  2384. if (Integer(CustomData) and $1 > 0) then begin
  2385. Dest.Red := Dest.Red xor Dest.PixelDesc.RedRange;
  2386. Dest.Green := Dest.Green xor Dest.PixelDesc.GreenRange;
  2387. Dest.Blue := Dest.Blue xor Dest.PixelDesc.BlueRange;
  2388. end;
  2389. if (Integer(CustomData) and $2 > 0) then begin
  2390. Dest.Alpha := Dest.Alpha xor Dest.PixelDesc.AlphaRange;
  2391. end;
  2392. end;
  2393. end;
  2394. procedure TglBitmap.Invert(UseRGB, UseAlpha: Boolean);
  2395. begin
  2396. if ((UseRGB) or (UseAlpha)) then
  2397. AddFunc(glBitmapInvertFunc, False, Pointer(Integer(UseAlpha) shl 1 or Integer(UseRGB)));
  2398. end;
  2399. procedure TglBitmap.SetFilter(Min, Mag: Integer);
  2400. begin
  2401. case Min of
  2402. GL_NEAREST:
  2403. fFilterMin := GL_NEAREST;
  2404. GL_LINEAR:
  2405. fFilterMin := GL_LINEAR;
  2406. GL_NEAREST_MIPMAP_NEAREST:
  2407. fFilterMin := GL_NEAREST_MIPMAP_NEAREST;
  2408. GL_LINEAR_MIPMAP_NEAREST:
  2409. fFilterMin := GL_LINEAR_MIPMAP_NEAREST;
  2410. GL_NEAREST_MIPMAP_LINEAR:
  2411. fFilterMin := GL_NEAREST_MIPMAP_LINEAR;
  2412. GL_LINEAR_MIPMAP_LINEAR:
  2413. fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
  2414. else
  2415. raise EglBitmapException.Create('SetFilter - Unknow Minfilter.');
  2416. end;
  2417. case Mag of
  2418. GL_NEAREST:
  2419. fFilterMag := GL_NEAREST;
  2420. GL_LINEAR:
  2421. fFilterMag := GL_LINEAR;
  2422. else
  2423. raise EglBitmapException.Create('SetFilter - Unknow Magfilter.');
  2424. end;
  2425. // If texture is created then assign filter
  2426. if ID > 0 then begin
  2427. Bind(False);
  2428. glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
  2429. if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE_ARB) then begin
  2430. case fFilterMin of
  2431. GL_NEAREST, GL_LINEAR:
  2432. glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
  2433. GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR:
  2434. glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  2435. GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR:
  2436. glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  2437. end;
  2438. end else
  2439. glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
  2440. end;
  2441. end;
  2442. procedure TglBitmap.SetWrap(S: Integer; T: Integer; R: Integer);
  2443. begin
  2444. case S of
  2445. GL_CLAMP:
  2446. fWrapS := GL_CLAMP;
  2447. GL_REPEAT:
  2448. fWrapS := GL_REPEAT;
  2449. GL_CLAMP_TO_EDGE:
  2450. begin
  2451. if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
  2452. fWrapS := GL_CLAMP_TO_EDGE
  2453. else
  2454. fWrapS := GL_CLAMP;
  2455. end;
  2456. GL_CLAMP_TO_BORDER:
  2457. begin
  2458. if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
  2459. fWrapS := GL_CLAMP_TO_BORDER
  2460. else
  2461. fWrapS := GL_CLAMP;
  2462. end;
  2463. GL_MIRRORED_REPEAT:
  2464. begin
  2465. if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
  2466. fWrapS := GL_MIRRORED_REPEAT
  2467. else
  2468. raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
  2469. end;
  2470. else
  2471. raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).');
  2472. end;
  2473. case T of
  2474. GL_CLAMP:
  2475. fWrapT := GL_CLAMP;
  2476. GL_REPEAT:
  2477. fWrapT := GL_REPEAT;
  2478. GL_CLAMP_TO_EDGE:
  2479. begin
  2480. if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
  2481. fWrapT := GL_CLAMP_TO_EDGE
  2482. else
  2483. fWrapT := GL_CLAMP;
  2484. end;
  2485. GL_CLAMP_TO_BORDER:
  2486. begin
  2487. if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
  2488. fWrapT := GL_CLAMP_TO_BORDER
  2489. else
  2490. fWrapT := GL_CLAMP;
  2491. end;
  2492. GL_MIRRORED_REPEAT:
  2493. begin
  2494. if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
  2495. fWrapT := GL_MIRRORED_REPEAT
  2496. else
  2497. raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (T).');
  2498. end;
  2499. else
  2500. raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (T).');
  2501. end;
  2502. case R of
  2503. GL_CLAMP:
  2504. fWrapR := GL_CLAMP;
  2505. GL_REPEAT:
  2506. fWrapR := GL_REPEAT;
  2507. GL_CLAMP_TO_EDGE:
  2508. begin
  2509. if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
  2510. fWrapR := GL_CLAMP_TO_EDGE
  2511. else
  2512. fWrapR := GL_CLAMP;
  2513. end;
  2514. GL_CLAMP_TO_BORDER:
  2515. begin
  2516. if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
  2517. fWrapR := GL_CLAMP_TO_BORDER
  2518. else
  2519. fWrapR := GL_CLAMP;
  2520. end;
  2521. GL_MIRRORED_REPEAT:
  2522. begin
  2523. if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
  2524. fWrapR := GL_MIRRORED_REPEAT
  2525. else
  2526. raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (R).');
  2527. end;
  2528. else
  2529. raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (R).');
  2530. end;
  2531. if ID > 0 then begin
  2532. Bind (False);
  2533. glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
  2534. glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
  2535. glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
  2536. end;
  2537. end;
  2538. procedure TglBitmap.SetDataPointer(NewData: PByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
  2539. begin
  2540. // Data
  2541. if Data <> NewData then begin
  2542. if (Assigned(Data))
  2543. then FreeMem(Data);
  2544. fData := NewData;
  2545. end;
  2546. if Data = nil then begin
  2547. fInternalFormat := ifEmpty;
  2548. fPixelSize := 0;
  2549. fRowSize := 0;
  2550. end else begin
  2551. if Width <> -1 then begin
  2552. fDimension.Fields := fDimension.Fields + [ffX];
  2553. fDimension.X := Width;
  2554. end;
  2555. if Height <> -1 then begin
  2556. fDimension.Fields := fDimension.Fields + [ffY];
  2557. fDimension.Y := Height;
  2558. end;
  2559. fInternalFormat := Format;
  2560. fPixelSize := Trunc(FormatGetSize(InternalFormat));
  2561. fRowSize := Trunc(FormatGetSize(InternalFormat) * Self.Width);
  2562. end;
  2563. end;
  2564. {$ifdef GLB_SUPPORT_PNG_READ}
  2565. {$ifdef GLB_LIB_PNG}
  2566. procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
  2567. begin
  2568. TStream(png_get_io_ptr(png)).Read(buffer^, size);
  2569. end;
  2570. {$endif}
  2571. function TglBitmap.LoadPNG(Stream: TStream): Boolean;
  2572. {$ifdef GLB_SDL_IMAGE}
  2573. var
  2574. Surface: PSDL_Surface;
  2575. RWops: PSDL_RWops;
  2576. begin
  2577. Result := False;
  2578. RWops := glBitmapCreateRWops(Stream);
  2579. try
  2580. if IMG_isPNG(RWops) > 0 then begin
  2581. Surface := IMG_LoadPNG_RW(RWops);
  2582. try
  2583. AssignFromSurface(Surface);
  2584. Result := True;
  2585. finally
  2586. SDL_FreeSurface(Surface);
  2587. end;
  2588. end;
  2589. finally
  2590. SDL_FreeRW(RWops);
  2591. end;
  2592. end;
  2593. {$endif}
  2594. {$ifdef GLB_LIB_PNG}
  2595. var
  2596. StreamPos: Int64;
  2597. signature: array [0..7] of byte;
  2598. png: png_structp;
  2599. png_info: png_infop;
  2600. TempHeight, TempWidth: Integer;
  2601. Format: TglBitmapInternalFormat;
  2602. png_data: pByte;
  2603. png_rows: array of pByte;
  2604. Row, LineSize: Integer;
  2605. begin
  2606. Result := False;
  2607. if not init_libPNG then
  2608. raise Exception.Create('LoadPNG - unable to initialize libPNG.');
  2609. try
  2610. // signature
  2611. StreamPos := Stream.Position;
  2612. Stream.Read(signature, 8);
  2613. Stream.Position := StreamPos;
  2614. if png_check_sig(@signature, 8) <> 0 then begin
  2615. // png read struct
  2616. png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
  2617. if png = nil then
  2618. raise EglBitmapException.Create('LoadPng - couldn''t create read struct.');
  2619. // png info
  2620. png_info := png_create_info_struct(png);
  2621. if png_info = nil then begin
  2622. png_destroy_read_struct(@png, nil, nil);
  2623. raise EglBitmapException.Create('LoadPng - couldn''t create info struct.');
  2624. end;
  2625. // set read callback
  2626. png_set_read_fn(png, stream, glBitmap_libPNG_read_func);
  2627. // read informations
  2628. png_read_info(png, png_info);
  2629. // size
  2630. TempHeight := png_get_image_height(png, png_info);
  2631. TempWidth := png_get_image_width(png, png_info);
  2632. // format
  2633. case png_get_color_type(png, png_info) of
  2634. PNG_COLOR_TYPE_GRAY:
  2635. Format := ifLuminance;
  2636. PNG_COLOR_TYPE_GRAY_ALPHA:
  2637. Format := ifLuminanceAlpha;
  2638. PNG_COLOR_TYPE_RGB:
  2639. Format := ifRGB8;
  2640. PNG_COLOR_TYPE_RGB_ALPHA:
  2641. Format := ifRGBA8;
  2642. else
  2643. raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
  2644. end;
  2645. // cut upper 8 bit from 16 bit formats
  2646. if png_get_bit_depth(png, png_info) > 8 then
  2647. png_set_strip_16(png);
  2648. // expand bitdepth smaller than 8
  2649. if png_get_bit_depth(png, png_info) < 8 then
  2650. png_set_expand(png);
  2651. // allocating mem for scanlines
  2652. LineSize := png_get_rowbytes(png, png_info);
  2653. GetMem(png_data, TempHeight * LineSize);
  2654. try
  2655. SetLength(png_rows, TempHeight);
  2656. for Row := Low(png_rows) to High(png_rows) do begin
  2657. png_rows[Row] := png_data;
  2658. Inc(png_rows[Row], Row * LineSize);
  2659. end;
  2660. // read complete image into scanlines
  2661. png_read_image(png, @png_rows[0]);
  2662. // read end
  2663. png_read_end(png, png_info);
  2664. // destroy read struct
  2665. png_destroy_read_struct(@png, @png_info, nil);
  2666. SetLength(png_rows, 0);
  2667. // set new data
  2668. SetDataPointer(png_data, Format, TempWidth, TempHeight);
  2669. Result := True;
  2670. except
  2671. FreeMem(png_data);
  2672. raise;
  2673. end;
  2674. end;
  2675. finally
  2676. quit_libPNG;
  2677. end;
  2678. end;
  2679. {$endif}
  2680. {$ifdef GLB_PNGIMAGE}
  2681. var
  2682. StreamPos: Int64;
  2683. Png: TPNGObject;
  2684. Header: Array[0..7] of Byte;
  2685. Row, Col, PixSize, LineSize: Integer;
  2686. NewImage, pSource, pDest, pAlpha: pByte;
  2687. Format: TglBitmapInternalFormat;
  2688. const
  2689. PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10);
  2690. begin
  2691. Result := False;
  2692. StreamPos := Stream.Position;
  2693. Stream.Read(Header[0], SizeOf(Header));
  2694. Stream.Position := StreamPos;
  2695. {Test if the header matches}
  2696. if Header = PngHeader then begin
  2697. Png := TPNGObject.Create;
  2698. try
  2699. Png.LoadFromStream(Stream);
  2700. case Png.Header.ColorType of
  2701. COLOR_GRAYSCALE:
  2702. Format := ifLuminance;
  2703. COLOR_GRAYSCALEALPHA:
  2704. Format := ifLuminanceAlpha;
  2705. COLOR_RGB:
  2706. Format := ifBGR8;
  2707. COLOR_RGBALPHA:
  2708. Format := ifBGRA8;
  2709. else
  2710. raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
  2711. end;
  2712. PixSize := Trunc(FormatGetSize(Format));
  2713. LineSize := Integer(Png.Header.Width) * PixSize;
  2714. GetMem(NewImage, LineSize * Integer(Png.Header.Height));
  2715. try
  2716. pDest := NewImage;
  2717. case Png.Header.ColorType of
  2718. COLOR_RGB, COLOR_GRAYSCALE:
  2719. begin
  2720. for Row := 0 to Png.Height -1 do begin
  2721. Move (Png.Scanline[Row]^, pDest^, LineSize);
  2722. Inc(pDest, LineSize);
  2723. end;
  2724. end;
  2725. COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA:
  2726. begin
  2727. PixSize := PixSize -1;
  2728. for Row := 0 to Png.Height -1 do begin
  2729. pSource := Png.Scanline[Row];
  2730. pAlpha := pByte(Png.AlphaScanline[Row]);
  2731. for Col := 0 to Png.Width -1 do begin
  2732. Move (pSource^, pDest^, PixSize);
  2733. Inc(pSource, PixSize);
  2734. Inc(pDest, PixSize);
  2735. pDest^ := pAlpha^;
  2736. inc(pAlpha);
  2737. Inc(pDest);
  2738. end;
  2739. end;
  2740. end;
  2741. else
  2742. raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
  2743. end;
  2744. SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height);
  2745. Result := True;
  2746. except
  2747. FreeMem(NewImage);
  2748. raise;
  2749. end;
  2750. finally
  2751. Png.Free;
  2752. end;
  2753. end;
  2754. end;
  2755. {$endif}
  2756. {$endif}
  2757. {$ifdef GLB_LIB_JPEG}
  2758. type
  2759. glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
  2760. glBitmap_libJPEG_source_mgr = record
  2761. pub: jpeg_source_mgr;
  2762. SrcStream: TStream;
  2763. SrcBuffer: array [1..4096] of byte;
  2764. end;
  2765. glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
  2766. glBitmap_libJPEG_dest_mgr = record
  2767. pub: jpeg_destination_mgr;
  2768. DestStream: TStream;
  2769. DestBuffer: array [1..4096] of byte;
  2770. end;
  2771. procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
  2772. //var
  2773. // Msg: String;
  2774. begin
  2775. // SetLength(Msg, 256);
  2776. // cinfo^.err^.format_message(cinfo, pChar(Msg));
  2777. // Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
  2778. // cinfo^.global_state := 0;
  2779. // jpeg_abort(cinfo);
  2780. end;
  2781. procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
  2782. //var
  2783. // Msg: String;
  2784. begin
  2785. // SetLength(Msg, 256);
  2786. // cinfo^.err^.format_message(cinfo, pChar(Msg));
  2787. // Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
  2788. // cinfo^.global_state := 0;
  2789. end;
  2790. procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
  2791. begin
  2792. end;
  2793. function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
  2794. var
  2795. src: glBitmap_libJPEG_source_mgr_ptr;
  2796. bytes: integer;
  2797. begin
  2798. src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
  2799. bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096);
  2800. if (bytes <= 0) then begin
  2801. src^.SrcBuffer[1] := $FF;
  2802. src^.SrcBuffer[2] := JPEG_EOI;
  2803. bytes := 2;
  2804. end;
  2805. src^.pub.next_input_byte := @(src^.SrcBuffer[1]);
  2806. src^.pub.bytes_in_buffer := bytes;
  2807. result := true;
  2808. end;
  2809. procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
  2810. var
  2811. src: glBitmap_libJPEG_source_mgr_ptr;
  2812. begin
  2813. src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src);
  2814. if num_bytes > 0 then begin
  2815. // wanted byte isn't in buffer so set stream position and read buffer
  2816. if num_bytes > src^.pub.bytes_in_buffer then begin
  2817. src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer;
  2818. src^.pub.fill_input_buffer(cinfo);
  2819. end else begin
  2820. // wanted byte is in buffer so only skip
  2821. inc(src^.pub.next_input_byte, num_bytes);
  2822. dec(src^.pub.bytes_in_buffer, num_bytes);
  2823. end;
  2824. end;
  2825. end;
  2826. procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
  2827. begin
  2828. end;
  2829. procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
  2830. begin
  2831. end;
  2832. function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
  2833. var
  2834. dest: glBitmap_libJPEG_dest_mgr_ptr;
  2835. begin
  2836. dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
  2837. if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin
  2838. // write complete buffer
  2839. dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer));
  2840. // reset buffer
  2841. dest^.pub.next_output_byte := @dest^.DestBuffer[1];
  2842. dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
  2843. end;
  2844. Result := True;
  2845. end;
  2846. procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
  2847. var
  2848. Idx: Integer;
  2849. dest: glBitmap_libJPEG_dest_mgr_ptr;
  2850. begin
  2851. dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest);
  2852. for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin
  2853. // check for endblock
  2854. if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin
  2855. // write endblock
  2856. dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
  2857. // leave
  2858. Break;
  2859. end else
  2860. dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
  2861. end;
  2862. end;
  2863. {$endif}
  2864. {$ifdef GLB_SUPPORT_JPEG_READ}
  2865. function TglBitmap.LoadJPEG(Stream: TStream): Boolean;
  2866. {$ifdef GLB_SDL_IMAGE}
  2867. var
  2868. Surface: PSDL_Surface;
  2869. RWops: PSDL_RWops;
  2870. begin
  2871. Result := False;
  2872. RWops := glBitmapCreateRWops(Stream);
  2873. try
  2874. if IMG_isJPG(RWops) > 0 then begin
  2875. Surface := IMG_LoadJPG_RW(RWops);
  2876. try
  2877. AssignFromSurface(Surface);
  2878. Result := True;
  2879. finally
  2880. SDL_FreeSurface(Surface);
  2881. end;
  2882. end;
  2883. finally
  2884. SDL_FreeRW(RWops);
  2885. end;
  2886. end;
  2887. {$endif}
  2888. {$ifdef GLB_LIB_JPEG}
  2889. var
  2890. StreamPos: Int64;
  2891. Temp: array[0..1]of Byte;
  2892. jpeg: jpeg_decompress_struct;
  2893. jpeg_err: jpeg_error_mgr;
  2894. IntFormat: TglBitmapInternalFormat;
  2895. pImage: pByte;
  2896. TempHeight, TempWidth: Integer;
  2897. pTemp: pByte;
  2898. Row: Integer;
  2899. begin
  2900. Result := False;
  2901. if not init_libJPEG then
  2902. raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
  2903. try
  2904. // reading first two bytes to test file and set cursor back to begin
  2905. StreamPos := Stream.Position;
  2906. Stream.Read(Temp[0], 2);
  2907. Stream.Position := StreamPos;
  2908. // if Bitmap then read file.
  2909. if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
  2910. FillChar(jpeg, SizeOf(jpeg_decompress_struct), $00);
  2911. FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
  2912. // error managment
  2913. jpeg.err := jpeg_std_error(@jpeg_err);
  2914. jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
  2915. jpeg_err.output_message := glBitmap_libJPEG_output_message;
  2916. // decompression struct
  2917. jpeg_create_decompress(@jpeg);
  2918. // allocation space for streaming methods
  2919. jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr));
  2920. // seeting up custom functions
  2921. with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin
  2922. pub.init_source := glBitmap_libJPEG_init_source;
  2923. pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer;
  2924. pub.skip_input_data := glBitmap_libJPEG_skip_input_data;
  2925. pub.resync_to_restart := jpeg_resync_to_restart; // use default method
  2926. pub.term_source := glBitmap_libJPEG_term_source;
  2927. pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read
  2928. pub.next_input_byte := nil; // until buffer loaded
  2929. SrcStream := Stream;
  2930. end;
  2931. // set global decoding state
  2932. jpeg.global_state := DSTATE_START;
  2933. // read header of jpeg
  2934. jpeg_read_header(@jpeg, False);
  2935. // setting output parameter
  2936. case jpeg.jpeg_color_space of
  2937. JCS_GRAYSCALE:
  2938. begin
  2939. jpeg.out_color_space := JCS_GRAYSCALE;
  2940. IntFormat := ifLuminance;
  2941. end;
  2942. else
  2943. jpeg.out_color_space := JCS_RGB;
  2944. IntFormat := ifRGB8;
  2945. end;
  2946. // reading image
  2947. jpeg_start_decompress(@jpeg);
  2948. TempHeight := jpeg.output_height;
  2949. TempWidth := jpeg.output_width;
  2950. // creating new image
  2951. GetMem(pImage, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
  2952. try
  2953. pTemp := pImage;
  2954. for Row := 0 to TempHeight -1 do begin
  2955. jpeg_read_scanlines(@jpeg, @pTemp, 1);
  2956. Inc(pTemp, Trunc(FormatGetSize(IntFormat) * TempWidth));
  2957. end;
  2958. // finish decompression
  2959. jpeg_finish_decompress(@jpeg);
  2960. // destroy decompression
  2961. jpeg_destroy_decompress(@jpeg);
  2962. SetDataPointer(pImage, IntFormat, TempWidth, TempHeight);
  2963. Result := True;
  2964. except
  2965. FreeMem(pImage);
  2966. raise;
  2967. end;
  2968. end;
  2969. finally
  2970. quit_libJPEG;
  2971. end;
  2972. end;
  2973. {$endif}
  2974. {$ifdef GLB_DELPHI_JPEG}
  2975. var
  2976. bmp: TBitmap;
  2977. jpg: TJPEGImage;
  2978. StreamPos: Int64;
  2979. Temp: array[0..1]of Byte;
  2980. begin
  2981. Result := False;
  2982. // reading first two bytes to test file and set cursor back to begin
  2983. StreamPos := Stream.Position;
  2984. Stream.Read(Temp[0], 2);
  2985. Stream.Position := StreamPos;
  2986. // if Bitmap then read file.
  2987. if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
  2988. bmp := TBitmap.Create;
  2989. try
  2990. jpg := TJPEGImage.Create;
  2991. try
  2992. jpg.LoadFromStream(Stream);
  2993. bmp.Assign(jpg);
  2994. Result := AssignFromBitmap(bmp);
  2995. finally
  2996. jpg.Free;
  2997. end;
  2998. finally
  2999. bmp.Free;
  3000. end;
  3001. end;
  3002. end;
  3003. {$endif}
  3004. {$endif}
  3005. const
  3006. BMP_MAGIC = $4D42;
  3007. BMP_COMP_RGB = 0;
  3008. BMP_COMP_RLE8 = 1;
  3009. BMP_COMP_RLE4 = 2;
  3010. BMP_COMP_BITFIELDS = 3;
  3011. type
  3012. TBMPHeader = packed record
  3013. bfType: Word;
  3014. bfSize: Cardinal;
  3015. bfReserved1: Word;
  3016. bfReserved2: Word;
  3017. bfOffBits: Cardinal;
  3018. end;
  3019. TBMPInfo = packed record
  3020. biSize: Cardinal;
  3021. biWidth: Longint;
  3022. biHeight: Longint;
  3023. biPlanes: Word;
  3024. biBitCount: Word;
  3025. biCompression: Cardinal;
  3026. biSizeImage: Cardinal;
  3027. biXPelsPerMeter: Longint;
  3028. biYPelsPerMeter: Longint;
  3029. biClrUsed: Cardinal;
  3030. biClrImportant: Cardinal;
  3031. end;
  3032. TBMPInfoOS = packed record
  3033. biSize: Cardinal;
  3034. biWidth: Longint;
  3035. biHeight: Longint;
  3036. biPlanes: Word;
  3037. biBitCount: Word;
  3038. end;
  3039. // TBMPPalette = record
  3040. // case Boolean of
  3041. // True : (Colors: array[Byte] of TRGBQUAD);
  3042. // False: (redMask, greenMask, blueMask: Cardinal);
  3043. // end;
  3044. function TglBitmap.LoadBMP(Stream: TStream): Boolean;
  3045. var
  3046. StreamPos: Int64;
  3047. Header: TBMPHeader;
  3048. Info: TBMPInfo;
  3049. NewImage, pData: pByte;
  3050. Format: TglBitmapInternalFormat;
  3051. LineSize, Padding, LineIdx: Integer;
  3052. RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
  3053. PaddingBuff: Cardinal;
  3054. function GetLineWidth : Integer;
  3055. begin
  3056. Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
  3057. end;
  3058. begin
  3059. Result := False;
  3060. RedMask := 0;
  3061. GreenMask := 0;
  3062. BlueMask := 0;
  3063. Format := ifEmpty;
  3064. // Header
  3065. StreamPos := Stream.Position;
  3066. Stream.Read(Header, SizeOf(Header));
  3067. if Header.bfType = BMP_MAGIC then begin
  3068. Stream.Read(Info, SizeOf(Info));
  3069. // Check for Compression
  3070. if Info.biCompression <> BMP_COMP_RGB then begin
  3071. if Info.biCompression = BMP_COMP_BITFIELDS then begin
  3072. // Read Bitmasks for 16 or 32 Bit (24 Bit dosn't support Bitmasks!)
  3073. if (Info.biBitCount = 16) or (Info.biBitCount = 32) then begin
  3074. Stream.Read(RedMask, SizeOf(Cardinal));
  3075. Stream.Read(GreenMask, SizeOf(Cardinal));
  3076. Stream.Read(BlueMask, SizeOf(Cardinal));
  3077. Stream.Read(AlphaMask, SizeOf(Cardinal));
  3078. end;
  3079. end else begin
  3080. // RLE compression is unsupported
  3081. Stream.Position := StreamPos;
  3082. Exit;
  3083. end;
  3084. end;
  3085. // Skip palette
  3086. if Info.biBitCount < 16 then
  3087. Stream.Position := Stream.Position + Info.biClrUsed * 4;
  3088. // Jump to the data
  3089. Stream.Position := StreamPos + Header.bfOffBits;
  3090. // Select Format
  3091. case Info.biBitCount of
  3092. 8 : Format := ifLuminance;
  3093. 16:
  3094. begin
  3095. if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin
  3096. Format := ifRGB5A1;
  3097. end else begin
  3098. if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifLuminanceAlpha) then
  3099. Format := ifLuminanceAlpha;
  3100. if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGBA4) then
  3101. Format := ifRGBA4;
  3102. if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifRGB5A1) then
  3103. Format := ifRGB5A1;
  3104. if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifR5G6B5) then
  3105. Format := ifR5G6B5;
  3106. end;
  3107. end;
  3108. 24: Format := ifBGR8;
  3109. 32:
  3110. begin
  3111. if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin
  3112. Format := ifBGRA8;
  3113. end else begin
  3114. if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGBA8) then
  3115. Format := ifRGBA8;
  3116. if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifBGRA8) then
  3117. Format := ifBGRA8;
  3118. if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGB10A2) then
  3119. Format := ifRGB10A2;
  3120. end;
  3121. end;
  3122. end;
  3123. if Format <> ifEmpty then begin
  3124. LineSize := Trunc(Info.biWidth * FormatGetSize(Format));
  3125. Padding := GetLineWidth - LineSize;
  3126. // copying data
  3127. GetMem(NewImage, Info.biHeight * LineSize);
  3128. try
  3129. FillChar(NewImage^, Info.biHeight * LineSize, $FF);
  3130. // Set pData to last Line
  3131. pData := NewImage;
  3132. Inc(pData, LineSize * (Info.biHeight -1));
  3133. // Copy Image Data
  3134. for LineIdx := 0 to Info.biHeight - 1 do begin
  3135. Stream.Read(pData^, LineSize);
  3136. Dec(pData, LineSize);
  3137. Stream.Read(PaddingBuff, Padding);
  3138. end;
  3139. // Set new Image
  3140. SetDataPointer(NewImage, Format, Info.biWidth, Info.biHeight);
  3141. Result := True;
  3142. except
  3143. FreeMem(NewImage);
  3144. raise;
  3145. end;
  3146. end;
  3147. end
  3148. else Stream.Position := StreamPos;
  3149. end;
  3150. const
  3151. DDS_MAGIC = $20534444;
  3152. // DDS_header.dwFlags
  3153. DDSD_CAPS = $00000001;
  3154. DDSD_HEIGHT = $00000002;
  3155. DDSD_WIDTH = $00000004;
  3156. DDSD_PITCH = $00000008;
  3157. DDSD_PIXELFORMAT = $00001000;
  3158. DDSD_MIPMAPCOUNT = $00020000;
  3159. DDSD_LINEARSIZE = $00080000;
  3160. DDSD_DEPTH = $00800000;
  3161. // DDS_header.sPixelFormat.dwFlags
  3162. DDPF_ALPHAPIXELS = $00000001;
  3163. DDPF_FOURCC = $00000004;
  3164. DDPF_INDEXED = $00000020;
  3165. DDPF_RGB = $00000040;
  3166. // DDS_header.sCaps.dwCaps1
  3167. DDSCAPS_COMPLEX = $00000008;
  3168. DDSCAPS_TEXTURE = $00001000;
  3169. DDSCAPS_MIPMAP = $00400000;
  3170. // DDS_header.sCaps.dwCaps2
  3171. DDSCAPS2_CUBEMAP = $00000200;
  3172. DDSCAPS2_CUBEMAP_POSITIVEX = $00000400;
  3173. DDSCAPS2_CUBEMAP_NEGATIVEX = $00000800;
  3174. DDSCAPS2_CUBEMAP_POSITIVEY = $00001000;
  3175. DDSCAPS2_CUBEMAP_NEGATIVEY = $00002000;
  3176. DDSCAPS2_CUBEMAP_POSITIVEZ = $00004000;
  3177. DDSCAPS2_CUBEMAP_NEGATIVEZ = $00008000;
  3178. DDSCAPS2_VOLUME = $00200000;
  3179. D3DFMT_DXT1 = $31545844;
  3180. D3DFMT_DXT3 = $33545844;
  3181. D3DFMT_DXT5 = $35545844;
  3182. type
  3183. TDDSPixelFormat = packed record
  3184. dwSize: Cardinal;
  3185. dwFlags: Cardinal;
  3186. dwFourCC: Cardinal;
  3187. dwRGBBitCount: Cardinal;
  3188. dwRBitMask: Cardinal;
  3189. dwGBitMask: Cardinal;
  3190. dwBBitMask: Cardinal;
  3191. dwAlphaBitMask: Cardinal;
  3192. end;
  3193. TDDSCaps = packed record
  3194. dwCaps1: Cardinal;
  3195. dwCaps2: Cardinal;
  3196. dwDDSX: Cardinal;
  3197. dwReserved: Cardinal;
  3198. end;
  3199. TDDSHeader = packed record
  3200. dwMagic: Cardinal;
  3201. dwSize: Cardinal;
  3202. dwFlags: Cardinal;
  3203. dwHeight: Cardinal;
  3204. dwWidth: Cardinal;
  3205. dwPitchOrLinearSize: Cardinal;
  3206. dwDepth: Cardinal;
  3207. dwMipMapCount: Cardinal;
  3208. dwReserved: array[0..10] of Cardinal;
  3209. PixelFormat: TDDSPixelFormat;
  3210. Caps: TDDSCaps;
  3211. dwReserved2: Cardinal;
  3212. end;
  3213. function TglBitmap.LoadDDS(Stream: TStream): Boolean;
  3214. var
  3215. Header: TDDSHeader;
  3216. StreamPos: Int64;
  3217. Y, LineSize: Cardinal;
  3218. // MipMapCount, X, Y, XSize, YSize: Cardinal;
  3219. RowSize: Cardinal;
  3220. NewImage, pData: pByte;
  3221. Format: TglBitmapInternalFormat;
  3222. function RaiseEx : Exception;
  3223. begin
  3224. Result := EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
  3225. end;
  3226. function GetInternalFormat: TglBitmapInternalFormat;
  3227. begin
  3228. with Header.PixelFormat do begin
  3229. // Compresses
  3230. if (dwFlags and DDPF_FOURCC) > 0 then begin
  3231. case Header.PixelFormat.dwFourCC of
  3232. D3DFMT_DXT1: Result := ifDXT1;
  3233. D3DFMT_DXT3: Result := ifDXT3;
  3234. D3DFMT_DXT5: Result := ifDXT5;
  3235. else
  3236. raise RaiseEx;
  3237. end;
  3238. end else
  3239. // RGB
  3240. if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
  3241. case dwRGBBitCount of
  3242. 8:
  3243. begin
  3244. if dwFlags and DDPF_ALPHAPIXELS > 0 then
  3245. Result := ifAlpha
  3246. else
  3247. Result := ifLuminance;
  3248. end;
  3249. 16:
  3250. begin
  3251. if dwFlags and DDPF_ALPHAPIXELS > 0 then begin
  3252. // Alpha
  3253. case GetBitSize(dwRBitMask) of
  3254. 5: Result := ifRGB5A1;
  3255. 4: Result := ifRGBA4;
  3256. else
  3257. Result := ifLuminanceAlpha;
  3258. end;
  3259. end else begin
  3260. // no Alpha
  3261. Result := ifR5G6B5;
  3262. end;
  3263. end;
  3264. 24:
  3265. begin
  3266. if dwRBitMask > dwBBitMask then
  3267. Result := ifBGR8
  3268. else
  3269. Result := ifRGB8;
  3270. end;
  3271. 32:
  3272. begin
  3273. if GetBitSize(dwRBitMask) = 10 then
  3274. Result := ifRGB10A2
  3275. else
  3276. if dwRBitMask > dwBBitMask then
  3277. Result := ifBGRA8
  3278. else
  3279. Result := ifRGBA8;
  3280. end;
  3281. else
  3282. raise RaiseEx;
  3283. end;
  3284. end else
  3285. raise RaiseEx;
  3286. end;
  3287. end;
  3288. begin
  3289. Result := False;
  3290. // Header
  3291. StreamPos := Stream.Position;
  3292. Stream.Read(Header, sizeof(Header));
  3293. if ((Header.dwMagic <> DDS_MAGIC) or (Header.dwSize <> 124) or
  3294. ((Header.dwFlags and DDSD_PIXELFORMAT) = 0) or ((Header.dwFlags and DDSD_CAPS) = 0)) then begin
  3295. Stream.Position := StreamPos;
  3296. Exit;
  3297. end;
  3298. // Pixelformat
  3299. // if Header.dwFlags and DDSD_MIPMAPCOUNT <> 0
  3300. // then MipMapCount := Header.dwMipMapCount
  3301. // else MipMapCount := 1;
  3302. Format := GetInternalFormat;
  3303. LineSize := Trunc(Header.dwWidth * FormatGetSize(Format));
  3304. GetMem(NewImage, Header.dwHeight * LineSize);
  3305. try
  3306. pData := NewImage;
  3307. // Compressed
  3308. if (Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0 then begin
  3309. RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
  3310. for Y := 0 to Header.dwHeight -1 do begin
  3311. Stream.Read(pData^, RowSize);
  3312. Inc(pData, LineSize);
  3313. end;
  3314. end else
  3315. // RGB(A)
  3316. if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
  3317. RowSize := Header.dwPitchOrLinearSize;
  3318. for Y := 0 to Header.dwHeight -1 do begin
  3319. Stream.Read(pData^, RowSize);
  3320. Inc(pData, LineSize);
  3321. end;
  3322. end
  3323. else raise RaiseEx;
  3324. SetDataPointer(NewImage, Format, Header.dwWidth, Header.dwHeight);
  3325. Result := True;
  3326. except
  3327. FreeMem(NewImage);
  3328. raise;
  3329. end;
  3330. end;
  3331. type
  3332. TTGAHeader = packed record
  3333. ImageID: Byte;
  3334. ColorMapType: Byte;
  3335. ImageType: Byte;
  3336. ColorMapSpec: Array[0..4] of Byte;
  3337. OrigX: Word;
  3338. OrigY: Word;
  3339. Width: Word;
  3340. Height: Word;
  3341. Bpp: Byte;
  3342. ImageDes: Byte;
  3343. end;
  3344. const
  3345. TGA_UNCOMPRESSED_RGB = 2;
  3346. TGA_UNCOMPRESSED_GRAY = 3;
  3347. TGA_COMPRESSED_RGB = 10;
  3348. TGA_COMPRESSED_GRAY = 11;
  3349. function TglBitmap.LoadTGA(Stream: TStream): Boolean;
  3350. var
  3351. Header: TTGAHeader;
  3352. NewImage, pData: PByte;
  3353. StreamPos: Int64;
  3354. PixelSize, LineSize, YStart, YEnd, YInc: Integer;
  3355. Format: TglBitmapInternalFormat;
  3356. const
  3357. CACHE_SIZE = $4000;
  3358. procedure ReadUncompressed;
  3359. var
  3360. RowSize: Integer;
  3361. begin
  3362. RowSize := Header.Width * PixelSize;
  3363. // copy line by line
  3364. while YStart <> YEnd + YInc do begin
  3365. pData := NewImage;
  3366. Inc(pData, YStart * LineSize);
  3367. Stream.Read(pData^, RowSize);
  3368. Inc(YStart, YInc);
  3369. end;
  3370. end;
  3371. procedure ReadCompressed;
  3372. var
  3373. HeaderWidth, HeaderHeight: Integer;
  3374. LinePixelsRead, ImgPixelsRead, ImgPixelsToRead: Integer;
  3375. Cache: PByte;
  3376. CacheSize, CachePos: Integer;
  3377. Temp: Byte;
  3378. TempBuf: Array [0..15] of Byte;
  3379. PixelRepeat: Boolean;
  3380. PixelToRead, TempPixels: Integer;
  3381. procedure CheckLine;
  3382. begin
  3383. if LinePixelsRead >= HeaderWidth then begin
  3384. LinePixelsRead := 0;
  3385. pData := NewImage;
  3386. Inc(YStart, YInc);
  3387. Inc(pData, YStart * LineSize);
  3388. end;
  3389. end;
  3390. procedure CachedRead(var Buffer; Count: Integer);
  3391. var
  3392. BytesRead: Integer;
  3393. begin
  3394. if (CachePos + Count) > CacheSize then begin
  3395. BytesRead := 0;
  3396. // Read Data
  3397. if CacheSize - CachePos > 0 then begin
  3398. BytesRead := CacheSize - CachePos;
  3399. Move(pByteArray(Cache)^[CachePos], Buffer, BytesRead);
  3400. Inc(CachePos, BytesRead);
  3401. end;
  3402. // Reload Data
  3403. CacheSize := Min(CACHE_SIZE, Stream.Size - Stream.Position);
  3404. Stream.Read(Cache^, CacheSize);
  3405. CachePos := 0;
  3406. // Read else
  3407. if Count - BytesRead > 0 then begin
  3408. Move(pByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
  3409. Inc(CachePos, Count - BytesRead);
  3410. end;
  3411. end else begin
  3412. Move(pByteArray(Cache)^[CachePos], Buffer, Count);
  3413. Inc(CachePos, Count);
  3414. end;
  3415. end;
  3416. begin
  3417. CacheSize := 0;
  3418. CachePos := 0;
  3419. HeaderWidth := Header.Width;
  3420. HeaderHeight := Header.Height;
  3421. GetMem(Cache, CACHE_SIZE); // 16K Buffer
  3422. try
  3423. ImgPixelsToRead := HeaderWidth * HeaderHeight;
  3424. ImgPixelsRead := 0;
  3425. LinePixelsRead := 0;
  3426. pData := NewImage;
  3427. Inc(pData, YStart * LineSize);
  3428. // Read until all Pixels
  3429. repeat
  3430. CachedRead(Temp, 1);
  3431. PixelRepeat := Temp and $80 > 0;
  3432. PixelToRead := (Temp and $7F) + 1;
  3433. Inc(ImgPixelsRead, PixelToRead);
  3434. if PixelRepeat then begin
  3435. // repeat one pixel x times
  3436. CachedRead(TempBuf[0], PixelSize);
  3437. // repeat Pixel
  3438. while PixelToRead > 0 do begin
  3439. CheckLine;
  3440. TempPixels := HeaderWidth - LinePixelsRead;
  3441. if PixelToRead < TempPixels then
  3442. TempPixels := PixelToRead;
  3443. Inc(LinePixelsRead, TempPixels);
  3444. Dec(PixelToRead, TempPixels);
  3445. while TempPixels > 0 do begin
  3446. case PixelSize of
  3447. 1:
  3448. begin
  3449. pData^ := TempBuf[0];
  3450. Inc(pData);
  3451. end;
  3452. 2:
  3453. begin
  3454. pWord(pData)^ := pWord(@TempBuf[0])^;
  3455. Inc(pData, 2);
  3456. end;
  3457. 3:
  3458. begin
  3459. pWord(pData)^ := pWord(@TempBuf[0])^;
  3460. Inc(pData, 2);
  3461. pData^ := TempBuf[2];
  3462. Inc(pData);
  3463. end;
  3464. 4:
  3465. begin
  3466. pDWord(pData)^ := pDWord(@TempBuf[0])^;
  3467. Inc(pData, 4);
  3468. end;
  3469. end;
  3470. Dec(TempPixels);
  3471. end;
  3472. end;
  3473. end else begin
  3474. // copy x pixels
  3475. while PixelToRead > 0 do begin
  3476. CheckLine;
  3477. TempPixels := HeaderWidth - LinePixelsRead;
  3478. if PixelToRead < TempPixels then
  3479. TempPixels := PixelToRead;
  3480. CachedRead(pData^, PixelSize * TempPixels);
  3481. Inc(pData, PixelSize * TempPixels);
  3482. Inc(LinePixelsRead, TempPixels);
  3483. Dec(PixelToRead, TempPixels);
  3484. end;
  3485. end;
  3486. until ImgPixelsRead >= ImgPixelsToRead;
  3487. finally
  3488. FreeMem(Cache)
  3489. end;
  3490. end;
  3491. begin
  3492. Result := False;
  3493. // reading header to test file and set cursor back to begin
  3494. StreamPos := Stream.Position;
  3495. Stream.Read(Header, SizeOf(Header));
  3496. // no colormapped files
  3497. if (Header.ColorMapType = 0) then begin
  3498. if Header.ImageType in [TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY] then begin
  3499. case Header.Bpp of
  3500. 8: Format := ifAlpha;
  3501. 16: Format := ifLuminanceAlpha;
  3502. 24: Format := ifBGR8;
  3503. 32: Format := ifBGRA8;
  3504. else
  3505. raise EglBitmapException.Create('LoadTga - unsupported BitsPerPixel found.');
  3506. end;
  3507. // skip image ID
  3508. if Header.ImageID <> 0 then
  3509. Stream.Position := Stream.Position + Header.ImageID;
  3510. PixelSize := Trunc(FormatGetSize(Format));
  3511. LineSize := Trunc(Header.Width * PixelSize);
  3512. GetMem(NewImage, LineSize * Header.Height);
  3513. try
  3514. // Row direction
  3515. if (Header.ImageDes and $20 > 0) then begin
  3516. YStart := 0;
  3517. YEnd := Header.Height -1;
  3518. YInc := 1;
  3519. end else begin
  3520. YStart := Header.Height -1;
  3521. YEnd := 0;
  3522. YInc := -1;
  3523. end;
  3524. // Read Image
  3525. case Header.ImageType of
  3526. TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
  3527. ReadUncompressed;
  3528. TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
  3529. ReadCompressed;
  3530. end;
  3531. SetDataPointer(NewImage, Format, Header.Width, Header.Height);
  3532. Result := True;
  3533. except
  3534. FreeMem(NewImage);
  3535. raise;
  3536. end;
  3537. end
  3538. else Stream.Position := StreamPos;
  3539. end
  3540. else Stream.Position := StreamPos;
  3541. end;
  3542. {$ifdef GLB_SUPPORT_PNG_WRITE}
  3543. {$ifdef GLB_LIB_PNG}
  3544. procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
  3545. begin
  3546. TStream(png_get_io_ptr(png)).Write(buffer^, size);
  3547. end;
  3548. {$endif}
  3549. procedure TglBitmap.SavePNG(Stream: TStream);
  3550. {$ifdef GLB_LIB_PNG}
  3551. var
  3552. png: png_structp;
  3553. png_info: png_infop;
  3554. png_rows: array of pByte;
  3555. LineSize: Integer;
  3556. ColorType: Integer;
  3557. Row: Integer;
  3558. begin
  3559. if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
  3560. raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
  3561. if not init_libPNG then
  3562. raise Exception.Create('SavePNG - unable to initialize libPNG.');
  3563. try
  3564. case FInternalFormat of
  3565. ifAlpha, ifLuminance, ifDepth8:
  3566. ColorType := PNG_COLOR_TYPE_GRAY;
  3567. ifLuminanceAlpha:
  3568. ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
  3569. ifBGR8, ifRGB8:
  3570. ColorType := PNG_COLOR_TYPE_RGB;
  3571. ifBGRA8, ifRGBA8:
  3572. ColorType := PNG_COLOR_TYPE_RGBA;
  3573. else
  3574. raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
  3575. end;
  3576. LineSize := Trunc(FormatGetSize(FInternalFormat) * Width);
  3577. // creating array for scanline
  3578. SetLength(png_rows, Height);
  3579. try
  3580. for Row := 0 to Height - 1 do begin
  3581. png_rows[Row] := Data;
  3582. Inc(png_rows[Row], Row * LineSize)
  3583. end;
  3584. // write struct
  3585. png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
  3586. if png = nil then
  3587. raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
  3588. // create png info
  3589. png_info := png_create_info_struct(png);
  3590. if png_info = nil then begin
  3591. png_destroy_write_struct(@png, nil);
  3592. raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
  3593. end;
  3594. // set read callback
  3595. png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil);
  3596. // set compression
  3597. png_set_compression_level(png, 6);
  3598. if InternalFormat in [ifBGR8, ifBGRA8] then
  3599. png_set_bgr(png);
  3600. // setup header
  3601. png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
  3602. // write info
  3603. png_write_info(png, png_info);
  3604. // write image data
  3605. png_write_image(png, @png_rows[0]);
  3606. // write end
  3607. png_write_end(png, png_info);
  3608. // destroy write struct
  3609. png_destroy_write_struct(@png, @png_info);
  3610. finally
  3611. SetLength(png_rows, 0);
  3612. end;
  3613. finally
  3614. quit_libPNG;
  3615. end;
  3616. end;
  3617. {$endif}
  3618. {$ifdef GLB_PNGIMAGE}
  3619. var
  3620. Png: TPNGObject;
  3621. pSource, pDest: pByte;
  3622. X, Y, PixSize: Integer;
  3623. ColorType: Cardinal;
  3624. Alpha: Boolean;
  3625. pTemp: pByte;
  3626. Temp: Byte;
  3627. begin
  3628. if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
  3629. raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
  3630. case FInternalFormat of
  3631. ifAlpha, ifLuminance, ifDepth8:
  3632. begin
  3633. ColorType := COLOR_GRAYSCALE;
  3634. PixSize := 1;
  3635. Alpha := False;
  3636. end;
  3637. ifLuminanceAlpha:
  3638. begin
  3639. ColorType := COLOR_GRAYSCALEALPHA;
  3640. PixSize := 1;
  3641. Alpha := True;
  3642. end;
  3643. ifBGR8, ifRGB8:
  3644. begin
  3645. ColorType := COLOR_RGB;
  3646. PixSize := 3;
  3647. Alpha := False;
  3648. end;
  3649. ifBGRA8, ifRGBA8:
  3650. begin
  3651. ColorType := COLOR_RGBALPHA;
  3652. PixSize := 3;
  3653. Alpha := True
  3654. end;
  3655. else
  3656. raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
  3657. end;
  3658. Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
  3659. try
  3660. // Copy ImageData
  3661. pSource := Data;
  3662. for Y := 0 to Height -1 do begin
  3663. pDest := png.ScanLine[Y];
  3664. for X := 0 to Width -1 do begin
  3665. Move(pSource^, pDest^, PixSize);
  3666. Inc(pDest, PixSize);
  3667. Inc(pSource, PixSize);
  3668. if Alpha then begin
  3669. png.AlphaScanline[Y]^[X] := pSource^;
  3670. Inc(pSource);
  3671. end;
  3672. end;
  3673. // convert RGB line to BGR
  3674. if InternalFormat in [ifRGB8, ifRGBA8] then begin
  3675. pTemp := png.ScanLine[Y];
  3676. for X := 0 to Width -1 do begin
  3677. Temp := pByteArray(pTemp)^[0];
  3678. pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
  3679. pByteArray(pTemp)^[2] := Temp;
  3680. Inc(pTemp, 3);
  3681. end;
  3682. end;
  3683. end;
  3684. // Save to Stream
  3685. Png.CompressionLevel := 6;
  3686. Png.SaveToStream(Stream);
  3687. finally
  3688. FreeAndNil(Png);
  3689. end;
  3690. end;
  3691. {$endif}
  3692. {$endif}
  3693. procedure TglBitmap.SaveDDS(Stream: TStream);
  3694. var
  3695. Header: TDDSHeader;
  3696. Pix: TglBitmapPixelData;
  3697. begin
  3698. if not FormatIsUncompressed(InternalFormat) then
  3699. raise EglBitmapUnsupportedInternalFormat.Create('SaveDDS - ' + UNSUPPORTED_INTERNAL_FORMAT);
  3700. if InternalFormat = ifAlpha then
  3701. FormatPreparePixel(Pix, ifLuminance)
  3702. else
  3703. FormatPreparePixel(Pix, InternalFormat);
  3704. // Generell
  3705. FillChar(Header, SizeOf(Header), 0);
  3706. Header.dwMagic := DDS_MAGIC;
  3707. Header.dwSize := 124;
  3708. Header.dwFlags := DDSD_PITCH or DDSD_CAPS or DDSD_PIXELFORMAT;
  3709. if Width > 0 then begin
  3710. Header.dwWidth := Width;
  3711. Header.dwFlags := Header.dwFlags or DDSD_WIDTH;
  3712. end;
  3713. if Height > 0 then begin
  3714. Header.dwHeight := Height;
  3715. Header.dwFlags := Header.dwFlags or DDSD_HEIGHT;
  3716. end;
  3717. Header.dwPitchOrLinearSize := fRowSize;
  3718. Header.dwMipMapCount := 1;
  3719. // Caps
  3720. Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
  3721. // Pixelformat
  3722. Header.PixelFormat.dwSize := Sizeof(Header.PixelFormat);
  3723. Header.PixelFormat.dwFlags := DDPF_RGB;
  3724. if FormatHasAlpha(InternalFormat) and (InternalFormat <> ifAlpha)
  3725. then Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
  3726. Header.PixelFormat.dwRGBBitCount := Trunc(FormatGetSize(InternalFormat) * 8);
  3727. Header.PixelFormat.dwRBitMask := Pix.PixelDesc.RedRange shl Pix.PixelDesc.RedShift;
  3728. Header.PixelFormat.dwGBitMask := Pix.PixelDesc.GreenRange shl Pix.PixelDesc.GreenShift;
  3729. Header.PixelFormat.dwBBitMask := Pix.PixelDesc.BlueRange shl Pix.PixelDesc.BlueShift;
  3730. Header.PixelFormat.dwAlphaBitMask := Pix.PixelDesc.AlphaRange shl Pix.PixelDesc.AlphaShift;
  3731. // Write
  3732. Stream.Write(Header, SizeOf(Header));
  3733. Stream.Write(Data^, FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat));
  3734. end;
  3735. procedure TglBitmap.SaveTGA(Stream: TStream);
  3736. var
  3737. Header: TTGAHeader;
  3738. Size: Integer;
  3739. pTemp: pByte;
  3740. procedure ConvertData(pTemp: pByte);
  3741. var
  3742. Idx, PixelSize: Integer;
  3743. Temp: byte;
  3744. begin
  3745. PixelSize := fPixelSize;
  3746. for Idx := 1 to Height * Width do begin
  3747. Temp := pByteArray(pTemp)^[2];
  3748. pByteArray(pTemp)^[2] := pByteArray(pTemp)^[0];
  3749. pByteArray(pTemp)^[0] := Temp;
  3750. Inc(pTemp, PixelSize);
  3751. end;
  3752. end;
  3753. begin
  3754. if not (ftTGA in FormatGetSupportedFiles (InternalFormat)) then
  3755. raise EglBitmapUnsupportedInternalFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT);
  3756. FillChar(Header, SizeOf(Header), 0);
  3757. case InternalFormat of
  3758. ifAlpha, ifLuminance, ifDepth8:
  3759. begin
  3760. Header.ImageType := TGA_UNCOMPRESSED_GRAY;
  3761. Header.Bpp := 8;
  3762. end;
  3763. ifLuminanceAlpha:
  3764. begin
  3765. Header.ImageType := TGA_UNCOMPRESSED_GRAY;
  3766. Header.Bpp := 16;
  3767. end;
  3768. ifRGB8, ifBGR8:
  3769. begin
  3770. Header.ImageType := TGA_UNCOMPRESSED_RGB;
  3771. Header.Bpp := 24;
  3772. end;
  3773. ifRGBA8, ifBGRA8:
  3774. begin
  3775. Header.ImageType := TGA_UNCOMPRESSED_RGB;
  3776. Header.Bpp := 32;
  3777. end;
  3778. else
  3779. raise EglBitmapUnsupportedInternalFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT);
  3780. end;
  3781. Header.Width := Width;
  3782. Header.Height := Height;
  3783. Header.ImageDes := $20;
  3784. if FormatHasAlpha(InternalFormat) then
  3785. Header.ImageDes := Header.ImageDes or $08;
  3786. Stream.Write(Header, SizeOf(Header));
  3787. // convert RGB(A) to BGR(A)
  3788. Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat);
  3789. if InternalFormat in [ifRGB8, ifRGBA8] then begin
  3790. GetMem(pTemp, Size);
  3791. end else
  3792. pTemp := Data;
  3793. try
  3794. // convert data
  3795. if InternalFormat in [ifRGB8, ifRGBA8] then begin
  3796. Move(Data^, pTemp^, Size);
  3797. ConvertData(pTemp);
  3798. end;
  3799. // write data
  3800. Stream.Write(pTemp^, Size);
  3801. finally
  3802. // free tempdata
  3803. if InternalFormat in [ifRGB8, ifRGBA8] then
  3804. FreeMem(pTemp);
  3805. end;
  3806. end;
  3807. {$ifdef GLB_SUPPORT_JPEG_WRITE}
  3808. procedure TglBitmap.SaveJPEG(Stream: TStream);
  3809. {$ifdef GLB_LIB_JPEG}
  3810. var
  3811. jpeg: jpeg_compress_struct;
  3812. jpeg_err: jpeg_error_mgr;
  3813. Row: Integer;
  3814. pTemp, pTemp2: pByte;
  3815. procedure CopyRow(pDest, pSource: pByte);
  3816. var
  3817. X: Integer;
  3818. begin
  3819. for X := 0 to Width - 1 do begin
  3820. pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
  3821. pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
  3822. pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
  3823. Inc(pDest, 3);
  3824. Inc(pSource, 3);
  3825. end;
  3826. end;
  3827. begin
  3828. if not (ftJPEG in FormatGetSupportedFiles(InternalFormat)) then
  3829. raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
  3830. if not init_libJPEG then
  3831. raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
  3832. try
  3833. FillChar(jpeg, SizeOf(jpeg_compress_struct), $00);
  3834. FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
  3835. // error managment
  3836. jpeg.err := jpeg_std_error(@jpeg_err);
  3837. jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
  3838. jpeg_err.output_message := glBitmap_libJPEG_output_message;
  3839. // compression struct
  3840. jpeg_create_compress(@jpeg);
  3841. // allocation space for streaming methods
  3842. jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
  3843. // seeting up custom functions
  3844. with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
  3845. pub.init_destination := glBitmap_libJPEG_init_destination;
  3846. pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
  3847. pub.term_destination := glBitmap_libJPEG_term_destination;
  3848. pub.next_output_byte := @DestBuffer[1];
  3849. pub.free_in_buffer := Length(DestBuffer);
  3850. DestStream := Stream;
  3851. end;
  3852. // very important state
  3853. jpeg.global_state := CSTATE_START;
  3854. jpeg.image_width := Width;
  3855. jpeg.image_height := Height;
  3856. case InternalFormat of
  3857. ifAlpha, ifLuminance, ifDepth8:
  3858. begin
  3859. jpeg.input_components := 1;
  3860. jpeg.in_color_space := JCS_GRAYSCALE;
  3861. end;
  3862. ifRGB8, ifBGR8:
  3863. begin
  3864. jpeg.input_components := 3;
  3865. jpeg.in_color_space := JCS_RGB;
  3866. end;
  3867. end;
  3868. // setting defaults
  3869. jpeg_set_defaults(@jpeg);
  3870. // compression quality
  3871. jpeg_set_quality(@jpeg, 95, True);
  3872. // start compression
  3873. jpeg_start_compress(@jpeg, true);
  3874. // write rows
  3875. pTemp := Data;
  3876. // initialing row
  3877. if InternalFormat = ifBGR8 then
  3878. GetMem(pTemp2, fRowSize)
  3879. else
  3880. pTemp2 := pTemp;
  3881. try
  3882. for Row := 0 to jpeg.image_height -1 do begin
  3883. // prepare row
  3884. if InternalFormat = ifBGR8 then
  3885. CopyRow(pTemp2, pTemp)
  3886. else
  3887. pTemp2 := pTemp;
  3888. // write row
  3889. jpeg_write_scanlines(@jpeg, @pTemp2, 1);
  3890. inc(pTemp, fRowSize);
  3891. end;
  3892. finally
  3893. // free memory
  3894. if InternalFormat = ifBGR8 then
  3895. FreeMem(pTemp2);
  3896. end;
  3897. // finish compression
  3898. jpeg_finish_compress(@jpeg);
  3899. // destroy compression
  3900. jpeg_destroy_compress(@jpeg);
  3901. finally
  3902. quit_libJPEG;
  3903. end;
  3904. end;
  3905. {$endif}
  3906. {$ifdef GLB_DELPHI_JPEG}
  3907. var
  3908. Bmp: TBitmap;
  3909. Jpg: TJPEGImage;
  3910. begin
  3911. if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then
  3912. raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
  3913. Bmp := TBitmap.Create;
  3914. try
  3915. Jpg := TJPEGImage.Create;
  3916. try
  3917. AssignToBitmap(Bmp);
  3918. if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
  3919. Jpg.Grayscale := True;
  3920. Jpg.PixelFormat := jf8Bit;
  3921. end;
  3922. Jpg.Assign(Bmp);
  3923. Jpg.SaveToStream(Stream);
  3924. finally
  3925. FreeAndNil(Jpg);
  3926. end;
  3927. finally
  3928. FreeAndNil(Bmp);
  3929. end;
  3930. end;
  3931. {$endif}
  3932. {$endif}
  3933. procedure TglBitmap.SaveBMP(Stream: TStream);
  3934. var
  3935. Header: TBMPHeader;
  3936. Info: TBMPInfo;
  3937. pData, pTemp: pByte;
  3938. PixelFormat: TglBitmapPixelData;
  3939. ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer;
  3940. Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
  3941. PaddingBuff: Cardinal;
  3942. function GetLineWidth : Integer;
  3943. begin
  3944. Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
  3945. end;
  3946. begin
  3947. if not (ftBMP in FormatGetSupportedFiles(InternalFormat)) then
  3948. raise EglBitmapUnsupportedInternalFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT);
  3949. ImageSize := Trunc(Width * Height * FormatGetSize(InternalFormat));
  3950. Header.bfType := BMP_MAGIC;
  3951. Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
  3952. Header.bfReserved1 := 0;
  3953. Header.bfReserved2 := 0;
  3954. Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
  3955. FillChar(Info, SizeOf(Info), 0);
  3956. Info.biSize := SizeOf(Info);
  3957. Info.biWidth := Width;
  3958. Info.biHeight := Height;
  3959. Info.biPlanes := 1;
  3960. Info.biCompression := BMP_COMP_RGB;
  3961. Info.biSizeImage := ImageSize;
  3962. case InternalFormat of
  3963. ifAlpha, ifLuminance, ifDepth8:
  3964. begin
  3965. Info.biBitCount := 8;
  3966. Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
  3967. Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal);
  3968. Info.biClrUsed := 256;
  3969. Info.biClrImportant := 256;
  3970. end;
  3971. ifLuminanceAlpha, ifRGBA4, ifR5G6B5, ifRGB5A1:
  3972. begin
  3973. Info.biBitCount := 16;
  3974. Info.biCompression := BMP_COMP_BITFIELDS;
  3975. end;
  3976. ifBGR8, ifRGB8:
  3977. Info.biBitCount := 24;
  3978. ifBGRA8, ifRGBA8, ifRGB10A2:
  3979. begin
  3980. Info.biBitCount := 32;
  3981. Info.biCompression := BMP_COMP_BITFIELDS;
  3982. end;
  3983. else
  3984. raise EglBitmapUnsupportedInternalFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT);
  3985. end;
  3986. Info.biXPelsPerMeter := 2835;
  3987. Info.biYPelsPerMeter := 2835;
  3988. // prepare bitmasks
  3989. if Info.biCompression = BMP_COMP_BITFIELDS then begin
  3990. Info.biSize := Info.biSize + 4 * SizeOf(Cardinal);
  3991. Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal);
  3992. Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
  3993. FormatPreparePixel(PixelFormat, InternalFormat);
  3994. with PixelFormat.PixelDesc do begin
  3995. RedMask := RedRange shl RedShift;
  3996. GreenMask := GreenRange shl GreenShift;
  3997. BlueMask := BlueRange shl BlueShift;
  3998. AlphaMask := AlphaRange shl AlphaShift;
  3999. end;
  4000. end;
  4001. // headers
  4002. Stream.Write(Header, SizeOf(Header));
  4003. Stream.Write(Info, SizeOf(Info));
  4004. // colortable
  4005. if Info.biBitCount = 8 then begin
  4006. Temp := 0;
  4007. for ColorIdx := Low(Byte) to High(Byte) do begin
  4008. Stream.Write(Temp, 4);
  4009. Temp := Temp + $00010101;
  4010. end;
  4011. end;
  4012. // bitmasks
  4013. if Info.biCompression = BMP_COMP_BITFIELDS then begin
  4014. Stream.Write(RedMask, SizeOf(Cardinal));
  4015. Stream.Write(GreenMask, SizeOf(Cardinal));
  4016. Stream.Write(BlueMask, SizeOf(Cardinal));
  4017. Stream.Write(AlphaMask, SizeOf(Cardinal));
  4018. end;
  4019. // image data
  4020. LineSize := Trunc(Width * FormatGetSize(InternalFormat));
  4021. Padding := GetLineWidth - LineSize;
  4022. PaddingBuff := 0;
  4023. pData := Data;
  4024. Inc(pData, (Height -1) * LineSize);
  4025. // prepare row buffer. But only for RGB because RGBA supports color masks
  4026. // so it's possible to change color within the image.
  4027. if InternalFormat = ifRGB8 then
  4028. GetMem(pTemp, fRowSize)
  4029. else
  4030. pTemp := nil;
  4031. try
  4032. // write image data
  4033. for LineIdx := 0 to Height - 1 do begin
  4034. // preparing row
  4035. if InternalFormat = ifRGB8 then begin
  4036. Move(pData^, pTemp^, fRowSize);
  4037. SwapRGB(pTemp, Width, False);
  4038. end else
  4039. pTemp := pData;
  4040. Stream.Write(pTemp^, LineSize);
  4041. Dec(pData, LineSize);
  4042. if Padding > 0 then
  4043. Stream.Write(PaddingBuff, Padding);
  4044. end;
  4045. finally
  4046. // destroy row buffer
  4047. if InternalFormat = ifRGB8 then
  4048. FreeMem(pTemp);
  4049. end;
  4050. end;
  4051. procedure TglBitmap.Bind(EnableTextureUnit: Boolean);
  4052. begin
  4053. if EnableTextureUnit then
  4054. glEnable(Target);
  4055. if ID > 0 then
  4056. glBindTexture(Target, ID);
  4057. end;
  4058. procedure TglBitmap.Unbind(DisableTextureUnit: Boolean);
  4059. begin
  4060. if DisableTextureUnit then
  4061. glDisable(Target);
  4062. glBindTexture(Target, 0);
  4063. end;
  4064. procedure TglBitmap.GetPixel(const Pos: TglBitmapPixelPosition;
  4065. var Pixel: TglBitmapPixelData);
  4066. begin
  4067. if Assigned (fGetPixelFunc) then
  4068. fGetPixelFunc(Pos, Pixel);
  4069. end;
  4070. procedure TglBitmap.SetPixel (const Pos: TglBitmapPixelPosition;
  4071. const Pixel: TglBitmapPixelData);
  4072. begin
  4073. if Assigned (fSetPixelFunc) then
  4074. fSetPixelFunc(Pos, Pixel);
  4075. end;
  4076. procedure TglBitmap.CreateID;
  4077. begin
  4078. // Generate Texture
  4079. if ID <> 0 then
  4080. glDeleteTextures(1, @ID);
  4081. glGenTextures(1, @ID);
  4082. Bind(False);
  4083. end;
  4084. procedure TglBitmap.SetupParameters(var BuildWithGlu: Boolean);
  4085. begin
  4086. // Set up parameters
  4087. SetWrap(fWrapS, fWrapT, fWrapR);
  4088. SetFilter(fFilterMin, fFilterMag);
  4089. SetAnisotropic(fAnisotropic);
  4090. SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
  4091. // Mip Maps generation Mode
  4092. BuildWithGlu := False;
  4093. if (MipMap = mmMipmap) then begin
  4094. if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
  4095. glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
  4096. else
  4097. BuildWithGlu := True;
  4098. end else
  4099. if (MipMap = mmMipmapGlu) then
  4100. BuildWithGlu := True;
  4101. end;
  4102. procedure TglBitmap.SelectFormat(DataFormat: TglBitmapInternalFormat; var glFormat, glInternalFormat, glType: Cardinal; CanConvertImage: Boolean = True);
  4103. procedure Check12;
  4104. begin
  4105. if not GL_VERSION_1_2 then
  4106. raise EglBitmapUnsupportedInternalFormat.Create('SelectFormat - You need at least OpenGL 1.2 to support these format.');
  4107. end;
  4108. begin
  4109. glType := GL_UNSIGNED_BYTE;
  4110. // selecting Format
  4111. case DataFormat of
  4112. ifAlpha:
  4113. glFormat := GL_ALPHA;
  4114. ifLuminance:
  4115. glFormat := GL_LUMINANCE;
  4116. ifDepth8:
  4117. glFormat := GL_DEPTH_COMPONENT;
  4118. ifLuminanceAlpha:
  4119. glFormat := GL_LUMINANCE_ALPHA;
  4120. ifBGR8:
  4121. begin
  4122. if (GL_VERSION_1_2 or GL_EXT_bgra) then begin
  4123. glFormat := GL_BGR;
  4124. end else begin
  4125. if CanConvertImage then
  4126. ConvertTo(ifRGB8);
  4127. glFormat := GL_RGB;
  4128. end;
  4129. end;
  4130. ifBGRA8:
  4131. begin
  4132. if (GL_VERSION_1_2 or GL_EXT_bgra) then begin
  4133. glFormat := GL_BGRA;
  4134. end else begin
  4135. if CanConvertImage then
  4136. ConvertTo(ifRGBA8);
  4137. glFormat := GL_RGBA;
  4138. end;
  4139. end;
  4140. ifRGB8:
  4141. glFormat := GL_RGB;
  4142. ifRGBA8:
  4143. glFormat := GL_RGBA;
  4144. ifRGBA4:
  4145. begin
  4146. Check12;
  4147. glFormat := GL_BGRA;
  4148. glType := GL_UNSIGNED_SHORT_4_4_4_4_REV;
  4149. end;
  4150. ifRGB5A1:
  4151. begin
  4152. Check12;
  4153. glFormat := GL_BGRA;
  4154. glType := GL_UNSIGNED_SHORT_1_5_5_5_REV;
  4155. end;
  4156. ifRGB10A2:
  4157. begin
  4158. Check12;
  4159. glFormat := GL_BGRA;
  4160. glType := GL_UNSIGNED_INT_2_10_10_10_REV;
  4161. end;
  4162. ifR5G6B5:
  4163. begin
  4164. Check12;
  4165. glFormat := GL_RGB;
  4166. glType := GL_UNSIGNED_SHORT_5_6_5;
  4167. end;
  4168. else
  4169. glFormat := 0;
  4170. end;
  4171. // Selecting InternalFormat
  4172. case DataFormat of
  4173. ifDXT1, ifDXT3, ifDXT5:
  4174. begin
  4175. if GL_EXT_texture_compression_s3tc then begin
  4176. case DataFormat of
  4177. ifDXT1:
  4178. glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
  4179. ifDXT3:
  4180. glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
  4181. ifDXT5:
  4182. glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
  4183. end;
  4184. end else begin
  4185. // Compression isn't supported so convert to RGBA
  4186. if CanConvertImage then
  4187. ConvertTo(ifRGBA8);
  4188. glFormat := GL_RGBA;
  4189. glInternalFormat := GL_RGBA8;
  4190. end;
  4191. end;
  4192. ifAlpha:
  4193. begin
  4194. case Format of
  4195. tf4BitsPerChanel:
  4196. glInternalFormat := GL_ALPHA4;
  4197. tf8BitsPerChanel:
  4198. glInternalFormat := GL_ALPHA8;
  4199. tfCompressed:
  4200. begin
  4201. if (GL_ARB_texture_compression or GL_VERSION_1_3) then
  4202. glInternalFormat := GL_COMPRESSED_ALPHA
  4203. else
  4204. glInternalFormat := GL_ALPHA;
  4205. end;
  4206. else
  4207. glInternalFormat := GL_ALPHA;
  4208. end;
  4209. end;
  4210. ifLuminance:
  4211. begin
  4212. case Format of
  4213. tf4BitsPerChanel:
  4214. glInternalFormat := GL_LUMINANCE4;
  4215. tf8BitsPerChanel:
  4216. glInternalFormat := GL_LUMINANCE8;
  4217. tfCompressed:
  4218. begin
  4219. if (GL_ARB_texture_compression or GL_VERSION_1_3) then
  4220. glInternalFormat := GL_COMPRESSED_LUMINANCE
  4221. else
  4222. glInternalFormat := GL_LUMINANCE;
  4223. end;
  4224. else
  4225. glInternalFormat := GL_LUMINANCE;
  4226. end;
  4227. end;
  4228. ifDepth8:
  4229. begin
  4230. glInternalFormat := GL_DEPTH_COMPONENT;
  4231. end;
  4232. ifLuminanceAlpha:
  4233. begin
  4234. case Format of
  4235. tf4BitsPerChanel:
  4236. glInternalFormat := GL_LUMINANCE4_ALPHA4;
  4237. tf8BitsPerChanel:
  4238. glInternalFormat := GL_LUMINANCE8_ALPHA8;
  4239. tfCompressed:
  4240. begin
  4241. if (GL_ARB_texture_compression or GL_VERSION_1_3) then
  4242. glInternalFormat := GL_COMPRESSED_LUMINANCE_ALPHA
  4243. else
  4244. glInternalFormat := GL_LUMINANCE_ALPHA;
  4245. end;
  4246. else
  4247. glInternalFormat := GL_LUMINANCE_ALPHA;
  4248. end;
  4249. end;
  4250. ifBGR8, ifRGB8:
  4251. begin
  4252. case Format of
  4253. tf4BitsPerChanel:
  4254. glInternalFormat := GL_RGB4;
  4255. tf8BitsPerChanel:
  4256. glInternalFormat := GL_RGB8;
  4257. tfCompressed:
  4258. begin
  4259. if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin
  4260. glInternalFormat := GL_COMPRESSED_RGB
  4261. end else begin
  4262. if (GL_EXT_texture_compression_s3tc) then
  4263. glInternalFormat := GL_COMPRESSED_RGB_S3TC_DXT1_EXT
  4264. else
  4265. glInternalFormat := GL_RGB;
  4266. end;
  4267. end;
  4268. else
  4269. glInternalFormat := GL_RGB;
  4270. end;
  4271. end;
  4272. ifBGRA8, ifRGBA8, ifRGBA4, ifRGB5A1, ifRGB10A2, ifR5G6B5:
  4273. begin
  4274. case Format of
  4275. tf4BitsPerChanel:
  4276. glInternalFormat := GL_RGBA4;
  4277. tf8BitsPerChanel:
  4278. glInternalFormat := GL_RGBA8;
  4279. tfCompressed:
  4280. begin
  4281. if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin
  4282. glInternalFormat := GL_COMPRESSED_RGBA
  4283. end else begin
  4284. if (GL_EXT_texture_compression_s3tc) then
  4285. glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
  4286. else
  4287. glInternalFormat := GL_RGBA;
  4288. end;
  4289. end;
  4290. else
  4291. glInternalFormat := GL_RGBA;
  4292. end;
  4293. end;
  4294. end;
  4295. end;
  4296. function TglBitmap.FlipHorz: Boolean;
  4297. begin
  4298. Result := False;
  4299. end;
  4300. function TglBitmap.FlipVert: Boolean;
  4301. begin
  4302. Result := False;
  4303. end;
  4304. procedure TglBitmap.FreeData;
  4305. begin
  4306. SetDataPointer(nil, ifEmpty);
  4307. end;
  4308. procedure glBitmapFillWithColorFunc(var FuncRec: TglBitmapFunctionRec);
  4309. type
  4310. PglBitmapPixelData = ^TglBitmapPixelData;
  4311. begin
  4312. with FuncRec do begin
  4313. Dest.Red := PglBitmapPixelData(CustomData)^.Red;
  4314. Dest.Green := PglBitmapPixelData(CustomData)^.Green;
  4315. Dest.Blue := PglBitmapPixelData(CustomData)^.Blue;
  4316. Dest.Alpha := PglBitmapPixelData(CustomData)^.Alpha;
  4317. end;
  4318. end;
  4319. procedure TglBitmap.FillWithColor(Red, Green, Blue, Alpha: Byte);
  4320. begin
  4321. FillWithColorFloat(Red / $FF, Green / $FF, Blue / $FF, Alpha / $FF);
  4322. end;
  4323. procedure TglBitmap.FillWithColorFloat(Red, Green, Blue, Alpha: Single);
  4324. var
  4325. PixelData: TglBitmapPixelData;
  4326. begin
  4327. FormatPreparePixel(PixelData, InternalFormat);
  4328. PixelData.Red := Max(0, Min(PixelData.PixelDesc.RedRange, Trunc(PixelData.PixelDesc.RedRange * Red)));
  4329. PixelData.Green := Max(0, Min(PixelData.PixelDesc.GreenRange, Trunc(PixelData.PixelDesc.GreenRange * Green)));
  4330. PixelData.Blue := Max(0, Min(PixelData.PixelDesc.BlueRange, Trunc(PixelData.PixelDesc.BlueRange * Blue)));
  4331. PixelData.Alpha := Max(0, Min(PixelData.PixelDesc.AlphaRange, Trunc(PixelData.PixelDesc.AlphaRange * Alpha)));
  4332. AddFunc(glBitmapFillWithColorFunc, False, @PixelData);
  4333. end;
  4334. procedure TglBitmap.FillWithColorRange(Red, Green, Blue, Alpha: Cardinal);
  4335. var
  4336. PixelData: TglBitmapPixelData;
  4337. begin
  4338. FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
  4339. FillWithColorFloat(
  4340. Red / PixelData.PixelDesc.RedRange,
  4341. Green / PixelData.PixelDesc.GreenRange,
  4342. Blue / PixelData.PixelDesc.BlueRange,
  4343. Alpha / PixelData.PixelDesc.AlphaRange);
  4344. end;
  4345. procedure TglBitmap.SetAnisotropic(const Value: Integer);
  4346. var
  4347. MaxAniso: Integer;
  4348. begin
  4349. fAnisotropic := Value;
  4350. if (ID > 0) then begin
  4351. if GL_EXT_texture_filter_anisotropic then begin
  4352. if fAnisotropic > 0 then begin
  4353. Bind(False);
  4354. glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAniso);
  4355. if Value > MaxAniso then
  4356. fAnisotropic := MaxAniso;
  4357. glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
  4358. end;
  4359. end else begin
  4360. fAnisotropic := 0;
  4361. end;
  4362. end;
  4363. end;
  4364. procedure TglBitmap.SetInternalFormat(const Value: TglBitmapInternalFormat);
  4365. begin
  4366. if InternalFormat <> Value then begin
  4367. if FormatGetSize(Value) <> FormatGetSize(InternalFormat) then
  4368. raise EglBitmapUnsupportedInternalFormat.Create('SetInternalFormat - ' + UNSUPPORTED_INTERNAL_FORMAT);
  4369. // Update whatever
  4370. SetDataPointer(Data, Value);
  4371. end;
  4372. end;
  4373. function TglBitmap.AddFunc(Func: TglBitmapFunction; CreateTemp: Boolean;
  4374. CustomData: Pointer): boolean;
  4375. begin
  4376. Result := AddFunc(Self, Func, CreateTemp, InternalFormat, CustomData);
  4377. end;
  4378. function TglBitmap.AddFunc(Source: TglBitmap; Func: TglBitmapFunction;
  4379. CreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer): boolean;
  4380. var
  4381. pDest, NewImage, pSource: pByte;
  4382. TempHeight, TempWidth: Integer;
  4383. MapFunc: TglBitmapMapFunc;
  4384. UnMapFunc: TglBitmapUnMapFunc;
  4385. FuncRec: TglBitmapFunctionRec;
  4386. begin
  4387. Assert(Assigned(Data));
  4388. Assert(Assigned(Source));
  4389. Assert(Assigned(Source.Data));
  4390. Result := False;
  4391. if Assigned (Source.Data) and FormatIsUncompressed(Format) and
  4392. ((Source.Height > 0) or (Source.Width > 0)) then begin
  4393. // inkompatible Formats so CreateTemp
  4394. if FormatGetSize(Format) <> FormatGetSize(InternalFormat) then
  4395. CreateTemp := True;
  4396. // Values
  4397. TempHeight := Max(1, Source.Height);
  4398. TempWidth := Max(1, Source.Width);
  4399. FuncRec.Sender := Self;
  4400. FuncRec.CustomData := CustomData;
  4401. NewImage := nil;
  4402. if CreateTemp then begin
  4403. GetMem(NewImage, Trunc(FormatGetSize(Format) * TempHeight * TempWidth));
  4404. pDest := NewImage;
  4405. end
  4406. else pDest := Data;
  4407. try
  4408. // Mapping
  4409. MapFunc := FormatGetMapFunc(Format);
  4410. FormatPreparePixel(FuncRec.Dest, Format);
  4411. FormatPreparePixel(FuncRec.Source, Source.InternalFormat);
  4412. FuncRec.Size := Source.Dimension;
  4413. FuncRec.Position.Fields := FuncRec.Size.Fields;
  4414. if FormatIsUncompressed(Source.InternalFormat) then begin
  4415. // Uncompressed Images
  4416. pSource := Source.Data;
  4417. UnMapFunc := FormatGetUnMapFunc(Source.InternalFormat);
  4418. FuncRec.Position.Y := 0;
  4419. while FuncRec.Position.Y < TempHeight do begin
  4420. FuncRec.Position.X := 0;
  4421. while FuncRec.Position.X < TempWidth do begin
  4422. // Get Data
  4423. UnMapFunc(pSource, FuncRec.Source);
  4424. // Func
  4425. Func(FuncRec);
  4426. // Set Data
  4427. MapFunc(FuncRec.Dest, pDest);
  4428. Inc(FuncRec.Position.X);
  4429. end;
  4430. Inc(FuncRec.Position.Y);
  4431. end;
  4432. end else begin
  4433. // Compressed Images
  4434. FuncRec.Position.Y := 0;
  4435. while FuncRec.Position.Y < TempHeight do begin
  4436. FuncRec.Position.X := 0;
  4437. while FuncRec.Position.X < TempWidth do begin
  4438. // Get Data
  4439. fGetPixelFunc(FuncRec.Position, FuncRec.Source);
  4440. // Func
  4441. Func(FuncRec);
  4442. // Set Data
  4443. MapFunc(FuncRec.Dest, pDest);
  4444. Inc(FuncRec.Position.X);
  4445. end;
  4446. Inc(FuncRec.Position.Y);
  4447. end;
  4448. end;
  4449. // Updating Image or InternalFormat
  4450. if CreateTemp then
  4451. SetDataPointer(NewImage, Format)
  4452. else
  4453. if Format <> InternalFormat then
  4454. SetInternalFormat(Format);
  4455. Result := True;
  4456. except
  4457. if CreateTemp
  4458. then FreeMem(NewImage);
  4459. raise;
  4460. end;
  4461. end;
  4462. end;
  4463. procedure glBitmapConvertCopyFunc(var FuncRec: TglBitmapFunctionRec);
  4464. begin
  4465. with FuncRec do begin
  4466. if Source.PixelDesc.RedRange > 0 then
  4467. Dest.Red := Source.Red;
  4468. if Source.PixelDesc.GreenRange > 0 then
  4469. Dest.Green := Source.Green;
  4470. if Source.PixelDesc.BlueRange > 0 then
  4471. Dest.Blue := Source.Blue;
  4472. if Source.PixelDesc.AlphaRange > 0 then
  4473. Dest.Alpha := Source.Alpha;
  4474. end;
  4475. end;
  4476. procedure glBitmapConvertCalculateRGBAFunc(var FuncRec: TglBitmapFunctionRec);
  4477. begin
  4478. with FuncRec do begin
  4479. if Source.PixelDesc.RedRange > 0 then
  4480. Dest.Red := Round(Dest.PixelDesc.RedRange * Source.Red / Source.PixelDesc.RedRange);
  4481. if Source.PixelDesc.GreenRange > 0 then
  4482. Dest.Green := Round(Dest.PixelDesc.GreenRange * Source.Green / Source.PixelDesc.GreenRange);
  4483. if Source.PixelDesc.BlueRange > 0 then
  4484. Dest.Blue := Round(Dest.PixelDesc.BlueRange * Source.Blue / Source.PixelDesc.BlueRange);
  4485. if Source.PixelDesc.AlphaRange > 0 then
  4486. Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Source.Alpha / Source.PixelDesc.AlphaRange);
  4487. end;
  4488. end;
  4489. procedure glBitmapConvertShiftRGBAFunc(var FuncRec: TglBitmapFunctionRec);
  4490. begin
  4491. with FuncRec do
  4492. with TglBitmapPixelDesc(CustomData^) do begin
  4493. if Source.PixelDesc.RedRange > 0 then
  4494. Dest.Red := Source.Red shr RedShift;
  4495. if Source.PixelDesc.GreenRange > 0 then
  4496. Dest.Green := Source.Green shr GreenShift;
  4497. if Source.PixelDesc.BlueRange > 0 then
  4498. Dest.Blue := Source.Blue shr BlueShift;
  4499. if Source.PixelDesc.AlphaRange > 0 then
  4500. Dest.Alpha := Source.Alpha shr AlphaShift;
  4501. end;
  4502. end;
  4503. function TglBitmap.ConvertTo(NewFormat: TglBitmapInternalFormat): boolean;
  4504. var
  4505. Source, Dest: TglBitmapPixelData;
  4506. PixelDesc: TglBitmapPixelDesc;
  4507. function CopyDirect: Boolean;
  4508. begin
  4509. Result :=
  4510. ((Source.PixelDesc.RedRange = Dest.PixelDesc.RedRange) or (Source.PixelDesc.RedRange = 0) or (Dest.PixelDesc.RedRange = 0)) and
  4511. ((Source.PixelDesc.GreenRange = Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and
  4512. ((Source.PixelDesc.BlueRange = Dest.PixelDesc.BlueRange) or (Source.PixelDesc.BlueRange = 0) or (Dest.PixelDesc.BlueRange = 0)) and
  4513. ((Source.PixelDesc.AlphaRange = Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0));
  4514. end;
  4515. function CanShift: Boolean;
  4516. begin
  4517. Result :=
  4518. ((Source.PixelDesc.RedRange >= Dest.PixelDesc.RedRange ) or (Source.PixelDesc.RedRange = 0) or (Dest.PixelDesc.RedRange = 0)) and
  4519. ((Source.PixelDesc.GreenRange >= Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and
  4520. ((Source.PixelDesc.BlueRange >= Dest.PixelDesc.BlueRange ) or (Source.PixelDesc.BlueRange = 0) or (Dest.PixelDesc.BlueRange = 0)) and
  4521. ((Source.PixelDesc.AlphaRange >= Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0));
  4522. end;
  4523. function GetShift(Source, Dest: Cardinal) : ShortInt;
  4524. begin
  4525. Result := 0;
  4526. while (Source > Dest) and (Source > 0) do begin
  4527. Inc(Result);
  4528. Source := Source shr 1;
  4529. end;
  4530. end;
  4531. begin
  4532. if NewFormat <> InternalFormat then begin
  4533. FormatPreparePixel(Source, InternalFormat);
  4534. FormatPreparePixel(Dest, NewFormat);
  4535. if CopyDirect then
  4536. Result := AddFunc(Self, glBitmapConvertCopyFunc, False, NewFormat)
  4537. else
  4538. if CanShift then begin
  4539. PixelDesc.RedShift := GetShift(Source.PixelDesc.RedRange, Dest.PixelDesc.RedRange);
  4540. PixelDesc.GreenShift := GetShift(Source.PixelDesc.GreenRange, Dest.PixelDesc.GreenRange);
  4541. PixelDesc.BlueShift := GetShift(Source.PixelDesc.BlueRange, Dest.PixelDesc.BlueRange);
  4542. PixelDesc.AlphaShift := GetShift(Source.PixelDesc.AlphaRange, Dest.PixelDesc.AlphaRange);
  4543. Result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, False, NewFormat, @PixelDesc);
  4544. end
  4545. else Result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, False, NewFormat);
  4546. end
  4547. else Result := True;
  4548. end;
  4549. function TglBitmap.RemoveAlpha: Boolean;
  4550. begin
  4551. Result := False;
  4552. if (Assigned(Data)) then begin
  4553. if not (FormatIsUncompressed(InternalFormat) or FormatHasAlpha(InternalFormat)) then
  4554. raise EglBitmapUnsupportedInternalFormat.Create('RemoveAlpha - ' + UNSUPPORTED_INTERNAL_FORMAT);
  4555. Result := ConvertTo(FormatGetWithoutAlpha(InternalFormat));
  4556. end;
  4557. end;
  4558. function TglBitmap.AddAlphaFromFunc(Func: TglBitmapFunction; CustomData: Pointer): boolean;
  4559. begin
  4560. if not FormatIsUncompressed(InternalFormat) then
  4561. raise EglBitmapUnsupportedInternalFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_INTERNAL_FORMAT);
  4562. Result := AddFunc(Self, Func, False, FormatGetWithAlpha(InternalFormat), CustomData);
  4563. end;
  4564. function TglBitmap.GetHeight: Integer;
  4565. begin
  4566. if ffY in fDimension.Fields then
  4567. Result := fDimension.Y
  4568. else
  4569. Result := -1;
  4570. end;
  4571. function TglBitmap.GetWidth: Integer;
  4572. begin
  4573. if ffX in fDimension.Fields then
  4574. Result := fDimension.X
  4575. else
  4576. Result := -1;
  4577. end;
  4578. function TglBitmap.GetFileHeight: Integer;
  4579. begin
  4580. Result := Max(1, Height);
  4581. end;
  4582. function TglBitmap.GetFileWidth: Integer;
  4583. begin
  4584. Result := Max(1, Width);
  4585. end;
  4586. procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
  4587. var
  4588. Temp: Single;
  4589. begin
  4590. with FuncRec do begin
  4591. Temp :=
  4592. Source.Red / Source.PixelDesc.RedRange * 0.3 +
  4593. Source.Green / Source.PixelDesc.GreenRange * 0.59 +
  4594. Source.Blue / Source.PixelDesc.BlueRange * 0.11;
  4595. Dest.Alpha := Round (Dest.PixelDesc.AlphaRange * Temp);
  4596. end;
  4597. end;
  4598. function TglBitmap.AddAlphaFromglBitmap(glBitmap: TglBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean;
  4599. var
  4600. pDest, pDest2, pSource: pByte;
  4601. TempHeight, TempWidth: Integer;
  4602. MapFunc: TglBitmapMapFunc;
  4603. DestUnMapFunc, UnMapFunc: TglBitmapUnMapFunc;
  4604. FuncRec: TglBitmapFunctionRec;
  4605. begin
  4606. Result := False;
  4607. assert(Assigned(Data));
  4608. assert(Assigned(glBitmap));
  4609. assert(Assigned(glBitmap.Data));
  4610. if ((glBitmap.Width = Width) and (glBitmap.Height = Height)) then begin
  4611. // Convert to Data with Alpha
  4612. Result := ConvertTo(FormatGetWithAlpha(FormatGetUncompressed(InternalFormat)));
  4613. if not Assigned(Func) then
  4614. Func := glBitmapAlphaFunc;
  4615. // Values
  4616. TempHeight := glBitmap.FileHeight;
  4617. TempWidth := glBitmap.FileWidth;
  4618. FuncRec.Sender := Self;
  4619. FuncRec.CustomData := CustomData;
  4620. pDest := Data;
  4621. pDest2 := Data;
  4622. pSource := glBitmap.Data;
  4623. // Mapping
  4624. FormatPreparePixel(FuncRec.Dest, InternalFormat);
  4625. FormatPreparePixel(FuncRec.Source, glBitmap.InternalFormat);
  4626. MapFunc := FormatGetMapFunc(InternalFormat);
  4627. DestUnMapFunc := FormatGetUnMapFunc(InternalFormat);
  4628. UnMapFunc := FormatGetUnMapFunc(glBitmap.InternalFormat);
  4629. FuncRec.Size := Dimension;
  4630. FuncRec.Position.Fields := FuncRec.Size.Fields;
  4631. FuncRec.Position.Y := 0;
  4632. while FuncRec.Position.Y < TempHeight do begin
  4633. FuncRec.Position.X := 0;
  4634. while FuncRec.Position.X < TempWidth do begin
  4635. // Get Data
  4636. UnMapFunc(pSource, FuncRec.Source);
  4637. DestUnMapFunc(pDest2, FuncRec.Dest);
  4638. // Func
  4639. Func(FuncRec);
  4640. // Set Data
  4641. MapFunc(FuncRec.Dest, pDest);
  4642. Inc(FuncRec.Position.X);
  4643. end;
  4644. Inc(FuncRec.Position.Y);
  4645. end;
  4646. end;
  4647. end;
  4648. procedure TglBitmap.SetBorderColor(Red, Green, Blue, Alpha: Single);
  4649. begin
  4650. fBorderColor[0] := Red;
  4651. fBorderColor[1] := Green;
  4652. fBorderColor[2] := Blue;
  4653. fBorderColor[3] := Alpha;
  4654. if ID > 0 then begin
  4655. Bind (False);
  4656. glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
  4657. end;
  4658. end;
  4659. { TglBitmap2D }
  4660. procedure TglBitmap2D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
  4661. var
  4662. Idx, LineWidth: Integer;
  4663. begin
  4664. inherited;
  4665. // Format
  4666. if FormatIsUncompressed(Format) then begin
  4667. fUnmapFunc := FormatGetUnMapFunc(Format);
  4668. fGetPixelFunc := GetPixel2DUnmap;
  4669. fMapFunc := FormatGetMapFunc(Format);
  4670. fSetPixelFunc := SetPixel2DUnmap;
  4671. // Assigning Data
  4672. if Assigned(Data) then begin
  4673. SetLength(fLines, GetHeight);
  4674. LineWidth := Trunc(GetWidth * FormatGetSize(InternalFormat));
  4675. for Idx := 0 to GetHeight -1 do begin
  4676. fLines[Idx] := Data;
  4677. Inc(fLines[Idx], Idx * LineWidth);
  4678. end;
  4679. end
  4680. else SetLength(fLines, 0);
  4681. end else begin
  4682. SetLength(fLines, 0);
  4683. fSetPixelFunc := nil;
  4684. case Format of
  4685. ifDXT1:
  4686. fGetPixelFunc := GetPixel2DDXT1;
  4687. ifDXT3:
  4688. fGetPixelFunc := GetPixel2DDXT3;
  4689. ifDXT5:
  4690. fGetPixelFunc := GetPixel2DDXT5;
  4691. else
  4692. fGetPixelFunc := nil;
  4693. end;
  4694. end;
  4695. end;
  4696. procedure TglBitmap2D.GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
  4697. type
  4698. PDXT1Chunk = ^TDXT1Chunk;
  4699. TDXT1Chunk = packed record
  4700. Color1: WORD;
  4701. Color2: WORD;
  4702. Pixels: array [0..3] of byte;
  4703. end;
  4704. var
  4705. BasePtr: pDXT1Chunk;
  4706. PixPos: Integer;
  4707. Colors: array [0..3] of TRGBQuad;
  4708. begin
  4709. BasePtr := pDXT1Chunk(pData);
  4710. PixPos := BasePtr^.Pixels[relY] shr (relX * 2) and $3;
  4711. if PixPos in [0, 2, 3] then begin
  4712. Colors[0].rgbRed := BasePtr^.Color1 and $F800 shr 8;
  4713. Colors[0].rgbGreen := BasePtr^.Color1 and $07E0 shr 3;
  4714. Colors[0].rgbBlue := BasePtr^.Color1 and $001F shl 3;
  4715. Colors[0].rgbReserved := 255;
  4716. end;
  4717. if PixPos in [1, 2, 3] then begin
  4718. Colors[1].rgbRed := BasePtr^.Color2 and $F800 shr 8;
  4719. Colors[1].rgbGreen := BasePtr^.Color2 and $07E0 shr 3;
  4720. Colors[1].rgbBlue := BasePtr^.Color2 and $001F shl 3;
  4721. Colors[1].rgbReserved := 255;
  4722. end;
  4723. if PixPos = 2 then begin
  4724. Colors[2].rgbRed := (Colors[0].rgbRed * 67 + Colors[1].rgbRed * 33) div 100;
  4725. Colors[2].rgbGreen := (Colors[0].rgbGreen * 67 + Colors[1].rgbGreen * 33) div 100;
  4726. Colors[2].rgbBlue := (Colors[0].rgbBlue * 67 + Colors[1].rgbBlue * 33) div 100;
  4727. Colors[2].rgbReserved := 255;
  4728. end;
  4729. if PixPos = 3 then begin
  4730. Colors[3].rgbRed := (Colors[0].rgbRed * 33 + Colors[1].rgbRed * 67) div 100;
  4731. Colors[3].rgbGreen := (Colors[0].rgbGreen * 33 + Colors[1].rgbGreen * 67) div 100;
  4732. Colors[3].rgbBlue := (Colors[0].rgbBlue * 33 + Colors[1].rgbBlue * 67) div 100;
  4733. if BasePtr^.Color1 > BasePtr^.Color2 then
  4734. Colors[3].rgbReserved := 255
  4735. else
  4736. Colors[3].rgbReserved := 0;
  4737. end;
  4738. Pixel.Red := Colors[PixPos].rgbRed;
  4739. Pixel.Green := Colors[PixPos].rgbGreen;
  4740. Pixel.Blue := Colors[PixPos].rgbBlue;
  4741. Pixel.Alpha := Colors[PixPos].rgbReserved;
  4742. end;
  4743. procedure TglBitmap2D.GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
  4744. var
  4745. BasePtr: pByte;
  4746. PosX, PosY: Integer;
  4747. begin
  4748. inherited;
  4749. if (Pos.Y <= Height) and (Pos.X <= Width) then begin
  4750. PosX := Pos.X div 4;
  4751. PosY := Pos.Y div 4;
  4752. BasePtr := Data;
  4753. Inc(BasePtr, (PosY * Width div 4 + PosX) * 8);
  4754. GetDXTColorBlock(BasePtr, Pos.X - PosX * 4, Pos.Y - PosY * 4, Pixel);
  4755. end;
  4756. end;
  4757. procedure TglBitmap2D.GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
  4758. type
  4759. PDXT3AlphaChunk = ^TDXT3AlphaChunk;
  4760. TDXT3AlphaChunk = array [0..3] of WORD;
  4761. var
  4762. ColorPtr: pByte;
  4763. AlphaPtr: PDXT3AlphaChunk;
  4764. PosX, PosY, relX, relY: Integer;
  4765. begin
  4766. inherited;
  4767. if (Pos.Y <= Height) and (Pos.X <= Width) then begin
  4768. PosX := Pos.X div 4;
  4769. PosY := Pos.Y div 4;
  4770. relX := Pos.X - PosX * 4;
  4771. relY := Pos.Y - PosY * 4;
  4772. // get color value
  4773. AlphaPtr := PDXT3AlphaChunk(Data);
  4774. Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2);
  4775. ColorPtr := pByte(AlphaPtr);
  4776. Inc(ColorPtr, 8);
  4777. GetDXTColorBlock(ColorPtr, relX, relY, Pixel);
  4778. // extracting alpha
  4779. Pixel.Alpha := AlphaPtr^[relY] shr (4 * relX) and $0F shl 4;
  4780. end;
  4781. end;
  4782. procedure TglBitmap2D.GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
  4783. var
  4784. ColorPtr: pByte;
  4785. AlphaPtr: PInt64;
  4786. PixPos, PosX, PosY, relX, relY: Integer;
  4787. Alpha0, Alpha1: Byte;
  4788. begin
  4789. inherited;
  4790. if (Pos.Y <= Height) and (Pos.X <= Width) then begin
  4791. PosX := Pos.X div 4;
  4792. PosY := Pos.Y div 4;
  4793. relX := Pos.X - PosX * 4;
  4794. relY := Pos.Y - PosY * 4;
  4795. // get color value
  4796. AlphaPtr := PInt64(Data);
  4797. Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2);
  4798. ColorPtr := pByte(AlphaPtr);
  4799. Inc(ColorPtr, 8);
  4800. GetDXTColorBlock(ColorPtr, relX, relY, Pixel);
  4801. // extracting alpha
  4802. Alpha0 := AlphaPtr^ and $FF;
  4803. Alpha1 := AlphaPtr^ shr 8 and $FF;
  4804. PixPos := AlphaPtr^ shr (16 + (relY * 4 + relX) * 3) and $07;
  4805. // use alpha 0
  4806. if PixPos = 0 then begin
  4807. Pixel.Alpha := Alpha0;
  4808. end else
  4809. // use alpha 1
  4810. if PixPos = 1 then begin
  4811. Pixel.Alpha := Alpha1;
  4812. end else
  4813. // alpha interpolate 7 Steps
  4814. if Alpha0 > Alpha1 then begin
  4815. Pixel.Alpha := ((8 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 7;
  4816. end else
  4817. // alpha is 100% transparent or not transparent
  4818. if PixPos >= 6 then begin
  4819. if PixPos = 6 then
  4820. Pixel.Alpha := 0
  4821. else
  4822. Pixel.Alpha := 255;
  4823. end else
  4824. // alpha interpolate 5 Steps
  4825. begin
  4826. Pixel.Alpha := ((6 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 5;
  4827. end;
  4828. end;
  4829. end;
  4830. procedure TglBitmap2D.GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
  4831. var
  4832. pTemp: pByte;
  4833. begin
  4834. pTemp := fLines[Pos.Y];
  4835. Inc(pTemp, Pos.X * fPixelSize);
  4836. fUnmapFunc(pTemp, Pixel);
  4837. end;
  4838. procedure TglBitmap2D.SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
  4839. var
  4840. pTemp: pByte;
  4841. begin
  4842. pTemp := fLines[Pos.Y];
  4843. Inc(pTemp, Pos.X * fPixelSize);
  4844. fMapFunc(Pixel, pTemp);
  4845. end;
  4846. function TglBitmap2D.FlipHorz: Boolean;
  4847. var
  4848. Col, Row: Integer;
  4849. pTempDest, pDest, pSource: pByte;
  4850. ImgSize: Integer;
  4851. begin
  4852. Result := Inherited FlipHorz;
  4853. if Assigned(Data) then begin
  4854. pSource := Data;
  4855. ImgSize := Height * fRowSize;
  4856. GetMem(pDest, ImgSize);
  4857. try
  4858. pTempDest := pDest;
  4859. Dec(pTempDest, fRowSize + fPixelSize);
  4860. for Row := 0 to Height -1 do begin
  4861. Inc(pTempDest, fRowSize * 2);
  4862. for Col := 0 to Width -1 do begin
  4863. Move(pSource^, pTempDest^, fPixelSize);
  4864. Inc(pSource, fPixelSize);
  4865. Dec(pTempDest, fPixelSize);
  4866. end;
  4867. end;
  4868. SetDataPointer(pDest, InternalFormat);
  4869. Result := True;
  4870. except
  4871. FreeMem(pDest);
  4872. raise;
  4873. end;
  4874. end;
  4875. end;
  4876. function TglBitmap2D.FlipVert: Boolean;
  4877. var
  4878. Row: Integer;
  4879. pTempDest, pDest, pSource: pByte;
  4880. begin
  4881. Result := Inherited FlipVert;
  4882. if Assigned(Data) then begin
  4883. pSource := Data;
  4884. GetMem(pDest, Height * fRowSize);
  4885. try
  4886. pTempDest := pDest;
  4887. Inc(pTempDest, Width * (Height -1) * fPixelSize);
  4888. for Row := 0 to Height -1 do begin
  4889. Move(pSource^, pTempDest^, fRowSize);
  4890. Dec(pTempDest, fRowSize);
  4891. Inc(pSource, fRowSize);
  4892. end;
  4893. SetDataPointer(pDest, InternalFormat);
  4894. Result := True;
  4895. except
  4896. FreeMem(pDest);
  4897. raise;
  4898. end;
  4899. end;
  4900. end;
  4901. procedure TglBitmap2D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
  4902. begin
  4903. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  4904. // Upload data
  4905. if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
  4906. glCompressedTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Trunc(Width * Height * FormatGetSize(Self.InternalFormat)), Data)
  4907. else
  4908. if BuildWithGlu then
  4909. gluBuild2DMipmaps(Target, InternalFormat, Width, Height, Format, Typ, Data)
  4910. else
  4911. glTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Format, Typ, Data);
  4912. // Freigeben
  4913. if (FreeDataAfterGenTexture) then
  4914. FreeData;
  4915. end;
  4916. procedure TglBitmap2D.GenTexture(TestTextureSize: Boolean);
  4917. var
  4918. BuildWithGlu, PotTex, TexRec: Boolean;
  4919. glFormat, glInternalFormat, glType: Cardinal;
  4920. TexSize: Integer;
  4921. begin
  4922. if Assigned(Data) then begin
  4923. // Check Texture Size
  4924. if (TestTextureSize) then begin
  4925. glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
  4926. if ((Height > TexSize) or (Width > TexSize)) then
  4927. raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
  4928. PotTex := IsPowerOfTwo (Height) and IsPowerOfTwo (Width);
  4929. TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
  4930. (Target = GL_TEXTURE_RECTANGLE_ARB);
  4931. if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
  4932. raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
  4933. end;
  4934. CreateId;
  4935. SetupParameters(BuildWithGlu);
  4936. SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
  4937. UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
  4938. // Infos sammeln
  4939. glAreTexturesResident(1, @ID, @fIsResident);
  4940. end;
  4941. end;
  4942. procedure TglBitmap2D.AfterConstruction;
  4943. begin
  4944. inherited;
  4945. Target := GL_TEXTURE_2D;
  4946. end;
  4947. type
  4948. TMatrixItem = record
  4949. X, Y: Integer;
  4950. W: Single;
  4951. end;
  4952. PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec;
  4953. TglBitmapToNormalMapRec = Record
  4954. Scale: Single;
  4955. Heights: array of Single;
  4956. MatrixU : array of TMatrixItem;
  4957. MatrixV : array of TMatrixItem;
  4958. end;
  4959. const
  4960. oneover255 = 1 / 255;
  4961. procedure glBitmapToNormalMapPrepareFunc (var FuncRec: TglBitmapFunctionRec);
  4962. var
  4963. Val: Single;
  4964. begin
  4965. with FuncRec do begin
  4966. Val := Source.Red * 0.3 + Source.Green * 0.59 + Source.Blue * 0.11;
  4967. PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Val * oneover255;
  4968. end;
  4969. end;
  4970. procedure glBitmapToNormalMapPrepareAlphaFunc (var FuncRec: TglBitmapFunctionRec);
  4971. begin
  4972. with FuncRec do
  4973. PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Source.Alpha * oneover255;
  4974. end;
  4975. procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
  4976. type
  4977. TVec = Array[0..2] of Single;
  4978. var
  4979. Idx: Integer;
  4980. du, dv: Double;
  4981. Len: Single;
  4982. Vec: TVec;
  4983. function GetHeight(X, Y: Integer): Single;
  4984. begin
  4985. with FuncRec do begin
  4986. X := Max(0, Min(Size.X -1, X));
  4987. Y := Max(0, Min(Size.Y -1, Y));
  4988. Result := PglBitmapToNormalMapRec (CustomData)^.Heights[Y * Size.X + X];
  4989. end;
  4990. end;
  4991. begin
  4992. with FuncRec do begin
  4993. with PglBitmapToNormalMapRec (CustomData)^ do begin
  4994. du := 0;
  4995. for Idx := Low(MatrixU) to High(MatrixU) do
  4996. du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
  4997. dv := 0;
  4998. for Idx := Low(MatrixU) to High(MatrixU) do
  4999. dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W;
  5000. Vec[0] := -du * Scale;
  5001. Vec[1] := -dv * Scale;
  5002. Vec[2] := 1;
  5003. end;
  5004. // Normalize
  5005. Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
  5006. if Len <> 0 then begin
  5007. Vec[0] := Vec[0] * Len;
  5008. Vec[1] := Vec[1] * Len;
  5009. Vec[2] := Vec[2] * Len;
  5010. end;
  5011. // Farbe zuweisem
  5012. Dest.Red := Trunc((Vec[0] + 1) * 127.5);
  5013. Dest.Green := Trunc((Vec[1] + 1) * 127.5);
  5014. Dest.Blue := Trunc((Vec[2] + 1) * 127.5);
  5015. end;
  5016. end;
  5017. procedure TglBitmap2D.ToNormalMap(Func: TglBitmapNormalMapFunc; Scale: Single; UseAlpha: Boolean);
  5018. var
  5019. Rec: TglBitmapToNormalMapRec;
  5020. procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single);
  5021. begin
  5022. if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin
  5023. Matrix[Index].X := X;
  5024. Matrix[Index].Y := Y;
  5025. Matrix[Index].W := W;
  5026. end;
  5027. end;
  5028. begin
  5029. if not FormatIsUncompressed(InternalFormat) then
  5030. raise EglBitmapUnsupportedInternalFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_INTERNAL_FORMAT);
  5031. if Scale > 100 then
  5032. Rec.Scale := 100
  5033. else
  5034. if Scale < -100 then
  5035. Rec.Scale := -100
  5036. else
  5037. Rec.Scale := Scale;
  5038. SetLength(Rec.Heights, Width * Height);
  5039. try
  5040. case Func of
  5041. nm4Samples:
  5042. begin
  5043. SetLength(Rec.MatrixU, 2);
  5044. SetEntry(Rec.MatrixU, 0, -1, 0, -0.5);
  5045. SetEntry(Rec.MatrixU, 1, 1, 0, 0.5);
  5046. SetLength(Rec.MatrixV, 2);
  5047. SetEntry(Rec.MatrixV, 0, 0, 1, 0.5);
  5048. SetEntry(Rec.MatrixV, 1, 0, -1, -0.5);
  5049. end;
  5050. nmSobel:
  5051. begin
  5052. SetLength(Rec.MatrixU, 6);
  5053. SetEntry(Rec.MatrixU, 0, -1, 1, -1.0);
  5054. SetEntry(Rec.MatrixU, 1, -1, 0, -2.0);
  5055. SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
  5056. SetEntry(Rec.MatrixU, 3, 1, 1, 1.0);
  5057. SetEntry(Rec.MatrixU, 4, 1, 0, 2.0);
  5058. SetEntry(Rec.MatrixU, 5, 1, -1, 1.0);
  5059. SetLength(Rec.MatrixV, 6);
  5060. SetEntry(Rec.MatrixV, 0, -1, 1, 1.0);
  5061. SetEntry(Rec.MatrixV, 1, 0, 1, 2.0);
  5062. SetEntry(Rec.MatrixV, 2, 1, 1, 1.0);
  5063. SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
  5064. SetEntry(Rec.MatrixV, 4, 0, -1, -2.0);
  5065. SetEntry(Rec.MatrixV, 5, 1, -1, -1.0);
  5066. end;
  5067. nm3x3:
  5068. begin
  5069. SetLength(Rec.MatrixU, 6);
  5070. SetEntry(Rec.MatrixU, 0, -1, 1, -1/6);
  5071. SetEntry(Rec.MatrixU, 1, -1, 0, -1/6);
  5072. SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
  5073. SetEntry(Rec.MatrixU, 3, 1, 1, 1/6);
  5074. SetEntry(Rec.MatrixU, 4, 1, 0, 1/6);
  5075. SetEntry(Rec.MatrixU, 5, 1, -1, 1/6);
  5076. SetLength(Rec.MatrixV, 6);
  5077. SetEntry(Rec.MatrixV, 0, -1, 1, 1/6);
  5078. SetEntry(Rec.MatrixV, 1, 0, 1, 1/6);
  5079. SetEntry(Rec.MatrixV, 2, 1, 1, 1/6);
  5080. SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
  5081. SetEntry(Rec.MatrixV, 4, 0, -1, -1/6);
  5082. SetEntry(Rec.MatrixV, 5, 1, -1, -1/6);
  5083. end;
  5084. nm5x5:
  5085. begin
  5086. SetLength(Rec.MatrixU, 20);
  5087. SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16);
  5088. SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10);
  5089. SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10);
  5090. SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16);
  5091. SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10);
  5092. SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8);
  5093. SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8);
  5094. SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10);
  5095. SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8);
  5096. SetEntry(Rec.MatrixU, 9, -1, 0, -0.5);
  5097. SetEntry(Rec.MatrixU, 10, 1, 0, 0.5);
  5098. SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8);
  5099. SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
  5100. SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8);
  5101. SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8);
  5102. SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10);
  5103. SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
  5104. SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
  5105. SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10);
  5106. SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16);
  5107. SetLength(Rec.MatrixV, 20);
  5108. SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16);
  5109. SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10);
  5110. SetEntry(Rec.MatrixV, 2, 0, 2, 0.25);
  5111. SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10);
  5112. SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16);
  5113. SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10);
  5114. SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8);
  5115. SetEntry(Rec.MatrixV, 7, 0, 1, 0.5);
  5116. SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8);
  5117. SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16);
  5118. SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
  5119. SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8);
  5120. SetEntry(Rec.MatrixV, 12, 0, -1, -0.5);
  5121. SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8);
  5122. SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10);
  5123. SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
  5124. SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
  5125. SetEntry(Rec.MatrixV, 17, 0, -2, -0.25);
  5126. SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10);
  5127. SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16);
  5128. end;
  5129. end;
  5130. // Daten Sammeln
  5131. if UseAlpha and FormatHasAlpha(InternalFormat) then
  5132. AddFunc(glBitmapToNormalMapPrepareAlphaFunc, False, @Rec)
  5133. else
  5134. AddFunc(glBitmapToNormalMapPrepareFunc, False, @Rec);
  5135. // Neues Bild berechnen
  5136. AddFunc(glBitmapToNormalMapFunc, False, @Rec);
  5137. finally
  5138. SetLength(Rec.Heights, 0);
  5139. end;
  5140. end;
  5141. procedure TglBitmap2D.GrabScreen(Top, Left, Right, Bottom: Integer; Format: TglBitmapInternalFormat);
  5142. var
  5143. Temp: pByte;
  5144. Size: Integer;
  5145. glFormat, glInternalFormat, glType: Cardinal;
  5146. begin
  5147. if not FormatIsUncompressed(Format) then
  5148. raise EglBitmapUnsupportedInternalFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_INTERNAL_FORMAT);
  5149. // Only to select Formats
  5150. SelectFormat(Format, glFormat, glInternalFormat, glType, False);
  5151. Size := FormatGetImageSize(glBitmapPosition(Right - Left, Bottom - Top), Format);
  5152. GetMem(Temp, Size);
  5153. try
  5154. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  5155. glReadPixels(Left, Top, Right - Left, Bottom - Top, glFormat, glType, Temp);
  5156. // Set Data
  5157. SetDataPointer(Temp, Format, Right - Left, Bottom - Top);
  5158. // Flip
  5159. FlipVert;
  5160. except
  5161. FreeMem(Temp);
  5162. raise;
  5163. end;
  5164. end;
  5165. procedure TglBitmap2D.GetDataFromTexture;
  5166. var
  5167. Temp: pByte;
  5168. TempWidth, TempHeight, RedSize, GreenSize, BlueSize, AlphaSize, LumSize: Integer;
  5169. TempType, TempIntFormat: Cardinal;
  5170. IntFormat: TglBitmapInternalFormat;
  5171. begin
  5172. Bind;
  5173. // Request Data
  5174. glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
  5175. glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
  5176. glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
  5177. glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_RED_SIZE, @RedSize);
  5178. glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_GREEN_SIZE, @GreenSize);
  5179. glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_BLUE_SIZE, @BlueSize);
  5180. glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_ALPHA_SIZE, @AlphaSize);
  5181. glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_LUMINANCE_SIZE, @LumSize);
  5182. // Get glBitmapInternalFormat from TempIntFormat
  5183. TempType := GL_UNSIGNED_BYTE;
  5184. case TempIntFormat of
  5185. GL_ALPHA:
  5186. IntFormat := ifAlpha;
  5187. GL_LUMINANCE:
  5188. IntFormat := ifLuminance;
  5189. GL_LUMINANCE_ALPHA:
  5190. IntFormat := ifLuminanceAlpha;
  5191. GL_RGB4:
  5192. begin
  5193. IntFormat := ifR5G6B5;
  5194. TempIntFormat := GL_RGB;
  5195. TempType := GL_UNSIGNED_SHORT_5_6_5;
  5196. end;
  5197. GL_RGB, GL_RGB8:
  5198. IntFormat := ifRGB8;
  5199. GL_RGBA, GL_RGBA4, GL_RGBA8:
  5200. begin
  5201. if (RedSize = 4) and (BlueSize = 4) and (GreenSize = 4) and (AlphaSize = 4) then begin
  5202. IntFormat := ifRGBA4;
  5203. TempIntFormat := GL_BGRA;
  5204. TempType := GL_UNSIGNED_SHORT_4_4_4_4_REV;
  5205. end else
  5206. if (RedSize = 5) and (BlueSize = 5) and (GreenSize = 5) and (AlphaSize = 1) then begin
  5207. IntFormat := ifRGB5A1;
  5208. TempIntFormat := GL_BGRA;
  5209. TempType := GL_UNSIGNED_SHORT_1_5_5_5_REV;
  5210. end else begin
  5211. IntFormat := ifRGBA8;
  5212. end;
  5213. end;
  5214. GL_BGR:
  5215. IntFormat := ifBGR8;
  5216. GL_BGRA:
  5217. IntFormat := ifBGRA8;
  5218. GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
  5219. IntFormat := ifDXT1;
  5220. GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  5221. IntFormat := ifDXT1;
  5222. GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
  5223. IntFormat := ifDXT3;
  5224. GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
  5225. IntFormat := ifDXT5;
  5226. else
  5227. IntFormat := ifEmpty;
  5228. end;
  5229. // Getting data from OpenGL
  5230. GetMem(Temp, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
  5231. try
  5232. if FormatIsCompressed(IntFormat) and (GL_VERSION_1_3 or GL_ARB_texture_compression) then
  5233. glGetCompressedTexImage(Target, 0, Temp)
  5234. else
  5235. glGetTexImage(Target, 0, TempIntFormat, TempType, Temp);
  5236. SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
  5237. except
  5238. FreeMem(Temp);
  5239. raise;
  5240. end;
  5241. end;
  5242. function TglBitmap2D.GetScanline(Index: Integer): Pointer;
  5243. begin
  5244. if (Index >= Low(fLines)) and (Index <= High(fLines)) then
  5245. Result := fLines[Index]
  5246. else
  5247. Result := nil;
  5248. end;
  5249. { TglBitmap1D }
  5250. procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
  5251. var
  5252. pTemp: pByte;
  5253. Size: Integer;
  5254. begin
  5255. if Height > 1 then begin
  5256. // extract first line of the data
  5257. Size := FormatGetImageSize(glBitmapPosition(Width), Format);
  5258. GetMem(pTemp, Size);
  5259. Move(Data^, pTemp^, Size);
  5260. FreeMem(Data);
  5261. end else
  5262. pTemp := Data;
  5263. // set data pointer
  5264. inherited SetDataPointer(pTemp, Format, Width);
  5265. if FormatIsUncompressed(Format) then begin
  5266. fUnmapFunc := FormatGetUnMapFunc(Format);
  5267. fGetPixelFunc := GetPixel1DUnmap;
  5268. end;
  5269. end;
  5270. procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
  5271. var
  5272. pTemp: pByte;
  5273. begin
  5274. pTemp := Data;
  5275. Inc(pTemp, Pos.X * fPixelSize);
  5276. fUnmapFunc(pTemp, Pixel);
  5277. end;
  5278. function TglBitmap1D.FlipHorz: Boolean;
  5279. var
  5280. Col: Integer;
  5281. pTempDest, pDest, pSource: pByte;
  5282. begin
  5283. Result := Inherited FlipHorz;
  5284. if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin
  5285. pSource := Data;
  5286. GetMem(pDest, fRowSize);
  5287. try
  5288. pTempDest := pDest;
  5289. Inc(pTempDest, fRowSize);
  5290. for Col := 0 to Width -1 do begin
  5291. Move(pSource^, pTempDest^, fPixelSize);
  5292. Inc(pSource, fPixelSize);
  5293. Dec(pTempDest, fPixelSize);
  5294. end;
  5295. SetDataPointer(pDest, InternalFormat);
  5296. Result := True;
  5297. finally
  5298. FreeMem(pDest);
  5299. end;
  5300. end;
  5301. end;
  5302. procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
  5303. begin
  5304. // Upload data
  5305. if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
  5306. glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data)
  5307. else
  5308. // Upload data
  5309. if BuildWithGlu then
  5310. gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data)
  5311. else
  5312. glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data);
  5313. // Freigeben
  5314. if (FreeDataAfterGenTexture) then
  5315. FreeData;
  5316. end;
  5317. procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean);
  5318. var
  5319. BuildWithGlu, TexRec: Boolean;
  5320. glFormat, glInternalFormat, glType: Cardinal;
  5321. TexSize: Integer;
  5322. begin
  5323. if Assigned(Data) then begin
  5324. // Check Texture Size
  5325. if (TestTextureSize) then begin
  5326. glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
  5327. if (Width > TexSize) then
  5328. raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
  5329. TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
  5330. (Target = GL_TEXTURE_RECTANGLE_ARB);
  5331. if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
  5332. raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.');
  5333. end;
  5334. CreateId;
  5335. SetupParameters(BuildWithGlu);
  5336. SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
  5337. UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
  5338. // Infos sammeln
  5339. glAreTexturesResident(1, @ID, @fIsResident);
  5340. end;
  5341. end;
  5342. procedure TglBitmap1D.AfterConstruction;
  5343. begin
  5344. inherited;
  5345. Target := GL_TEXTURE_1D;
  5346. end;
  5347. { TglBitmapCubeMap }
  5348. procedure TglBitmapCubeMap.AfterConstruction;
  5349. begin
  5350. inherited;
  5351. if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then
  5352. raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.');
  5353. SetWrap; // set all to GL_CLAMP_TO_EDGE
  5354. Target := GL_TEXTURE_CUBE_MAP;
  5355. fGenMode := GL_REFLECTION_MAP;
  5356. end;
  5357. procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean);
  5358. begin
  5359. inherited Bind (EnableTextureUnit);
  5360. if EnableTexCoordsGen then begin
  5361. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode);
  5362. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode);
  5363. glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode);
  5364. glEnable(GL_TEXTURE_GEN_S);
  5365. glEnable(GL_TEXTURE_GEN_T);
  5366. glEnable(GL_TEXTURE_GEN_R);
  5367. end;
  5368. end;
  5369. procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean);
  5370. var
  5371. glFormat, glInternalFormat, glType: Cardinal;
  5372. BuildWithGlu: Boolean;
  5373. TexSize: Integer;
  5374. begin
  5375. // Check Texture Size
  5376. if (TestTextureSize) then begin
  5377. glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize);
  5378. if ((Height > TexSize) or (Width > TexSize)) then
  5379. raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.');
  5380. if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then
  5381. raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.');
  5382. end;
  5383. // create Texture
  5384. if ID = 0 then begin
  5385. CreateID;
  5386. SetupParameters(BuildWithGlu);
  5387. end;
  5388. SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
  5389. UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu);
  5390. end;
  5391. procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean);
  5392. begin
  5393. Assert(False, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
  5394. end;
  5395. procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen,
  5396. DisableTextureUnit: Boolean);
  5397. begin
  5398. inherited Unbind (DisableTextureUnit);
  5399. if DisableTexCoordsGen then begin
  5400. glDisable(GL_TEXTURE_GEN_S);
  5401. glDisable(GL_TEXTURE_GEN_T);
  5402. glDisable(GL_TEXTURE_GEN_R);
  5403. end;
  5404. end;
  5405. { TglBitmapNormalMap }
  5406. type
  5407. TVec = Array[0..2] of Single;
  5408. TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
  5409. PglBitmapNormalMapRec = ^TglBitmapNormalMapRec;
  5410. TglBitmapNormalMapRec = record
  5411. HalfSize : Integer;
  5412. Func: TglBitmapNormalMapGetVectorFunc;
  5413. end;
  5414. procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
  5415. begin
  5416. Vec[0] := HalfSize;
  5417. Vec[1] := - (Position.Y + 0.5 - HalfSize);
  5418. Vec[2] := - (Position.X + 0.5 - HalfSize);
  5419. end;
  5420. procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
  5421. begin
  5422. Vec[0] := - HalfSize;
  5423. Vec[1] := - (Position.Y + 0.5 - HalfSize);
  5424. Vec[2] := Position.X + 0.5 - HalfSize;
  5425. end;
  5426. procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
  5427. begin
  5428. Vec[0] := Position.X + 0.5 - HalfSize;
  5429. Vec[1] := HalfSize;
  5430. Vec[2] := Position.Y + 0.5 - HalfSize;
  5431. end;
  5432. procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
  5433. begin
  5434. Vec[0] := Position.X + 0.5 - HalfSize;
  5435. Vec[1] := - HalfSize;
  5436. Vec[2] := - (Position.Y + 0.5 - HalfSize);
  5437. end;
  5438. procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
  5439. begin
  5440. Vec[0] := Position.X + 0.5 - HalfSize;
  5441. Vec[1] := - (Position.Y + 0.5 - HalfSize);
  5442. Vec[2] := HalfSize;
  5443. end;
  5444. procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer);
  5445. begin
  5446. Vec[0] := - (Position.X + 0.5 - HalfSize);
  5447. Vec[1] := - (Position.Y + 0.5 - HalfSize);
  5448. Vec[2] := - HalfSize;
  5449. end;
  5450. procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec);
  5451. var
  5452. Vec : TVec;
  5453. Len: Single;
  5454. begin
  5455. with FuncRec do begin
  5456. with PglBitmapNormalMapRec (CustomData)^ do begin
  5457. Func(Vec, Position, HalfSize);
  5458. // Normalize
  5459. Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2]));
  5460. if Len <> 0 then begin
  5461. Vec[0] := Vec[0] * Len;
  5462. Vec[1] := Vec[1] * Len;
  5463. Vec[2] := Vec[2] * Len;
  5464. end;
  5465. // Scale Vector and AddVectro
  5466. Vec[0] := Vec[0] * 0.5 + 0.5;
  5467. Vec[1] := Vec[1] * 0.5 + 0.5;
  5468. Vec[2] := Vec[2] * 0.5 + 0.5;
  5469. end;
  5470. // Set Color
  5471. Dest.Red := Round(Vec[0] * 255);
  5472. Dest.Green := Round(Vec[1] * 255);
  5473. Dest.Blue := Round(Vec[2] * 255);
  5474. end;
  5475. end;
  5476. procedure TglBitmapNormalMap.AfterConstruction;
  5477. begin
  5478. inherited;
  5479. fGenMode := GL_NORMAL_MAP;
  5480. end;
  5481. procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer;
  5482. TestTextureSize: Boolean);
  5483. var
  5484. Rec: TglBitmapNormalMapRec;
  5485. SizeRec: TglBitmapPixelPosition;
  5486. begin
  5487. Rec.HalfSize := Size div 2;
  5488. FreeDataAfterGenTexture := False;
  5489. SizeRec.Fields := [ffX, ffY];
  5490. SizeRec.X := Size;
  5491. SizeRec.Y := Size;
  5492. // Positive X
  5493. Rec.Func := glBitmapNormalMapPosX;
  5494. LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
  5495. GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize);
  5496. // Negative X
  5497. Rec.Func := glBitmapNormalMapNegX;
  5498. LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
  5499. GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize);
  5500. // Positive Y
  5501. Rec.Func := glBitmapNormalMapPosY;
  5502. LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
  5503. GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize);
  5504. // Negative Y
  5505. Rec.Func := glBitmapNormalMapNegY;
  5506. LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
  5507. GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize);
  5508. // Positive Z
  5509. Rec.Func := glBitmapNormalMapPosZ;
  5510. LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
  5511. GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize);
  5512. // Negative Z
  5513. Rec.Func := glBitmapNormalMapNegZ;
  5514. LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
  5515. GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize);
  5516. end;
  5517. initialization
  5518. glBitmapSetDefaultFormat(tfDefault);
  5519. glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
  5520. glBitmapSetDefaultWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
  5521. glBitmapSetDefaultFreeDataAfterGenTexture(True);
  5522. glBitmapSetDefaultDeleteTextureOnFree(True);
  5523. finalization
  5524. end.